diff --git a/binaries/data/mods/official/gui/text/help.txt b/binaries/data/mods/official/gui/text/help.txt new file mode 100644 index 0000000000..0d2a0a3a2e --- /dev/null +++ b/binaries/data/mods/official/gui/text/help.txt @@ -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, ) - 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 + diff --git a/binaries/data/mods/official/scripts/entity_functions.js b/binaries/data/mods/official/scripts/entity_functions.js index 4025828207..0ecaf5066d 100644 --- a/binaries/data/mods/official/scripts/entity_functions.js +++ b/binaries/data/mods/official/scripts/entity_functions.js @@ -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"; + } } diff --git a/docs/JSReg.rtf b/docs/JSReg.rtf deleted file mode 100644 index 78847fb341..0000000000 Binary files a/docs/JSReg.rtf and /dev/null differ diff --git a/source/graphics/CinemaTrack.cpp b/source/graphics/CinemaTrack.cpp index c4a2bbf0f5..0f4cc78d67 100644 --- a/source/graphics/CinemaTrack.cpp +++ b/source/graphics/CinemaTrack.cpp @@ -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*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::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::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 #include - #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& 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 m_Paths; - std::vector::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& GetAllPaths() const { return m_Paths; } + +private: + std::vector m_Paths; + std::vector::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& GetAllTracks() { return m_Tracks; } + inline void SetAllTracks( const std::map& tracks) { m_Tracks = tracks; } private: - std::map m_Tracks; + bool m_Active; + std::map m_Tracks; std::list m_TrackQueue; }; diff --git a/source/graphics/GameView.cpp b/source/graphics/GameView.cpp index 16c69713e5..ac03805d03 100644 --- a/source/graphics/GameView.cpp +++ b/source/graphics/GameView.cpp @@ -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::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 diff --git a/source/graphics/GameView.h b/source/graphics/GameView.h index 4ae857e7b2..d2c481b164 100644 --- a/source/graphics/GameView.h +++ b/source/graphics/GameView.h @@ -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); diff --git a/source/maths/NUSpline.cpp b/source/maths/NUSpline.cpp index e7d83ae344..cd0dcbfebf 100644 --- a/source/maths/NUSpline.cpp +++ b/source/maths/NUSpline.cpp @@ -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 ) diff --git a/source/maths/NUSpline.h b/source/maths/NUSpline.h index 4af0ec2097..f983f3244d 100644 --- a/source/maths/NUSpline.h +++ b/source/maths/NUSpline.h @@ -24,12 +24,12 @@ public: void AddNode(const CVector3D &pos); void BuildSpline(); CVector3D GetPosition(float time); - - std::vector Node; + float MaxDistance; int NodeCount; protected: + std::vector 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(); }; diff --git a/source/ps/CConsole.cpp b/source/ps/CConsole.cpp index baa48bbe06..e24188e56f 100644 --- a/source/ps/CConsole.cpp +++ b/source/ps/CConsole.cpp @@ -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 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 \"\\\""); InsertMessage(L" -Say \"\""); + 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::iterator it=m_helpText.begin(); it!=m_helpText.end(); it++ ) + InsertMessage( it->c_str() ); + } else { Iter = m_mapFuncList.find(szCommand); diff --git a/source/ps/CConsole.h b/source/ps/CConsole.h index 73addfa43e..d90120de20 100644 --- a/source/ps/CConsole.h +++ b/source/ps/CConsole.h @@ -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 m_helpText; std::map m_mapFuncList; std::deque 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; diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 746acfdc9f..e75a691998 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -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; } diff --git a/source/ps/Network/NetMessage.cpp b/source/ps/Network/NetMessage.cpp index b0f200f997..b8887478e3 100644 --- a/source/ps/Network/NetMessage.cpp +++ b/source/ps/Network/NetMessage.cpp @@ -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(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(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(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(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: \ diff --git a/source/ps/Network/NetMessage.h b/source/ps/Network/NetMessage.h index 144cfe0d40..be48a0487b 100644 --- a/source/ps/Network/NetMessage.h +++ b/source/ps/Network/NetMessage.h @@ -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); diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp index 348cbe19c7..ce90940c5b 100644 --- a/source/scripting/ScriptGlue.cpp +++ b/source/scripting/ScriptGlue.cpp @@ -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& msgList, CNetMessage*& msg, HEntity formationEnt ) +void CreateFormationMessage( std::vector& 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(msg); + retMsg = CNetMessage::CreatePositionMessage( formation, NMT_FormationGoto, + CVector2D(tmp->m_TargetX, tmp->m_TargetY) ); + } + else if( type == NMT_Run ) + { + CGoto* tmp = static_cast(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(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(argv[0])) ->me); else entities = *EntityCollection::RetrieveSet(cx, JSVAL_TO_OBJECT(argv[0])); - + + msgEntities = entities; + std::map 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 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::iterator it=entityStore.begin(); it!=entityStore.end(); it++) + CreateFormationMessage(messages, msg, it->second); for ( std::vector::iterator it=messages.begin(); it != messages.end(); it++ ) { diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp index 2e2abb847c..3fd05ddfbe 100644 --- a/source/simulation/Entity.cpp +++ b/source/simulation/Entity.cpp @@ -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 tracker && angle <= tracker+step ) @@ -2188,37 +2188,8 @@ jsval CEntity::FindSector( JSContext* cx, uintN argc, jsval* argv ) float angle = ToPrimitive( argv[1] ); float maxAngle = ToPrimitive( argv[2] ); bool negative = ToPrimitive( 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 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) ) { diff --git a/source/simulation/EntityFormation.cpp b/source/simulation/EntityFormation.cpp index fd0928a9fb..9ef393b926 100644 --- a/source/simulation/EntityFormation.cpp +++ b/source/simulation/EntityFormation.cpp @@ -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] ) diff --git a/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp b/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp new file mode 100644 index 0000000000..1156baec8e --- /dev/null +++ b/source/tools/atlas/GameInterface/Handlers/CinemaHandler.cpp @@ -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 GetCurrentTracks() +{ + const std::map& tracks = g_Game->GetView()->GetCinema()->GetAllTracks(); + std::vector atlasTracks; + + for ( std::map::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& paths = it->second.GetAllPaths(); + + for ( std::vector::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& nodes = it2->GetAllNodes(); + + for ( size_t i=0; i& atlasTracks) +{ + std::map tracks; + + for ( std::vector::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& paths = it->paths; + + for ( std::vector::const_iterator it2=paths.begin(); it2!=paths.end(); it2++ ) + { + const sCinemaPath& atlasPath = *it2; + const std::vector& nodes = atlasPath.nodes; + TNSpline spline; + CCinemaData data = ConstructCinemaData(atlasPath); + + for ( size_t i=0; iGetView()->GetCinema()->SetAllTracks(tracks); +} + +QUERYHANDLER(GetCinemaIcons) +{ + VFSUtil::FileList files; + VFSUtil::FindFiles("art/textures/ui/session/icons/cinematic/","", files); + FileIOBuf buf; + size_t bufsize; + std::vector 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 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 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(); +} + +} + + + + + + + + \ No newline at end of file diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h index b3f6f426f3..b7d32336e5 100644 --- a/source/tools/atlas/GameInterface/Messages.h +++ b/source/tools/atlas/GameInterface/Messages.h @@ -270,9 +270,60 @@ COMMAND(SetObjectSettings, NOMERGE, ((sObjectSettings, settings)) ); - ////////////////////////////////////////////////////////////////////////// +struct sCinemaSplineNode +{ + float x, y, z, t; +}; +SHAREABLE_STRUCT(sCinemaSplineNode); + +struct sCinemaPath +{ + std::vector nodes; + float duration, x, y, z; + int mode, growth, change, style; //change == switch point + +}; +SHAREABLE_STRUCT(sCinemaPath); + +struct sCinemaTrack +{ + Shareable name; + float x, y, z, timescale, duration; + std::vector paths; +}; +SHAREABLE_STRUCT(sCinemaTrack); + +struct eCinemaMovementMode { enum { SMOOTH, IMMEDIATE_PATH, IMMEDIATE_TRACK }; }; +SHAREABLE_STRUCT(eCinemaMovementMode); + +struct sCinemaIcon +{ + Shareable name; + Shareable< std::vector > imageData; +}; +SHAREABLE_STRUCT(sCinemaIcon); + +QUERY(GetCinemaTracks, + , //no input + ((std::vector , tracks)) ); + +QUERY(GetCinemaIcons, + , + ((std::vector, images)) ); + + +COMMAND(SetCinemaTracks, + MERGE, + ((std::vector , tracks)) + ((float, timescale)) ); + +MESSAGE(CinemaMovement, + ((std::wstring, track)) + ((int, mode)) + ((float, t)) ); + #ifndef MESSAGES_SKIP_SETUP #include "MessagesSetup.h" #endif