Ticket #4270: visual-actor-squash.patch

File visual-actor-squash.patch, 11.4 KB (added by Itms, 8 years ago)
  • source/simulation2/components/CCmpUnitMotion.cpp

    diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp
    index 741c749..59552a2 100644
    a b public:  
    339339        serialize.NumberFixed_Unbounded("target max range", m_TargetMaxRange);
    340340
    341341        serialize.NumberFixed_Unbounded("speed", m_Speed);
     342        serialize.NumberFixed_Unbounded("current speed", m_CurSpeed);
    342343
    343344        serialize.Bool("moving", m_Moving);
    344345        serialize.Bool("facePointAfterMove", m_FacePointAfterMove);
  • source/simulation2/components/CCmpVisualActor.cpp

    diff --git a/source/simulation2/components/CCmpVisualActor.cpp b/source/simulation2/components/CCmpVisualActor.cpp
    index 0d701d5..7c65360 100644
    a b private:  
    8181    std::wstring m_SoundGroup;
    8282    fixed m_AnimDesync;
    8383    fixed m_AnimSyncRepeatTime; // 0.0 if not synced
     84    fixed m_AnimSyncOffsetTime;
    8485
    8586    std::map<CStr, CStr> m_VariantSelections;
    8687
    public:  
    202203
    203204        m_VisibleInAtlasOnly = paramNode.GetChild("VisibleInAtlasOnly").ToBool();
    204205        m_IsActorOnly = paramNode.GetChild("ActorOnly").IsOk();
    205        
     206
    206207        InitModel(paramNode);
    207208
    208         // We need to select animation even if graphics are disabled, as this modifies serialized state
    209209        SelectAnimation("idle", false, fixed::FromInt(1), L"");
    210210    }
    211211
    public:  
    225225        serialize.NumberFixed_Unbounded("g", m_G);
    226226        serialize.NumberFixed_Unbounded("b", m_B);
    227227
     228        SerializeMap<SerializeString, SerializeString>()(serialize, "anim overrides", m_AnimOverride);
     229
    228230        serialize.NumberFixed_Unbounded("anim run threshold", m_AnimRunThreshold);
    229231        serialize.StringASCII("anim name", m_AnimName, 0, 256);
    230232        serialize.Bool("anim once", m_AnimOnce);
    public:  
    232234        serialize.String("sound group", m_SoundGroup, 0, 256);
    233235        serialize.NumberFixed_Unbounded("anim desync", m_AnimDesync);
    234236        serialize.NumberFixed_Unbounded("anim sync repeat time", m_AnimSyncRepeatTime);
     237        serialize.NumberFixed_Unbounded("anim sync offset time", m_AnimSyncOffsetTime);
    235238
    236239        SerializeMap<SerializeString, SerializeString>()(serialize, "variation", m_VariantSelections);
    237240
    public:  
    264267        // If we serialized a different seed or different actor, reload actor
    265268        if (oldSeed != GetActorSeed() || m_BaseActorName != m_ActorName)
    266269            ReloadActor();
    267         else if (m_Unit)
    268             m_Unit->SetEntitySelection(m_VariantSelections);
    269 
    270         fixed repeattime = m_AnimSyncRepeatTime; // save because SelectAnimation overwrites it
    271 
    272         if (m_AnimRunThreshold.IsZero())
    273             SelectAnimation(m_AnimName, m_AnimOnce, m_AnimSpeed, m_SoundGroup);
    274270        else
    275             SelectMovementAnimation(m_AnimRunThreshold);
    276 
    277         SetAnimationSyncRepeat(repeattime);
     271            ReloadUnitAnimation();
    278272
    279273        if (m_Unit)
    280274        {
    public:  
    286280
    287281    virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
    288282    {
    289         // Quick exit for running in non-graphical mode
    290         if (m_Unit == NULL)
    291             return;
    292 
    293283        switch (msg.GetType())
    294284        {
    295285        case MT_Update_Final:
    public:  
    300290        }
    301291        case MT_OwnershipChanged:
    302292        {
     293            if (!m_Unit)
     294                break;
     295
    303296            const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg);
    304297            m_Unit->GetModel().SetPlayerID(msgData.to);
    305298            break;
    306299        }
    307300        case MT_TerrainChanged:
    308301        {
     302            if (!m_Unit)
     303                break;
     304
    309305            const CMessageTerrainChanged& msgData = static_cast<const CMessageTerrainChanged&> (msg);
    310306            m_Unit->GetModel().SetTerrainDirty(msgData.i0, msgData.j0, msgData.i1, msgData.j1);
    311307            break;
    public:  
    420416    virtual void SetVariant(const CStr& key, const CStr& selection)
    421417    {
    422418        m_VariantSelections[key] = selection;
    423         if (!m_Unit)
    424             return;
    425         m_Unit->SetEntitySelection(key, selection);
     419
     420        if (m_Unit)
     421            m_Unit->SetEntitySelection(key, selection);
    426422    }
    427423
    428424    virtual void SelectAnimation(const std::string& name, bool once, fixed speed, const std::wstring& soundgroup)
    public:  
    435431        m_AnimDesync = fixed::FromInt(1)/20; // TODO: make this an argument
    436432        m_AnimSyncRepeatTime = fixed::Zero();
    437433
    438         if (m_Unit)
    439         {
    440             SetVariant("animation", m_AnimName);
    441             if (m_Unit->GetAnimation())
    442                 m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
    443         }
     434        SetVariant("animation", m_AnimName);
     435
     436        if (m_Unit && m_Unit->GetAnimation())
     437            m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
    444438    }
    445439
    446440    virtual void ReplaceMoveAnimation(const std::string& name, const std::string& replace)
    public:  
    457451
    458452    virtual void SelectMovementAnimation(fixed runThreshold)
    459453    {
     454        SelectAnimation("walk", false, fixed::FromFloat(1.f), L"");
    460455        m_AnimRunThreshold = runThreshold;
    461 
    462         if (m_Unit)
    463         {
    464             SetVariant("animation", "walk");
    465             if (m_Unit->GetAnimation())
    466                 m_Unit->GetAnimation()->SetAnimationState("walk", false, 1.f, 0.f, L"");
    467         }
    468456    }
    469457
    470458    virtual void SetAnimationSyncRepeat(fixed repeattime)
    471459    {
    472460        m_AnimSyncRepeatTime = repeattime;
    473461
    474         if (m_Unit)
    475         {
    476             if (m_Unit->GetAnimation())
    477                 m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat());
    478         }
     462        if (m_Unit && m_Unit->GetAnimation())
     463            m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat());
    479464    }
    480465
    481466    virtual void SetAnimationSyncOffset(fixed actiontime)
    482467    {
    483         if (m_Unit)
    484         {
    485             if (m_Unit->GetAnimation())
    486                 m_Unit->GetAnimation()->SetAnimationSyncOffset(actiontime.ToFloat());
    487         }
     468        m_AnimSyncOffsetTime = actiontime;
     469
     470        if (m_Unit && m_Unit->GetAnimation())
     471            m_Unit->GetAnimation()->SetAnimationSyncOffset(m_AnimSyncOffsetTime.ToFloat());
    488472    }
    489473
    490474    virtual void SetShadingColor(fixed r, fixed g, fixed b, fixed a)
    public:  
    504488    virtual void SetVariable(const std::string& name, float value)
    505489    {
    506490        if (m_Unit)
    507         {
    508491            m_Unit->GetModel().SetEntityVariable(name, value);
    509         }
    510492    }
    511493
    512494    virtual u32 GetActorSeed()
    513495    {
    514496        return m_Seed;
    515497    }
    516    
     498
    517499    virtual void SetActorSeed(u32 seed)
    518500    {
    519501        if (seed == m_Seed)
    private:  
    546528    /// Helper method; initializes the model selection shape descriptor from XML. Factored out for readability of @ref Init.
    547529    void InitSelectionShapeDescriptor(const CParamNode& paramNode);
    548530
     531    // ReloadActor is used when the actor or seed changes.
    549532    void ReloadActor();
     533    // ReloadUnitAnimation is used for a minimal reloading upon deserialization, when the actor and seed are identical.
     534    // It is also used by ReloadActor.
     535    void ReloadUnitAnimation();
    550536
    551537    void Update(fixed turnLength);
    552538};
    void CCmpVisualActor::InitSelectionShapeDescriptor(const CParamNode& paramNode)  
    653639                float size0 = fpSize0.ToFloat();
    654640                float size1 = fpSize1.ToFloat();
    655641
    656                 // TODO: we should properly distinguish between CIRCLE and SQUARE footprint shapes here, but since cylinders 
    657                 // aren't implemented yet and are almost indistinguishable from boxes for small enough sizes anyway, 
    658                 // we'll just use boxes for either case. However, for circular footprints the size0 and size1 values both 
    659                 // represent the radius, so we do have to adjust them to match the size1 and size0's of square footprints 
     642                // TODO: we should properly distinguish between CIRCLE and SQUARE footprint shapes here, but since cylinders
     643                // aren't implemented yet and are almost indistinguishable from boxes for small enough sizes anyway,
     644                // we'll just use boxes for either case. However, for circular footprints the size0 and size1 values both
     645                // represent the radius, so we do have to adjust them to match the size1 and size0's of square footprints
    660646                // (which represent the full width and depth).
    661647                if (fpShape == ICmpFootprint::CIRCLE)
    662648                {
    void CCmpVisualActor::ReloadActor()  
    720706
    721707    InitModel(node->GetChild("VisualActor"));
    722708
    723     m_Unit->SetEntitySelection(m_VariantSelections);
    724 
    725     if (m_Unit->GetAnimation())
    726         m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
    727 
    728     // We'll lose the exact synchronisation but we should at least make sure it's going at the correct rate
    729     if (!m_AnimSyncRepeatTime.IsZero())
    730         if (m_Unit->GetAnimation())
    731             m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat());
     709    ReloadUnitAnimation();
    732710
    733711    m_Unit->GetModel().SetShadingColor(shading);
    734712
    void CCmpVisualActor::ReloadActor()  
    743721    }
    744722}
    745723
    746 void CCmpVisualActor::Update(fixed UNUSED(turnLength))
     724void CCmpVisualActor::ReloadUnitAnimation()
    747725{
    748726    if (!m_Unit)
    749727        return;
    750728
    751     // If we're in the special movement mode, select an appropriate animation
    752     if (!m_AnimRunThreshold.IsZero())
    753     {
    754         CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
    755         if (!cmpPosition || !cmpPosition->IsInWorld())
    756             return;
     729    m_Unit->SetEntitySelection(m_VariantSelections);
    757730
    758         CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetEntityHandle());
    759         if (!cmpUnitMotion)
    760             return;
     731    if (!m_Unit->GetAnimation())
     732        return;
    761733
    762         float speed = cmpUnitMotion->GetCurrentSpeed().ToFloat();
     734    m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
    763735
    764         std::string name;
    765         if (speed == 0.0f)
    766             name = "idle";
    767         else
    768             name = (speed < m_AnimRunThreshold.ToFloat()) ? "walk" : "run";
     736    // We'll lose the exact synchronisation but we should at least make sure it's going at the correct rate
     737    if (!m_AnimSyncRepeatTime.IsZero())
     738        m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat());
     739    if (!m_AnimSyncOffsetTime.IsZero())
     740        m_Unit->GetAnimation()->SetAnimationSyncOffset(m_AnimSyncOffsetTime.ToFloat());
     741}
    769742
    770         std::map<std::string, std::string>::const_iterator it = m_AnimOverride.find(name);
    771         if (it != m_AnimOverride.end())
    772             name = it->second;
     743void CCmpVisualActor::Update(fixed UNUSED(turnLength))
     744{
     745    // This function is currently only used to update the animation if the speed in
     746    // CCmpUnitMotion changes. This also only happens in the "special movement mode"
     747    // triggered by SelectMovementAnimation.
    773748
    774         SetVariant("animation", name);
    775         if (m_Unit->GetAnimation())
    776         {
    777             if (speed == 0.0f)
    778                 m_Unit->GetAnimation()->SetAnimationState(name, false, 1.f, 0.f, L"");
    779             else
    780                 m_Unit->GetAnimation()->SetAnimationState(name, false, speed, 0.f, L"");
    781         }
     749    // TODO: This should become event based, in order to save performance and to make the code
     750    // far less hacky. We should also take into account the speed when the animation is different
     751    // from the "special movement mode" walking animation.
     752
     753    // If we're not in the special movement mode, nothing to do.
     754    if (m_AnimRunThreshold.IsZero())
     755        return;
     756
     757    CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
     758    if (!cmpPosition || !cmpPosition->IsInWorld())
     759        return;
     760
     761    CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetEntityHandle());
     762    if (!cmpUnitMotion)
     763        return;
     764
     765    fixed speed = cmpUnitMotion->GetCurrentSpeed();
     766    std::string name;
     767
     768    if (speed.IsZero())
     769    {
     770        speed = fixed::FromFloat(1.f);
     771        name = "idle";
    782772    }
     773    else
     774        name = speed < m_AnimRunThreshold ? "walk" : "run";
     775
     776    std::map<std::string, std::string>::const_iterator it = m_AnimOverride.find(name);
     777    if (it != m_AnimOverride.end())
     778        name = it->second;
     779
     780    // Selecting the animation is going to reset the anim run threshold, so save it
     781    fixed runThreshold = m_AnimRunThreshold;
     782    SelectAnimation(name, false, speed, L"");
     783    m_AnimRunThreshold = runThreshold;
    783784}