1
0
forked from 0ad/0ad

Upgraded console (text wrap, help text), cinematic stuff

This was SVN commit r4065.
This commit is contained in:
pyrolink 2006-07-06 03:17:44 +00:00
parent 66306b553a
commit a95c72d0c1
19 changed files with 757 additions and 430 deletions

View File

@ -0,0 +1,176 @@
This is a function reference for scripters and modders.
entity = an object which represents a unit in the game. Each entity has its own set of functions and attributes.
handle = each entity has a number assigned to it that the engine uses as its "ID".
===============================================================================
Class: Output
WriteLog(...) - accepts any number of arguments of any type. All parameters are converted to strings. Output is NORMAL style log.
===============================================================================
Class: Entity
getEntityByHandle( int handle ) - returns the entity with the specified handle.
getEntityTemplateName( string name ) - returns the entity template object that has the specified name.
issueCommand( entity(s), int order_type, args[0], args[1]) - this will create a command, or order, for an entity or group of entities. This entity(s) is specified in the first parameter. order_type should be one of the net messages listed in the "net message order" section. args is an array that contains the data necessary for the order. For example, if it is a location message such as NMT_GOTO, args[0] should be the x coordinate of the destination and args[1] should be the y coordinate.
createEntityFormation( entities, string name ) - creates a formation of type "name" out of the units in "entities".
removeFromFormation( entity(s) ) - removes the entity(s) from their formation. It is required that if it is a group, they are all in the same formation.
lockEntityFormation( entity, bool lock ) - If lock is true, the formation "entity" is in will be locked. Otherwise, it will be unlocked.
isFormationLocked( entity ) -returns true if the entity's formation is locked, otherwise false.
startPlacing( string name ) - Activates the building placement cursor for placing a building. "name" is the name of the entity to place. Returns true on sucess
===============================================================================
Class: Events
AddGlobalHandler( string event_name, function handler ) - Registers a global handler for the specified DOM event. function handler can be a fragment or function. Returns true on success, else false.
RemoveGlobalHandler( string event_name, function handler ) - Removes a global handler. function handler can be a fragment or function. Returns true success.
===============================================================================
Class Timer:
setTimeout( code, int time ) - time is a delay in milliseconds. When this time has elapsed, "code" is executed once. Code can be a fragment or function
Example: setTimeout( console.write("1 second passed"), 1000 ); Returns the ID of the timer (int).
setIntervel( code, int time ) - nearly the same as setTimeout(), but "code" is executed every "time" milliseconds instead of once after a single delay.
cancelIntervel() - causes all functions registered with setInterval to no longer be called.
cancelTimer(int ID) - causes the timer or interval with this ID to longer be called.
====================================================
Class GameSetup:
createServer() - creates and returns a network server object
createClient() – creates and returns a client server object
startGame() – begins the process of starting the game. Returns true on success. –may be changed soon
endGame() – immediately ends the game
===============================================================================
Class Internationalization:
loadLanguage( string language ) – replaces the current langauge with “language”.
getLanguageID() - returns the name of the current language [string].
===============================================================================
Class GUI:
getGUIGlobal() - returns the "global" object associated with the current GUI.
===============================================================================
Class Misc. Engine:
getFPS() - returns the frame rate of the game [int].
exitProgram() - causes the game to exit.
changeCursor(string cursor) - changes the cursor to [string]. Cursors are stored in "art\textures\cursors" and "cursor" is the basename of the texture.
_lodbias(float sharpness) - changes the sharpness of textures (to "sharpness).
setCameraTarget(CVector3D position) - move the camera to look at "position". Returns true on success.
v3dist( CVector3D a, CVector3D b ) - returns the distance between vectors a and b [float].
isPaused() - returns true if the game is paused (else false).
setPaused(bool pause) - if true, the game is paused, else unpaused.
getGameTime() - returns the amount of time elapsed since the start of the game.
===============================================================================
Class water:
setWaterHeight( float height ) - changes the height of the water to "height".
getWaterHeight() - returns the height of the water plane [float].
setWaterColor( float r, float g, float b ) - sets the color of the water plane to the specified components.
setWaterMaxAlpha( float max ) - sets the maximum alpha value (when the water is at WaterFullDepth or deeper)
setWaterFullDepth( float depth ) - sets WaterFullDepth to "depth"-lower values result in water becoming opaque faster as the water gets deeper.
setAlphaWaterOffset( float offset ) - sets the water alpha offset (added to tweak water alpha near the shore).
toggleWater() - toggles the rendering of water.
===============================================================================
Net message types:
NMT_Goto
NMT_Patrol
NMT_AddWaypoint
NMT_Generic
NMT_Produce
NMT_PlaceObject
NMT_Run
NMT_NotifyRequest
NMT_FormationGoto
NMT_FormationGeneric
Notification codes:
NOTIFY_NONE
NOTIFY_GOTO
NOTIFY_RUN
NOTIFY_FOLLOW - combination of goto and run
NOTIFY_ATTACK
NOTIFY_DAMAGE
NOTIFY_COMBAT - combination of attack and damage
NOTIFY_ESCORT - combination of combat and follow
NOTIFY_GATHER
NOTIFY_IDLE
NOTIFY_ORDER_CHANGE
NOITFY_ALL - combination of all except order_change
Order codes:
ORDER_NONE
ORDER_GOTO
ORDER_RUN
ORDER_PATROL
ORDER_GENERIC
ORDER_PRODUCE
ORDER_START_CONSTRUCTION
===============================================================================
Entity Member functions:
registerDamage(entity inflictor) - Called when this entity is damaged. inflictor is the attacking entity. Updates the flank penalty.
registerOrderChange(entity) - Used to update flank penalty. Called when entity changes orders
getAttackDirections() - returns number of directions this entit yis being attacked from
findSector(int divs, float angle, float maxAngle, bool negative) - Finds the sector that "angle" is in. divs is the number of sectors, maxAngle is the angle of the arc to check for, negative is whether or not angles are from 0-range or -range/2-range/2
toString() - Get this entity's tag
getSpawnPoint() - returns vector object of position for entity spawn point
hasRallyPoint() - returns true if this entity has a rally point
setRallyPoint() - sets rally point to cursor's position
addAura(string name, float radius, int tickrate, function handler) - name is the name of hte aura, radius is its encompassing size, tickrate is something, and handler is the function to be called for events
removeAura(string name) - removes the aura "name" from this entity's auras
setActionParams(int id, float minRange, float maxRange, int speed, string animation) - id is the order code, min range and max range determine from how near or far the order can be performed, speed specifies how fast the order will happen, and animation is the name of the animation
triggerRun() - will trigger run next frame (this is the correct way to do it)
setRun() - set this entity running immediately
isRunning() - returns true of this entity is currently running
getRunState() - returns true if this entity will run when in range (or already in range)
requestNotification(entity, int notifyCode, bool destroyOld, bool scriptDestroy) - requests notification for an order type. entity is the target to be listened to, notifyCode is the notification ID, and destroyOld,if true, will destroy all previous requests except those being destroyed by the script. scriptDestroy determines whether or not the engine can destroy this request. Setting scriptDestroy to true means you must destroy it yourself later in the script. It is not recommended because doing so from multiple targets may override each other, so use sparingly and with caution.
forceCheckListeners(int notifyCode, entity ) - If necessary, listeners can be checked manually. notifyCode is the notification to check for, entity is the entity whose order data will be used.
getCurrentRequest() - returns the ID of the notification this entity is currently listening for
destroyAllNotifiers() - this entity will no longer listen to notifications
destroyNotifier(entity target) - the entity will no longer listen to notifications from entity. Use this to destroy notify requests manually
isInFormation() - returns true if this entity is in a formation
order(int order, arg1, arg2, <notification>) - Issues an order to this entity. order is the ID of the order being given, arg1 and arg2 are the parameters needed to complete the order (note that not necessarily all require two, so give the correct amount). The last parameter is optional and indicates whether this order is coming from a notification (if not specified, it will no longer listen to its notifiers)
orderSingle( see order() ) - will clear other orders and replace with this one
orderQueued( see order() ) - queues this order
isIdle() - returns true if this entity is idle
hasClass(string name) - returns true if this entity is part of class name
terminateOrder(bool destroyAll) - if destroyAll is true, all orders are terminated, otherwise the first current order
getHeight() - returns this entity's position.y

View File

@ -909,7 +909,7 @@ function entityEventNotification( evt )
//This is used to adjust the flank penalty (we're no longer being attacked).
if ( this.getCurrentRequest() == NOTIFY_ORDER_CHANGE )
{
this.registerOrderChange();
this.registerOrderChange( evt.target );
destroyNotifier( evt.target );
return;
}
@ -1088,6 +1088,12 @@ function entityEventTargetChanged( evt )
evt.secondaryCursor = "action-build";
}
}
//Rally point
else if ( this.building )
{
evt.defaultOrder = -1;
evt.defaultCursor = "cursor-rally";
}
}

Binary file not shown.

View File

@ -14,20 +14,18 @@
#include "lib/res/file/vfs.h"
#include "lib/res/mem.h"
CCinemaPath::CCinemaPath(CCinemaData data)
{
m_TotalDuration = data.m_TotalDuration;
m_TotalRotation = data.m_TotalRotation;
m_GrowthCount = data.m_GrowthCount;
m_Growth = data.m_Growth;
m_Switch = data.m_Switch;
CCinemaPath::CCinemaPath(const CCinemaData& data, const TNSpline& spline)
: CCinemaData(data), TNSpline(spline)
{
DistStylePtr = &CCinemaPath::EaseDefault;
DistModePtr = &CCinemaPath::EaseIn;
}
void CCinemaPath::DrawSpline(CVector4D RGBA, int smoothness)
{
if (GetNodeCount() < 3 || DistModePtr == NULL)
if (NodeCount < 3 || DistModePtr == NULL)
return;
float start = m_Spline.MaxDistance / smoothness;
float start = MaxDistance / smoothness;
CVector3D tmp;
float time=0;
@ -37,8 +35,8 @@ void CCinemaPath::DrawSpline(CVector4D RGBA, int smoothness)
for (int i=0; i<smoothness; i++)
{
//Find distorted time
time = (this->*DistModePtr)(start*i / m_Spline.MaxDistance);
tmp = m_Spline.GetPosition(time);
time = (this->*DistModePtr)(start*i / MaxDistance);
tmp = GetPosition(time);
glVertex3f( tmp.X, tmp.Y, tmp.Z );
}
glEnd();
@ -47,9 +45,9 @@ void CCinemaPath::DrawSpline(CVector4D RGBA, int smoothness)
glPointSize(6.0f);
//Draw spline endpoints
glBegin(GL_POINTS);
tmp = m_Spline.GetPosition(0);
tmp = GetPosition(0);
glVertex3f( tmp.X, tmp.Y, tmp.Z );
tmp = m_Spline.GetPosition(1);
tmp = GetPosition(1);
glVertex3f( tmp.X, tmp.Y, tmp.Z );
glEnd();
glPointSize(1.0f);
@ -63,7 +61,7 @@ void CCinemaPath::MoveToPointAt(float t, const CVector3D &startRotation)
Cam->m_Orientation.RotateY(fmodf(rot.Y, 360.0f));
Cam->m_Orientation.RotateZ(fmodf(rot.Z, 360.0f));
CVector3D pos = m_Spline.GetPosition(t);
CVector3D pos = GetPosition(t);
Cam->m_Orientation.Translate(pos);
}
@ -145,14 +143,12 @@ float CCinemaPath::EaseSine(float t)
//-------CinemaTrack functions------
//AddPath-For building tracks from loaded file
void CCinemaTrack::AddPath(CCinemaData data, TNSpline &spline)
void CCinemaTrack::AddPath(CCinemaData& data, TNSpline& spline)
{
CCinemaPath path(data);
CCinemaPath path(data, spline);
path.m_TimeElapsed=0;
path.SetSpline(spline);
path.m_TotalDuration = path.GetDuration();
path.UpdateSpline();
path.BuildSpline();
m_Paths.push_back(path);
std::vector<CCinemaPath>::iterator SetTemp;
SetTemp=m_Paths.end() - 1;
@ -198,45 +194,101 @@ void CCinemaTrack::AddPath(CCinemaData data, TNSpline &spline)
debug_printf("Cinematic mode not found for %d !", data.m_Style);
break;
}
UpdateDuration();
}
void CCinemaTrack::UpdateDuration()
{
m_TotalDuration=0;
for ( std::vector<CCinemaPath>::iterator it=m_Paths.begin(); it!=m_Paths.end(); it++ )
{
m_TotalDuration += it->MaxDistance;
}
}
bool CCinemaTrack::Validate()
{
if (m_CPA->m_TimeElapsed >= m_CPA->m_TotalDuration)
if ( m_CPA->m_TimeElapsed > 0.f )
return ValidateForward();
else
return ValidateRewind();
}
bool CCinemaTrack::ValidateRewind()
{
if (m_CPA->m_TimeElapsed < 0)
{
if (m_CPA == m_Paths.end() - 1)
if (m_CPA == m_Paths.begin())
{
return false;
}
//Make sure it's within limits of track
//Make sure it's within limits of path
else
{
float Pos = m_CPA->m_TimeElapsed - m_CPA->m_TotalDuration;
m_CPA++;
float Pos=m_CPA->m_TimeElapsed;
m_CPA--;
while (1)
{
if (Pos > m_CPA->m_TotalDuration)
if (m_CPA->GetDuration() + Pos < 0)
{
if (m_CPA == m_Paths.end() -1)
if (m_CPA == m_Paths.begin())
{
m_CPA->m_TimeElapsed = m_CPA->MaxDistance;
m_CPA->MoveToPointAt(0.0f, m_StartRotation );
return false;
}
Pos -= m_CPA->m_TotalDuration;
m_CPA++;
}
Pos+=m_CPA->GetDuration();
m_CPA->m_TimeElapsed=0;
m_CPA--;
}
else
{
m_CPA->m_TimeElapsed+=Pos;
break;
}
} //while
}
} //main if statement
return true;
}
} //inside limits
}
return true;
}
bool CCinemaTrack::ValidateForward()
{
if (m_CPA->m_TimeElapsed >= m_CPA->MaxDistance)
{
if (m_CPA == m_Paths.end() - 1)
{
return false;
}
//Make sure it's within limits of path
else
{
float Pos = m_CPA->m_TimeElapsed - m_CPA->MaxDistance;
m_CPA++;
while (1)
{
if (Pos > m_CPA->MaxDistance)
{
if (m_CPA == m_Paths.end() -1)
{
m_CPA->m_TimeElapsed = m_CPA->MaxDistance;
m_CPA->MoveToPointAt(1.0f, m_StartRotation );
return false;
}
Pos -= m_CPA->MaxDistance;
m_CPA->m_TimeElapsed = m_CPA->MaxDistance;
m_CPA++;
}
else
{
m_CPA->m_TimeElapsed+=Pos;
break;
}
}
} //inside limits of path
}
return true;
}
bool CCinemaTrack::Play(float DeltaTime)
{
if (m_CPA->m_TimeElapsed == 0)
@ -253,24 +305,39 @@ bool CCinemaTrack::Play(float DeltaTime)
}
}
//m_CPA->ResetRotation(m_CPA->m_TimeElapsed / m_CPA->m_TotalDuration);
m_CPA->m_TimeElapsed += DeltaTime;
m_CPA->m_TimeElapsed += m_TimeScale*DeltaTime;
m_AbsoluteTime += m_TimeScale*DeltaTime;
if (!Validate())
{
m_CPA->MoveToPointAt(1, m_StartRotation);
return false;
}
m_CPA->MoveToPointAt(m_CPA->m_TimeElapsed / m_CPA->m_TotalDuration, m_StartRotation);
m_CPA->MoveToPointAt( m_CPA->GetElapsedTime() / m_CPA->GetDuration(), m_StartRotation);
return true;
}
void CCinemaManager::AddTrack(CCinemaTrack track, CStr name)
void CCinemaTrack::MoveToPointAt(float t)
{
m_CPA->m_TimeElapsed = t;
if ( !Validate() )
return;
MoveToPointAt(m_CPA->m_TimeElapsed / m_CPA->GetDuration());
}
void CCinemaTrack::MoveToPointAbsolute(float time)
{
m_CPA = m_Paths.begin();
m_AbsoluteTime = m_CPA->m_TimeElapsed = time;
if (!ValidateForward())
return;
else
m_CPA->MoveToPointAt(m_CPA->m_TimeElapsed, m_StartRotation);
}
void CCinemaManager::AddTrack(CCinemaTrack track, CStrW name)
{
debug_assert( m_Tracks.find( name ) == m_Tracks.end() );
m_Tracks[name] = track;
}
void CCinemaManager::QueueTrack(CStr name, bool queue )
void CCinemaManager::QueueTrack(CStrW name, bool queue )
{
if (!m_TrackQueue.empty() && queue == false)
{
@ -278,10 +345,17 @@ void CCinemaManager::QueueTrack(CStr name, bool queue )
}
else
{
debug_assert(HasTrack(name));
m_TrackQueue.push_back(m_Tracks[name]);
m_TrackQueue.back().m_CPA = m_TrackQueue.back().m_Paths.begin();
}
}
void CCinemaManager::OverrideTrack(CStrW name)
{
m_TrackQueue.clear();
debug_assert(HasTrack(name));
m_TrackQueue.push_back( m_Tracks[name] );
}
bool CCinemaManager::Update(float DeltaTime)
{
if (!m_TrackQueue.front().Play(DeltaTime))
@ -291,10 +365,7 @@ bool CCinemaManager::Update(float DeltaTime)
}
return true;
}
bool CCinemaManager::IsPlaying()
{
return !m_TrackQueue.empty();
}
int CCinemaManager::LoadTracks()
{
unsigned int fileID;
@ -337,7 +408,6 @@ int CCinemaManager::LoadTracks()
int numNodes;
//load main data
Stream >> numNodes;
Stream >> tmpData.m_TotalDuration;
Stream >> tmpData.m_TotalRotation.X;
Stream >> tmpData.m_TotalRotation.Y;
Stream >> tmpData.m_TotalRotation.Z;
@ -361,46 +431,4 @@ int CCinemaManager::LoadTracks()
AddTrack(tmpTrack, Name);
}
return 0;
}
int CCinemaManager::HACK_WriteTrack(CCinemaTrack track)
{
char *name = "cinematic.cnm";
FILE *fp = fopen(name, "wb");
unsigned int fileID = 0x0ADC;
int numTracks = 1;
size_t numPaths = track.m_Paths.size();
fwrite( &fileID, sizeof(fileID), 1, fp);
fwrite( &numTracks, sizeof(numTracks), 1, fp);
fwrite( &name, sizeof(name), 1, fp);
fwrite( &numPaths, sizeof(numPaths), 1, fp);
fwrite( &track.m_StartRotation, sizeof(track.m_StartRotation), 1, fp );
for (size_t i=0; i<numPaths; i++)
{
int count = track.m_Paths[i].GetNodeCount();
float duration = track.m_Paths[i].GetDuration();
fwrite( &count, sizeof(int), 1, fp );
fwrite( &duration, sizeof(float), 1, fp );
fwrite( &track.m_Paths[i].m_TotalRotation, sizeof(CVector3D), 1, fp );
fwrite( &track.m_Paths[i].m_Growth, sizeof(float), 1, fp );
fwrite( &track.m_Paths[i].m_Switch, sizeof(float), 1, fp );
fwrite( &track.m_Paths[i].m_Growth, sizeof(float), 1, fp );
fwrite( &track.m_Paths[i].m_Mode, sizeof(float), 1, fp );
fwrite( &track.m_Paths[i].m_Style, sizeof(float), 1, fp );
for (int j=0; j < track.m_Paths[i].GetNodeCount(); j++)
{
CVector3D position = track.m_Paths[i].GetNodePosition(j);
float duration = track.m_Paths[i].GetNodeDuration(j);
fwrite( &position, sizeof(CVector3D), 1, fp );
fwrite( &duration, sizeof(float), 1, fp );
}
}
fclose(fp);
return 0;
}
}

View File

@ -15,21 +15,13 @@
#include <list>
#include <map>
#include "ps/CStr.h"
#include "maths/NUSpline.h"
/*
Andrew (aka pyrolink)
Contact: ajdecker1022@msn.com
desc: contains various functions used for cinematic camera tracks
Note: There are some differences between the common 'things' of this and the Atlas
version.
The Play functions for both are essentially the same, but Atlas does not support queued tracks.
The difference between the Track Manager and Cinema Manager is the track manager
is for adding and deleting tracks to the list, in the editor. The Cinema Manager is
for taking care of the queued up Tracks, i.e. when they are to be destroyed/added.
*/
class CVector3D;
@ -39,12 +31,12 @@ class CCamera;
//For loading data
class CCinemaData
{
public:
public:
CCinemaData() {}
~CCinemaData() {}
float m_TotalDuration;
//X=x rotation in degrees...etc
const CCinemaData* GetData() const { return this; }
CVector3D m_TotalRotation;
//Distortion variables
@ -56,17 +48,14 @@ public:
};
class CCinemaPath : public CCinemaData
//Once the data is part of the path, it shouldn't be changeable
class CCinemaPath : private CCinemaData, public TNSpline
{
friend class CCinemaTrack;
public:
CCinemaPath(CCinemaData data);
CCinemaPath() { DistStylePtr = &CCinemaPath::EaseDefault; DistModePtr = &CCinemaPath::EaseIn; }
CCinemaPath(const CCinemaData& data, const TNSpline& spline);
~CCinemaPath() { DistStylePtr = NULL; DistModePtr = NULL; }
float m_TimeElapsed;
//Resets Rotation-Must call before MoveToPointAt()!!!
void ResetRotation(float t);
//sets camera position to calculated point on spline
void MoveToPointAt(float t, const CVector3D &startRotation);
@ -89,72 +78,86 @@ public:
float (CCinemaPath::*DistStylePtr)(float ratio);
float (CCinemaPath::*DistModePtr)(float ratio);
const CCinemaData* GetData() const { return CCinemaData::GetData(); }
public:
//Used when time and position are already set (usually from loaded file)
void AddNode(const CVector3D &pos, float timePeriod) { m_Spline.AddNode(pos, timePeriod); }
void PushNode() { m_Spline.Node.push_back( SplineData() ); }
void InsertNode(const int index, const CVector3D &pos, float timePeriod) { m_Spline.InsertNode(index, pos, timePeriod); }
void RemoveNode(const int index) { m_Spline.RemoveNode(index); }
void UpdateNodeTime(const int index, float time) { m_Spline.Node[index].Distance = time; }
void UpdateNodePos(const int index, const CVector3D &pos) { m_Spline.Node[index].Position = pos; }
void DrawSpline(CVector4D RGBA, int smoothness);
int GetNodeCount() { return m_Spline.NodeCount; }
CVector3D GetNodePosition(const int index) { return m_Spline.Node[index].Position; }
float GetNodeDuration(const int index) { return m_Spline.Node[index].Distance; }
float GetDuration() { return m_Spline.MaxDistance; }
//Called when nodes have been added
void UpdateSpline() { m_Spline.BuildSpline(); }
void SetSpline( TNSpline spline ) { m_Spline = spline; }
inline CVector3D GetNodePosition(const int index) const { return Node[index].Position; }
inline float GetNodeDuration(const int index) const { return Node[index].Distance; }
inline float GetDuration() const { return MaxDistance; }
inline float GetElapsedTime() const { return m_TimeElapsed; }
const std::vector<SplineData>& GetAllNodes() const { return Node; }
// inline void SetElapsedTime(float time) { m_TimeElapsed = time; }
private:
TNSpline m_Spline;
float m_TimeElapsed;
};
class CCinemaTrack
{
friend class CCinemaManager;
public:
CCinemaTrack() {}
~CCinemaTrack() {}
std::vector<CCinemaPath> m_Paths;
std::vector<CCinemaPath>::iterator m_CPA; //current path
CVector3D m_StartRotation;
void AddPath(CCinemaData path, TNSpline &spline);
bool Validate();
void AddPath(CCinemaData& data, TNSpline& spline);
inline void SetTimeScale(float scale) { m_TimeScale = scale; }
inline void SetStartRotation(CVector3D rotation) { m_StartRotation = rotation; }
void UpdateDuration();
//DOES NOT set CPA to Paths.begin(). Returns-false indicates it's finished,
//true means it's still playing.
bool Play(float DeltaTime);
bool Play(float DeltaTime);
bool Validate();
void MoveToPointAt(float t);
void MoveToPointAbsolute(float time); //Time, not ratio, in terms of track
inline const CVector3D& GetRotation() const { return m_StartRotation; }
inline float GetTimeScale() const { return m_TimeScale; }
inline float GetTotalDuration() const { return m_TotalDuration; }
inline const std::vector<CCinemaPath>& GetAllPaths() const { return m_Paths; }
private:
std::vector<CCinemaPath> m_Paths;
std::vector<CCinemaPath>::iterator m_CPA; //current path
CVector3D m_StartRotation;
float m_TimeScale; //a negative timescale results in backwards play
float m_AbsoluteTime; //Current time of track, in absolute terms (not path)
float m_TotalDuration;
bool ValidateForward();
bool ValidateRewind();
};
//Class for in game playing of cinematics
class CCinemaManager
{
public:
CCinemaManager() {}
CCinemaManager() { m_Active=false; }
~CCinemaManager() {}
void AddTrack(CCinemaTrack track, CStr name);
void AddTrack(CCinemaTrack track, CStrW name);
int LoadTracks(); //Loads tracks from file
int HACK_WriteTrack(CCinemaTrack track);
//Adds track to list of being played. (Called by triggers?)
void QueueTrack(CStr name, bool queue);
void QueueTrack(CStrW name, bool queue);
void OverrideTrack(CStrW name); //clears track queue and replaces with 'name'
bool Update(float DeltaTime);
bool IsPlaying();
inline bool IsPlaying() const { return !m_TrackQueue.empty(); }
bool HasTrack(CStrW name) const { return m_Tracks.find(name) != m_Tracks.end(); }
inline bool IsActive() const { return m_Active; }
inline void SetActive(bool active) { m_Active=active; }
CCinemaTrack* GetTrack(CStrW name) { debug_assert(HasTrack(name)); return &m_Tracks[name]; }
inline const std::map<CStrW, CCinemaTrack>& GetAllTracks() { return m_Tracks; }
inline void SetAllTracks( const std::map<CStrW, CCinemaTrack>& tracks) { m_Tracks = tracks; }
private:
std::map<CStr, CCinemaTrack> m_Tracks;
bool m_Active;
std::map<CStrW, CCinemaTrack> m_Tracks;
std::list<CCinemaTrack> m_TrackQueue;
};

View File

@ -88,119 +88,6 @@ CGameView::CGameView(CGame *pGame):
m_UnitView=NULL;
m_UnitAttach=NULL;
/* //TEST TRACK
int Test_Nodes=15;
int Test_Variance=10.0f; //rand() % Test_Variance distortion of linear points
int Test_Space=30;
float Test_NodeTime = 0.65f;
CVector3D Test_Direction(1.0f, 0.0f, 1.0f);
CVector3D Test_StartPos(100, 150, -80);
Test_Direction.Normalize();
CCinemaData Test_Data;
TNSpline Test_Spline;
CCinemaTrack Test_Track;
//linear generation with variance factor
for (int i=0; i<Test_Nodes; i++)
{
CVector3D linear = Test_StartPos + Test_Direction * i * Test_Space;
if ( rand() % 2 )
linear.X += rand() % Test_Variance;
else
linear.X -= rand() % Test_Variance;
if ( rand() % 2 )
linear.Y += rand() % Test_Variance;
else
linear.Y -= rand() % Test_Variance;
if ( rand() % 2 )
linear.Z += rand() % Test_Variance;
else
linear.Z -= rand() % Test_Variance;
Test_Spline.AddNode( linear, Test_NodeTime );
}
Test_Data.m_TotalDuration = Test_Spline.MaxDistance;
Test_Data.m_TotalRotation = CVector3D( 0.0f, DEGTORAD(-150.0f), 0.0f );
Test_Data.m_Growth = Test_Data.m_GrowthCount = 1.9f;
Test_Data.m_Switch = .5f;
Test_Data.m_Mode = EM_IN;
Test_Data.m_Style = ES_DEFAULT;
Test_Track.m_StartRotation = CVector3D( DEGTORAD(30), DEGTORAD(-45), 0.0f );
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Style = ES_GROWTH;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_OUT;
Test_Data.m_Style = ES_EXPO;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_INOUT;
Test_Data.m_Style = ES_GROWTH;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_IN;
Test_Data.m_Style = ES_SINE;
Test_Track.AddPath( Test_Data, Test_Spline );
m_TrackManager.AddTrack(Test_Track, "test");
m_TrackManager.QueueTrack("test", true);
*/
//TEST TRACK
CVector3D Test_NodePos[] = { CVector3D( 109.31228f, 93.302315f, -28.760098f ),
CVector3D( 147.03696f, 87.134117f, 54.718628f ),
CVector3D( 174.245293f, 97.134117f, 116.449940f ),
CVector3D( 146.245293f, 107.134117f, 162.449940f ),
CVector3D( 117.245293f, 97.134117f, 134.449940f ),
CVector3D( 72.88226f, 87.134117f, 114.373001f ),
CVector3D( 50.39368f, 77.71053f, 99.925789f ) };
float Test_NodeTime = 0.85f;
CCinemaData Test_Data;
TNSpline Test_Spline;
CCinemaTrack Test_Track;
//linear generation with variance factor
for (int i=0; i<ARRAY_SIZE(Test_NodePos); i++)
{
Test_Spline.AddNode( Test_NodePos[i], Test_NodeTime );
}
Test_Data.m_TotalDuration = Test_Spline.MaxDistance;
Test_Data.m_TotalRotation = CVector3D( DEGTORAD(15.0f), DEGTORAD(-100.0f), 0.0f );
Test_Data.m_Growth = Test_Data.m_GrowthCount = 1.9f;
Test_Data.m_Switch = .5f;
Test_Data.m_Mode = EM_IN;
Test_Data.m_Style = ES_DEFAULT;
Test_Track.m_StartRotation = CVector3D( DEGTORAD(30), DEGTORAD(-45), 0.0f );
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Style = ES_GROWTH;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_OUT;
Test_Data.m_Style = ES_EXPO;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_INOUT;
Test_Data.m_Style = ES_GROWTH;
Test_Track.AddPath( Test_Data, Test_Spline );
Test_Data.m_Mode = EM_IN;
Test_Data.m_Style = ES_SINE;
Test_Track.AddPath( Test_Data, Test_Spline );
m_TrackManager.AddTrack(Test_Track, "test");
m_TestTrack.m_Paths.push_back(CCinemaPath());
ONCE( ScriptingInit(); );
}
@ -533,11 +420,12 @@ void CGameView::Update(float DeltaTime)
return;
}
if (m_TrackManager.IsPlaying())
if (m_TrackManager.IsActive())
{
if(!m_TrackManager.Update(DeltaTime))
if (m_TrackManager.IsPlaying())
{
ResetCamera();
if(!m_TrackManager.Update(DeltaTime))
ResetCamera();
}
m_ViewCamera.UpdateFrustum();
return;
@ -741,30 +629,6 @@ void CGameView::Update(float DeltaTime)
}
//Temporary hack for cinematic interface
if ( hotkeys[HOTKEY_CAMERA_CINEMA_ADD] )
{
std::vector<CCinemaPath>::iterator it = m_TestTrack.m_Paths.begin();
if (it->GetNodeCount() == 0)
m_TestTrack.m_StartRotation = m_ViewCamera.m_Orientation.GetRotation().m_V;
it->AddNode(m_ViewCamera.m_Orientation.GetTranslation(), 1.5f);
it->UpdateSpline();
}
if ( hotkeys[HOTKEY_CAMERA_CINEMA_DELETE] )
m_TestTrack.m_Paths.front().RemoveNode( m_TestTrack.m_Paths.front().GetNodeCount() - 1 );
m_TestTrack.m_Paths.front().UpdateSpline();
if ( hotkeys[HOTKEY_CAMERA_CINEMA_DELETE_ALL] )
{
for (int i=m_TestTrack.m_Paths.front().GetNodeCount() - 1; i >= 0; i--)
{
m_TestTrack.m_Paths.front().RemoveNode( i );
}
}
if ( hotkeys[HOTKEY_CAMERA_CINEMA_QUEUE] )
m_TrackManager.QueueTrack("test", false);
// Smoothed zooming (move a certain percentage towards the desired zoom distance every frame)
// Note that scroll wheel zooming is event-based and handled in game_view_handler

View File

@ -164,6 +164,8 @@ public:
inline CCamera *GetCamera()
{ return &m_ViewCamera; }
inline CCinemaManager* GetCinema()
{ return &m_TrackManager; };
};
extern InReaction game_view_handler(const SDL_Event* ev);

View File

@ -199,7 +199,22 @@ void TNSpline::RemoveNode(const int index)
}
NodeCount--;
}
void TNSpline::UpdateNodeTime(const int index, float time)
{
if (NodeCount == 0 || index > NodeCount - 1 )
{
return;
}
Node[index].Distance = time;
}
void TNSpline::UpdateNodePos(const int index, const CVector3D &pos)
{
if (NodeCount == 0 || index > NodeCount - 1 )
{
return;
}
Node[index].Position = pos;
}
void TNSpline::Constrain()
{
if ( NodeCount < 3 )

View File

@ -24,12 +24,12 @@ public:
void AddNode(const CVector3D &pos);
void BuildSpline();
CVector3D GetPosition(float time);
std::vector<SplineData> Node;
float MaxDistance;
int NodeCount;
protected:
std::vector<SplineData> Node;
CVector3D GetStartVelocity(int index);
CVector3D GetEndVelocity(int index);
};
@ -48,8 +48,10 @@ public:
void PushNode() { Node.push_back( SplineData() ); }
void InsertNode(const int index, const CVector3D &pos, float timePeriod);
void RemoveNode(const int index);
void BuildSpline(){ RNSpline::BuildSpline(); for (int i=0;i<5;i++) { Smooth(); Smooth(); Smooth(); } }
void UpdateNodeTime(const int index, float time);
void UpdateNodePos(const int index, const CVector3D &pos);
void BuildSpline(){ RNSpline::BuildSpline(); Smooth(); Smooth(); Smooth(); }
void Smooth(){ for( int x=0; x<3; x++ ) { SNSpline::Smooth(); Constrain(); } }
void Constrain();
};

View File

@ -33,11 +33,34 @@ CConsole::CConsole()
FlushBuffer();
m_iMsgHistPos = 1;
m_charsPerPage=0;
InsertMessage(L"[ 0 A.D. Console v0.12 ] type \"\\info\" for help");
InsertMessage(L"");
}
if (vfs_exists("gui/text/help.txt"))
{
FileIOBuf buf;
size_t size;
if ( vfs_load("gui/text/help.txt", buf, size) < 0 )
{
LOG( ERROR,"Console", "Help file not found for console" );
file_buf_free(buf);
return;
}
const char* text = (const char*)buf;
CStrW temp = CStrW( CStr(text) );
size_t i=0, strings = temp.Length()/1024 ;
for ( ; i<strings; ++i )
m_helpText.push_back( temp.substr(i*1024, 1023) );
m_helpText.push_back( temp.substr(strings*1024) );
file_buf_free(buf);
}
else
InsertMessage(L"No help file found.");
}
CConsole::~CConsole()
{
@ -505,16 +528,37 @@ void CConsole::InsertMessage(const wchar_t* szMessage, ...)
wcscpy(szBuffer+CONSOLE_MESSAGE_SIZE-4, L"...");
}
va_end(args);
// Split into lines and add each one individually
wchar_t* lineStart = szBuffer;
wchar_t* lineEnd;
while ( (lineEnd = wcschr(lineStart, '\n')) != NULL)
//Insert newlines to wraparound text where needed
CStrW wrapAround( szBuffer ), newline(L'\n');
size_t oldNewline=0;
size_t distance;
//make sure everything has been initialized
if ( m_charsPerPage != 0 )
{
m_deqMsgHistory.push_front(std::wstring(lineStart, lineEnd));
lineStart = lineEnd+1;
while ( oldNewline+m_charsPerPage < wrapAround.length() )
{
distance = wrapAround.find(newline, oldNewline) - oldNewline;
if ( distance > m_charsPerPage )
{
oldNewline += m_charsPerPage;
wrapAround.insert( oldNewline++, newline );
}
else
oldNewline += distance+1;
}
}
m_deqMsgHistory.push_front(std::wstring(lineStart));
// Split into lines and add each one individually
oldNewline = 0;
while ( (distance = wrapAround.find(newline, oldNewline)) != wrapAround.npos)
{
distance -= oldNewline;
m_deqMsgHistory.push_front(wrapAround.substr(oldNewline, distance));
oldNewline += distance+1;
}
m_deqMsgHistory.push_front(wrapAround.substr(oldNewline));
}
const wchar_t* CConsole::GetBuffer()
@ -577,6 +621,7 @@ void CConsole::ProcessBuffer(const wchar_t* szLine){
InsertMessage(L" -View commands \"\\commands\"");
InsertMessage(L" -Call command \"\\<command>\"");
InsertMessage(L" -Say \"<string>\"");
InsertMessage(L" -Help - Lists functions usable from console");
InsertMessage(L"");
}
else if (!wcscmp(szCommand, L"commands"))
@ -591,6 +636,13 @@ void CConsole::ProcessBuffer(const wchar_t* szLine){
InsertMessage(L"");
}
else if (! (wcscmp(szCommand, L"Help") && wcscmp(szCommand, L"help")) )
{
InsertMessage(L"");
InsertMessage(L"[Help]");
for ( std::vector<std::wstring>::iterator it=m_helpText.begin(); it!=m_helpText.end(); it++ )
InsertMessage( it->c_str() );
}
else
{
Iter = m_mapFuncList.find(szCommand);

View File

@ -39,7 +39,8 @@ private:
// "position" in show/hide animation, how visible the console is (0..1).
// allows implementing other animations than sliding, e.g. fading in/out.
float m_fVisibleFrac;
std::vector<std::wstring> m_helpText;
std::map<std::wstring, fptr> m_mapFuncList;
std::deque<std::wstring> m_deqMsgHistory;
@ -110,7 +111,9 @@ public:
bool IsActive() { return m_bVisible; }
int m_iFontHeight;
int m_iFontWidth;
int m_iFontOffset; // distance to move up before drawing
size_t m_charsPerPage;
};
extern CConsole* g_Console;

View File

@ -619,6 +619,8 @@ static void InitPs(bool setup_gui)
// Calculate and store the line spacing
CFont font("console");
g_Console->m_iFontHeight = font.GetLineSpacing();
g_Console->m_iFontWidth = font.GetCharacterWidth(L'C');
g_Console->m_charsPerPage = (size_t)(g_xres / g_Console->m_iFontWidth);
// Offset by an arbitrary amount, to make it fit more nicely
g_Console->m_iFontOffset = 9;
}

View File

@ -236,70 +236,7 @@ CNetCommand *CNetMessage::CommandFromJSArgs(const CEntityList &entities, JSConte
}
}
CNetCommand *CNetMessage::CastCommand(CNetMessage*& message, const CEntityList& entities, const ENetMessageType type)
{
#define CopyPositionMessage(_msg) \
case NMT_ ## _msg: \
{ \
C##_msg *msg = new C##_msg(); \
C##_msg *castmsg = static_cast<C##_msg*>(message); \
msg->m_TargetX = castmsg->m_TargetX; \
msg->m_TargetY = castmsg->m_TargetY; \
msg->m_Entities = entities; \
return msg; \
}
#define CopyEntityMessage(_msg) \
case NMT_ ## _msg: \
{ \
C##_msg *msg = new C##_msg(); \
C##_msg *castmsg = static_cast<C##_msg*>(message); \
msg->m_Entities = entities; \
msg->m_Target = castmsg->Target; \
return msg; \
}
#define CopyEntityIntMessage(_msg) \
case NMT_ ## _msg: \
{ \
C##_msg *msg = new C##_msg(); \
C##_msg *castmsg = static_cast<C##_msg*>(message); \
msg->m_Entities = entities; \
msg->m_Target = castmsg->m_Target; \
msg->m_Action = castmsg->m_Action; \
return msg; \
}
#define CopyProduceMessage(_msg) \
case NMT_ ## _msg: \
{ \
C##_msg *msg = new C##_msg(); \
C##_msg *castmsg = static_cast<C##_msg*>(message); \
msg->m_Entities = entities; \
msg->m_Name = castmsg->m_Name; \
msg->m_Type = castmsg->m_Type; \
return msg; \
}
switch (type)
{
CopyPositionMessage(Goto)
CopyPositionMessage(Run)
CopyPositionMessage(Patrol)
CopyPositionMessage(AddWaypoint)
CopyPositionMessage(FormationGoto)
CopyEntityIntMessage(Generic)
CopyEntityIntMessage(NotifyRequest)
CopyEntityIntMessage(FormationGeneric)
CopyProduceMessage(Produce)
default:
return NULL;
}
}
CNetMessage *CNetMessage::CreatePositionMessage( const CEntityList& entities, const ENetMessageType type, CVector2D pos )
CNetMessage *CNetMessage::CreatePositionMessage( const CEntityList& entities, const int type, CVector2D pos )
{
#define PosMessage(_msg) \
case NMT_ ## _msg: \
@ -323,7 +260,7 @@ CNetMessage *CNetMessage::CreatePositionMessage( const CEntityList& entities, co
return NULL;
}
}
CNetMessage *CNetMessage::CreateEntityIntMessage( const CEntityList& entities, const ENetMessageType type, HEntity& target, int action )
CNetMessage *CNetMessage::CreateEntityIntMessage( const CEntityList& entities, const int type, HEntity& target, int action )
{
#define EntMessage(_msg) \
case NMT_ ## _msg: \
@ -345,7 +282,7 @@ CNetMessage *CNetMessage::CreateEntityIntMessage( const CEntityList& entities, c
return NULL;
}
}
CNetMessage *CNetMessage::CreateProduceMessage( const CEntityList& entities, const ENetMessageType type, int proType, CStrW name )
CNetMessage *CNetMessage::CreateProduceMessage( const CEntityList& entities, const int type, int proType, CStrW name )
{
#define ProMessage(_msg)\
case NMT_ ## _msg: \

View File

@ -75,13 +75,11 @@ public:
static void ScriptingInit();
static CNetCommand *CommandFromJSArgs(const CEntityList &entities, JSContext* cx, uintN argc, jsval* argv);
//This, in a sense, a netmessage typecast. It copies the target data from "message", creates
//a message of type "type", and assigns the message entities as "entities".
static CNetCommand *CastCommand(CNetMessage*& message, const CEntityList &entities, const ENetMessageType type);
//These can create a net message without JS args
static CNetMessage *CreatePositionMessage( const CEntityList& entities, const ENetMessageType type, CVector2D pos );
static CNetMessage *CreateEntityIntMessage( const CEntityList& entities, const ENetMessageType type, HEntity& target, int action );
static CNetMessage *CreateProduceMessage( const CEntityList& entities, const ENetMessageType type, int proType, CStrW name );
static CNetMessage *CreatePositionMessage( const CEntityList& entities, const int type, CVector2D pos );
static CNetMessage *CreateEntityIntMessage( const CEntityList& entities, const int type, HEntity& target, int action );
static CNetMessage *CreateProduceMessage( const CEntityList& entities, const int type, int proType, CStrW name );
};
typedef CNetMessage * (*NetMessageDeserializer) (const u8 *buffer, uint length);

View File

@ -203,25 +203,34 @@ JSBool getEntityTemplate( JSContext* cx, JSObject*, uint argc, jsval* argv, jsva
return( JS_TRUE );
}
//Used to create net messages for formations--msgList.front() is the original message. see issueCommand
void CreateFormationMessage( std::vector<CNetMessage*>& msgList, CNetMessage*& msg, HEntity formationEnt )
void CreateFormationMessage( std::vector<CNetMessage*>& msgList, CNetMessage* msg, CEntityList& formation )
{
if ( formationEnt->GetFormation()->IsDuplication() || msgList.empty() )
return;
CNetMessage* tmp;
ENetMessageType type=msg->GetType();
CEntityList formation = formationEnt->GetFormation()->GetEntityList();
if ( type == NMT_Goto || type == NMT_Run )
CNetMessage* retMsg;
const int type = msg->GetType();
if ( type == NMT_Goto )
{
//formationEnt->GetFormation()->BaseToMovement();
tmp = CNetMessage::CastCommand(msg, formation, NMT_FormationGoto);
CGoto* tmp = static_cast<CGoto*>(msg);
retMsg = CNetMessage::CreatePositionMessage( formation, NMT_FormationGoto,
CVector2D(tmp->m_TargetX, tmp->m_TargetY) );
}
else if( type == NMT_Run )
{
CGoto* tmp = static_cast<CGoto*>(msg);
retMsg = CNetMessage::CreatePositionMessage( formation, NMT_FormationGoto,
CVector2D(tmp->m_TargetX, tmp->m_TargetY) );
}
else if ( type == NMT_Generic )
tmp = CNetMessage::CastCommand(msg, formation, NMT_FormationGeneric);
{
CGeneric* tmp = static_cast<CGeneric*>(msg);
retMsg = CNetMessage::CreateEntityIntMessage(formation, NMT_FormationGeneric,
tmp->m_Target, tmp->m_Action);
}
else
return;
msgList.push_back(tmp);
msgList.push_back(retMsg);
}
// Issue a command (network message) to an entity or collection.
@ -234,13 +243,16 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
debug_assert(JSVAL_IS_OBJECT(argv[0]));
*rval = JSVAL_NULL;
CEntityList entities;
CEntityList entities, msgEntities;
if (JS_GetClass(JSVAL_TO_OBJECT(argv[0])) == &CEntity::JSI_class)
entities.push_back( (ToNative<CEntity>(argv[0])) ->me);
else
entities = *EntityCollection::RetrieveSet(cx, JSVAL_TO_OBJECT(argv[0]));
msgEntities = entities;
std::map<int, CEntityList> entityStore;
//Destroy old notifiers if we're explicitly being reassigned
for ( size_t i=0; i < entities.size(); i++)
{
@ -248,11 +260,7 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
entities[i]->DestroyAllNotifiers();
}
std::vector<CNetMessage*> messages;
CNetMessage* msg = CNetMessage::CommandFromJSArgs(entities, cx, argc-1, argv+1);
if (!msg)
return JS_TRUE;
messages.push_back(msg);
//Generate messages for formations
for (size_t i=0; i < entities.size(); i++ )
{
@ -264,18 +272,23 @@ JSBool issueCommand( JSContext* cx, JSObject*, uint argc, jsval* argv, jsval* rv
if ( formation->IsLocked() && !duplicate)
{
formation->SelectAllUnits();
CreateFormationMessage(messages, msg, entities[i]);
entityStore[entities[i]->m_formation] = formation->GetEntityList();
formation->SetDuplication(true);
entities.erase( entities.begin()+i ); //we don't want to be in two orders
--i;
}
else if ( duplicate )
{
entities.erase( entities.begin()+i );
--i;
}
}
else
msgEntities.push_back( entities[i] );
}
CNetMessage* msg = CNetMessage::CommandFromJSArgs(msgEntities, cx, argc-1, argv+1);
if (!msg)
{
return JS_TRUE;
delete msg;
}
messages.push_back(msg);
for ( std::map<int, CEntityList>::iterator it=entityStore.begin(); it!=entityStore.end(); it++)
CreateFormationMessage(messages, msg, it->second);
for ( std::vector<CNetMessage*>::iterator it=messages.begin(); it != messages.end(); it++ )
{

View File

@ -1104,7 +1104,7 @@ int CEntity::findSector( int divs, float angle, float maxAngle, bool negative )
}
else
{
int i=0;
int i=1;
for ( float tracker=0.0f; tracker<maxAngle; tracker+=step, ++i )
{
if ( angle > tracker && angle <= tracker+step )
@ -2188,37 +2188,8 @@ jsval CEntity::FindSector( JSContext* cx, uintN argc, jsval* argv )
float angle = ToPrimitive<float>( argv[1] );
float maxAngle = ToPrimitive<float>( argv[2] );
bool negative = ToPrimitive<bool>( argv[3] );
float step = maxAngle/divs;
if ( negative )
{
float tracker;
int i=1, sectorRemainder;
for ( tracker=-maxAngle/2.0f; tracker+step<0.0f; tracker+=step, ++i )
{
if ( angle > tracker && angle <= tracker+step )
return ToJSVal(i);
}
sectorRemainder = i;
i=divs;
for ( tracker=maxAngle/2.0f; tracker-step>0.0f; tracker-=step, --i )
{
if ( angle < tracker && angle >= tracker-step )
return ToJSVal(i);
}
return ToJSVal(sectorRemainder);
}
else
{
int i=1;
for ( float tracker=0.0f; tracker<maxAngle; tracker+=step, ++i )
{
if ( angle > tracker && angle <= tracker+step )
return ToJSVal(i);
}
}
debug_warn("JS - FindSector(): invalid parameters");
return ToJSVal(-1);
return ToJSVal( findSector(divs, angle, maxAngle, negative) );
}
jsval CEntity::HasRallyPoint( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
{

View File

@ -84,7 +84,7 @@ bool CEntityFormation::AddUnit( CEntity*& entity )
}
void CEntityFormation::RemoveUnit( CEntity*& entity )
{
if ( !IsValidOrder(entity->m_formationSlot) || !entity )
if ( !(IsValidOrder(entity->m_formationSlot) && entity) )
return;
m_entities[entity->m_formationSlot] = NULL;
@ -110,7 +110,7 @@ bool CEntityFormation::IsSlotAppropriate( int order, CEntity* entity )
}
bool CEntityFormation::IsBetterUnit( int order, CEntity* entity )
{
if ( !( IsValidOrder(order) || entity ) )
if ( !( IsValidOrder(order) && entity ) )
return false;
//Adding to an empty slot, check if we're elligible
if ( !m_entities[order] )

View File

@ -0,0 +1,204 @@
#include "precompiled.h"
#include "MessageHandler.h"
#include "../CommandProc.h"
#include "graphics/GameView.h"
#include "ps/Game.h"
#include "ps/CStr.h"
#include "ps/CLogger.h"
#include "ps/VFSUtil.h"
#include "lib/res/graphics/tex.h"
#define LOG_CATEGORY "Cinema"
namespace AtlasMessage {
sCinemaTrack ConstructCinemaTrack(const CCinemaTrack& _track)
{
sCinemaTrack track;
const CVector3D& rotation = _track.GetRotation();
track.x = rotation.X;
track.y = rotation.Y;
track.z = rotation.Z;
track.timescale = _track.GetTimeScale();
track.duration = _track.GetTotalDuration();
return track;
}
sCinemaPath ConstructCinemaPath(const CCinemaData* data)
{
sCinemaPath path;
path.x = data->m_TotalRotation.X;
path.y = data->m_TotalRotation.Y;
path.z = data->m_TotalRotation.Z;
path.mode = data->m_Mode;
path.style = data->m_Style;
path.growth = data->m_Growth;
path.change = data->m_Switch;
return path;
}
CCinemaData ConstructCinemaData(const sCinemaPath& path)
{
CCinemaData data;
data.m_TotalRotation = CVector3D(path.x, path.y, path.z);
data.m_Growth = data.m_GrowthCount = path.growth;
data.m_Switch = path.change;
data.m_Mode = path.mode;
data.m_Style = path.style;
return data;
}
sCinemaSplineNode ConstructCinemaNode(const SplineData& data)
{
sCinemaSplineNode node;
node.x = data.Position.X;
node.y = data.Position.Y;
node.z = data.Position.Z;
node.t = data.Distance;
return node;
}
std::vector<sCinemaTrack> GetCurrentTracks()
{
const std::map<CStrW, CCinemaTrack>& tracks = g_Game->GetView()->GetCinema()->GetAllTracks();
std::vector<sCinemaTrack> atlasTracks;
for ( std::map<CStrW, CCinemaTrack>::const_iterator it=tracks.begin(); it!=tracks.end(); it++ )
{
const CCinemaTrack track = it->second;
atlasTracks.push_back( ConstructCinemaTrack(track) );
atlasTracks.back().name = it->first;
const std::vector<CCinemaPath>& paths = it->second.GetAllPaths();
for ( std::vector<CCinemaPath>::const_iterator it2=paths.begin(); it2!=paths.end(); it2++ )
{
const CCinemaData* data = it2->GetData(); //Get data part of path
atlasTracks.back().paths.push_back( ConstructCinemaPath(data) );
const std::vector<SplineData>& nodes = it2->GetAllNodes();
for ( size_t i=0; i<nodes.size(); ++i )
{
atlasTracks.back().paths.back().nodes.push_back( ConstructCinemaNode(nodes[i]) );
}
}
}
return atlasTracks;
}
void SetCurrentTracks(const std::vector<sCinemaTrack>& atlasTracks)
{
std::map<CStrW, CCinemaTrack> tracks;
for ( std::vector<sCinemaTrack>::const_iterator it=atlasTracks.begin(); it!=atlasTracks.end(); it++ )
{
CStrW trackName(*it->name);
tracks[trackName] = CCinemaTrack();
tracks[trackName].SetStartRotation( CVector3D(it->x, it->y, it->z) );
tracks[trackName].SetTimeScale(it->timescale);
const std::vector<sCinemaPath>& paths = it->paths;
for ( std::vector<sCinemaPath>::const_iterator it2=paths.begin(); it2!=paths.end(); it2++ )
{
const sCinemaPath& atlasPath = *it2;
const std::vector<sCinemaSplineNode>& nodes = atlasPath.nodes;
TNSpline spline;
CCinemaData data = ConstructCinemaData(atlasPath);
for ( size_t i=0; i<nodes.size(); ++i )
{
spline.AddNode( CVector3D(nodes[i].x, nodes[i].y, nodes[i].z), nodes[i].t );
}
tracks[trackName].AddPath(data, spline);
}
}
g_Game->GetView()->GetCinema()->SetAllTracks(tracks);
}
QUERYHANDLER(GetCinemaIcons)
{
VFSUtil::FileList files;
VFSUtil::FindFiles("art/textures/ui/session/icons/cinematic/","", files);
FileIOBuf buf;
size_t bufsize;
std::vector<sCinemaIcon> iconList;
for ( VFSUtil::FileList::iterator it=files.begin(); it != files.end(); it++ )
{
if ( tex_is_known_extension(*it) )
{
const char* file = it->c_str();
if ( vfs_load(file, buf, bufsize) < 0 )
{
LOG( ERROR, LOG_CATEGORY, "Failure on loading cinematic icon %s", file );
file_buf_free(buf);
continue;
}
sCinemaIcon icon;
std::wstring name( CStrW( *it->AfterLast("/").BeforeFirst(".").c_str() ) );
std::vector<unsigned char> data;
data.resize(sizeof(data));
//Copy the buffer to the icon
for ( size_t i=0; *buf++; i++ )
{
data.push_back(*buf);
}
file_buf_free(buf);
icon.name = name;
icon.imageData = data;
iconList.push_back(icon);
}
}
msg->images = iconList;
}
MESSAGEHANDLER(CinemaMovement)
{
CCinemaManager* manager = g_Game->GetView()->GetCinema();
CCinemaTrack* track = manager->GetTrack(*msg->track);
if ( msg->mode == eCinemaMovementMode::SMOOTH )
manager->OverrideTrack(*msg->track);
else if ( msg->mode == eCinemaMovementMode::IMMEDIATE_PATH )
track->MoveToPointAt(msg->t);
else if ( msg->mode == eCinemaMovementMode::IMMEDIATE_TRACK )
track->MoveToPointAbsolute(msg->t);
}
BEGIN_COMMAND(SetCinemaTracks)
{
std::vector<sCinemaTrack> m_oldTracks, m_newTracks;
void Do()
{
m_oldTracks = GetCurrentTracks();
m_newTracks = *msg->tracks;
Redo();
}
void Redo()
{
SetCurrentTracks(m_newTracks);
}
void Undo()
{
SetCurrentTracks(m_oldTracks);
}
};
END_COMMAND(SetCinemaTracks)
QUERYHANDLER(GetCinemaTracks)
{
msg->tracks = GetCurrentTracks();
}
}

View File

@ -270,9 +270,60 @@ COMMAND(SetObjectSettings, NOMERGE,
((sObjectSettings, settings))
);
//////////////////////////////////////////////////////////////////////////
struct sCinemaSplineNode
{
float x, y, z, t;
};
SHAREABLE_STRUCT(sCinemaSplineNode);
struct sCinemaPath
{
std::vector<sCinemaSplineNode> nodes;
float duration, x, y, z;
int mode, growth, change, style; //change == switch point
};
SHAREABLE_STRUCT(sCinemaPath);
struct sCinemaTrack
{
Shareable<std::wstring> name;
float x, y, z, timescale, duration;
std::vector<sCinemaPath> paths;
};
SHAREABLE_STRUCT(sCinemaTrack);
struct eCinemaMovementMode { enum { SMOOTH, IMMEDIATE_PATH, IMMEDIATE_TRACK }; };
SHAREABLE_STRUCT(eCinemaMovementMode);
struct sCinemaIcon
{
Shareable<std::wstring> name;
Shareable< std::vector<unsigned char> > imageData;
};
SHAREABLE_STRUCT(sCinemaIcon);
QUERY(GetCinemaTracks,
, //no input
((std::vector<AtlasMessage::sCinemaTrack> , tracks)) );
QUERY(GetCinemaIcons,
,
((std::vector<sCinemaIcon>, images)) );
COMMAND(SetCinemaTracks,
MERGE,
((std::vector<AtlasMessage::sCinemaTrack> , tracks))
((float, timescale)) );
MESSAGE(CinemaMovement,
((std::wstring, track))
((int, mode))
((float, t)) );
#ifndef MESSAGES_SKIP_SETUP
#include "MessagesSetup.h"
#endif