Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/simulation2/components/CCmpVisualActor.cpp
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | |||||
#include "ps/GameSetup/Config.h" | #include "ps/GameSetup/Config.h" | ||||
#include "renderer/Scene.h" | #include "renderer/Scene.h" | ||||
class CCmpVisualActor : public ICmpVisual | class CCmpVisualActor : public ICmpVisual | ||||
{ | { | ||||
public: | public: | ||||
static void ClassInit(CComponentManager& componentManager) | static void ClassInit(CComponentManager& componentManager) | ||||
{ | { | ||||
componentManager.SubscribeToMessageType(MT_Update_Final); | |||||
componentManager.SubscribeToMessageType(MT_InterpolatedPositionChanged); | componentManager.SubscribeToMessageType(MT_InterpolatedPositionChanged); | ||||
componentManager.SubscribeToMessageType(MT_OwnershipChanged); | componentManager.SubscribeToMessageType(MT_OwnershipChanged); | ||||
componentManager.SubscribeToMessageType(MT_ValueModification); | componentManager.SubscribeToMessageType(MT_ValueModification); | ||||
componentManager.SubscribeToMessageType(MT_TerrainChanged); | componentManager.SubscribeToMessageType(MT_TerrainChanged); | ||||
componentManager.SubscribeToMessageType(MT_Destroy); | componentManager.SubscribeToMessageType(MT_Destroy); | ||||
} | } | ||||
DEFAULT_COMPONENT_ALLOCATOR(VisualActor) | DEFAULT_COMPONENT_ALLOCATOR(VisualActor) | ||||
private: | private: | ||||
std::wstring m_BaseActorName, m_ActorName; | std::wstring m_BaseActorName, m_ActorName; | ||||
bool m_IsFoundationActor; | bool m_IsFoundationActor; | ||||
// Not initialized in non-visual mode | // Not initialized in non-visual mode | ||||
CUnit* m_Unit; | CUnit* m_Unit; | ||||
fixed m_R, m_G, m_B; // shading color | fixed m_R, m_G, m_B; // shading color | ||||
// Current animation state | // Current animation state | ||||
fixed m_AnimRunThreshold; // if non-zero this is the special walk/run mode | |||||
std::string m_AnimName; | std::string m_AnimName; | ||||
bool m_AnimOnce; | bool m_AnimOnce; | ||||
fixed m_AnimSpeed; | fixed m_AnimSpeed; | ||||
std::wstring m_SoundGroup; | std::wstring m_SoundGroup; | ||||
fixed m_AnimDesync; | fixed m_AnimDesync; | ||||
fixed m_AnimSyncRepeatTime; // 0.0 if not synced | fixed m_AnimSyncRepeatTime; // 0.0 if not synced | ||||
fixed m_AnimSyncOffsetTime; | fixed m_AnimSyncOffsetTime; | ||||
▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | public: | ||||
template<typename S> | template<typename S> | ||||
void SerializeCommon(S& serialize) | void SerializeCommon(S& serialize) | ||||
{ | { | ||||
serialize.NumberFixed_Unbounded("r", m_R); | serialize.NumberFixed_Unbounded("r", m_R); | ||||
serialize.NumberFixed_Unbounded("g", m_G); | serialize.NumberFixed_Unbounded("g", m_G); | ||||
serialize.NumberFixed_Unbounded("b", m_B); | serialize.NumberFixed_Unbounded("b", m_B); | ||||
serialize.NumberFixed_Unbounded("anim run threshold", m_AnimRunThreshold); | |||||
serialize.StringASCII("anim name", m_AnimName, 0, 256); | serialize.StringASCII("anim name", m_AnimName, 0, 256); | ||||
serialize.Bool("anim once", m_AnimOnce); | serialize.Bool("anim once", m_AnimOnce); | ||||
serialize.NumberFixed_Unbounded("anim speed", m_AnimSpeed); | serialize.NumberFixed_Unbounded("anim speed", m_AnimSpeed); | ||||
serialize.String("sound group", m_SoundGroup, 0, 256); | serialize.String("sound group", m_SoundGroup, 0, 256); | ||||
serialize.NumberFixed_Unbounded("anim desync", m_AnimDesync); | serialize.NumberFixed_Unbounded("anim desync", m_AnimDesync); | ||||
serialize.NumberFixed_Unbounded("anim sync repeat time", m_AnimSyncRepeatTime); | serialize.NumberFixed_Unbounded("anim sync repeat time", m_AnimSyncRepeatTime); | ||||
serialize.NumberFixed_Unbounded("anim sync offset time", m_AnimSyncOffsetTime); | serialize.NumberFixed_Unbounded("anim sync offset time", m_AnimSyncOffsetTime); | ||||
Show All 38 Lines | if (m_Unit) | ||||
m_Unit->GetModel().SetPlayerID(cmpOwnership->GetOwner()); | m_Unit->GetModel().SetPlayerID(cmpOwnership->GetOwner()); | ||||
} | } | ||||
} | } | ||||
virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) | virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) | ||||
{ | { | ||||
switch (msg.GetType()) | switch (msg.GetType()) | ||||
{ | { | ||||
case MT_Update_Final: | |||||
{ | |||||
const CMessageUpdate_Final& msgData = static_cast<const CMessageUpdate_Final&> (msg); | |||||
Update(msgData.turnLength); | |||||
break; | |||||
} | |||||
case MT_OwnershipChanged: | case MT_OwnershipChanged: | ||||
{ | { | ||||
if (!m_Unit) | if (!m_Unit) | ||||
break; | break; | ||||
const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg); | const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg); | ||||
m_Unit->GetModel().SetPlayerID(msgData.to); | m_Unit->GetModel().SetPlayerID(msgData.to); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | public: | ||||
virtual std::string GetAnimationName() const | virtual std::string GetAnimationName() const | ||||
{ | { | ||||
return m_AnimName; | return m_AnimName; | ||||
} | } | ||||
virtual void SelectAnimation(const std::string& name, bool once = false, fixed speed = fixed::FromInt(1)) | virtual void SelectAnimation(const std::string& name, bool once = false, fixed speed = fixed::FromInt(1)) | ||||
{ | { | ||||
m_AnimRunThreshold = fixed::Zero(); | |||||
m_AnimName = name; | m_AnimName = name; | ||||
m_AnimOnce = once; | m_AnimOnce = once; | ||||
m_AnimSpeed = speed; | m_AnimSpeed = speed; | ||||
m_SoundGroup = L""; | m_SoundGroup = L""; | ||||
m_AnimDesync = fixed::FromInt(1)/20; // TODO: make this an argument | m_AnimDesync = fixed::FromInt(1)/20; // TODO: make this an argument | ||||
m_AnimSyncRepeatTime = fixed::Zero(); | m_AnimSyncRepeatTime = fixed::Zero(); | ||||
m_AnimSyncOffsetTime = fixed::Zero(); | m_AnimSyncOffsetTime = fixed::Zero(); | ||||
SetVariant("animation", m_AnimName); | SetVariant("animation", m_AnimName); | ||||
CmpPtr<ICmpSound> cmpSound(GetEntityHandle()); | CmpPtr<ICmpSound> cmpSound(GetEntityHandle()); | ||||
if (cmpSound) | if (cmpSound) | ||||
m_SoundGroup = cmpSound->GetSoundGroup(wstring_from_utf8(m_AnimName)); | m_SoundGroup = cmpSound->GetSoundGroup(wstring_from_utf8(m_AnimName)); | ||||
if (!m_Unit || !m_Unit->GetAnimation() || !m_Unit->GetID()) | if (!m_Unit || !m_Unit->GetAnimation() || !m_Unit->GetID()) | ||||
return; | return; | ||||
m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str()); | m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str()); | ||||
} | } | ||||
virtual void SelectMovementAnimation(fixed runThreshold) | virtual void SelectMovementAnimation(const std::string& name, fixed speed) | ||||
{ | { | ||||
m_AnimRunThreshold = runThreshold; | ENSURE(name == "idle" || name == "walk" || name == "run"); | ||||
if (m_AnimName != "idle" && m_AnimName != "walk" && m_AnimName != "run") | |||||
return; | |||||
SelectAnimation(name, false, speed); | |||||
} | } | ||||
virtual void SetAnimationSyncRepeat(fixed repeattime) | virtual void SetAnimationSyncRepeat(fixed repeattime) | ||||
{ | { | ||||
m_AnimSyncRepeatTime = repeattime; | m_AnimSyncRepeatTime = repeattime; | ||||
if (m_Unit && m_Unit->GetAnimation()) | if (m_Unit && m_Unit->GetAnimation()) | ||||
m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat()); | m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat()); | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | private: | ||||
/// Helper method; initializes the model selection shape descriptor from XML. Factored out for readability of @ref Init. | /// Helper method; initializes the model selection shape descriptor from XML. Factored out for readability of @ref Init. | ||||
void InitSelectionShapeDescriptor(const CParamNode& paramNode); | void InitSelectionShapeDescriptor(const CParamNode& paramNode); | ||||
// ReloadActor is used when the actor or seed changes. | // ReloadActor is used when the actor or seed changes. | ||||
void ReloadActor(); | void ReloadActor(); | ||||
// ReloadUnitAnimation is used for a minimal reloading upon deserialization, when the actor and seed are identical. | // ReloadUnitAnimation is used for a minimal reloading upon deserialization, when the actor and seed are identical. | ||||
// It is also used by ReloadActor. | // It is also used by ReloadActor. | ||||
void ReloadUnitAnimation(); | void ReloadUnitAnimation(); | ||||
void Update(fixed turnLength); | |||||
}; | }; | ||||
REGISTER_COMPONENT_TYPE(VisualActor) | REGISTER_COMPONENT_TYPE(VisualActor) | ||||
// ------------------------------------------------------------------------------------------------------------------ | // ------------------------------------------------------------------------------------------------------------------ | ||||
void CCmpVisualActor::InitModel(const CParamNode& paramNode) | void CCmpVisualActor::InitModel(const CParamNode& paramNode) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 188 Lines • ▼ Show 20 Lines | void CCmpVisualActor::ReloadUnitAnimation() | ||||
m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str()); | m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str()); | ||||
// We'll lose the exact synchronisation but we should at least make sure it's going at the correct rate | // We'll lose the exact synchronisation but we should at least make sure it's going at the correct rate | ||||
if (!m_AnimSyncRepeatTime.IsZero()) | if (!m_AnimSyncRepeatTime.IsZero()) | ||||
m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat()); | m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat()); | ||||
if (!m_AnimSyncOffsetTime.IsZero()) | if (!m_AnimSyncOffsetTime.IsZero()) | ||||
m_Unit->GetAnimation()->SetAnimationSyncOffset(m_AnimSyncOffsetTime.ToFloat()); | m_Unit->GetAnimation()->SetAnimationSyncOffset(m_AnimSyncOffsetTime.ToFloat()); | ||||
} | } | ||||
void CCmpVisualActor::Update(fixed UNUSED(turnLength)) | |||||
{ | |||||
// This function is currently only used to update the animation if the speed in | |||||
// CCmpUnitMotion changes. This also only happens in the "special movement mode" | |||||
// triggered by SelectMovementAnimation. | |||||
// TODO: This should become event based, in order to save performance and to make the code | |||||
// far less hacky. We should also take into account the speed when the animation is different | |||||
// from the "special movement mode" walking animation. | |||||
// If we're not in the special movement mode, nothing to do. | |||||
if (m_AnimRunThreshold.IsZero()) | |||||
return; | |||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | |||||
if (!cmpPosition || !cmpPosition->IsInWorld()) | |||||
return; | |||||
CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetEntityHandle()); | |||||
if (!cmpUnitMotion) | |||||
return; | |||||
fixed speed = cmpUnitMotion->GetCurrentSpeed(); | |||||
std::string name; | |||||
if (speed.IsZero()) | |||||
{ | |||||
speed = fixed::FromFloat(1.f); | |||||
name = "idle"; | |||||
} | |||||
else | |||||
name = speed < m_AnimRunThreshold ? "walk" : "run"; | |||||
// Selecting the animation is going to reset the anim run threshold, so save it | |||||
fixed runThreshold = m_AnimRunThreshold; | |||||
SelectAnimation(name, false, speed); | |||||
m_AnimRunThreshold = runThreshold; | |||||
} |
Wildfire Games · Phabricator