Ticket #4270: fix-visualactor-save-reload.2.patch

File fix-visualactor-save-reload.2.patch, 6.9 KB (added by Itms, 8 years ago)
  • source/simulation2/components/CCmpVisualActor.cpp

     
    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
     
    205206       
    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
     
    232232        serialize.String("sound group", m_SoundGroup, 0, 256);
    233233        serialize.NumberFixed_Unbounded("anim desync", m_AnimDesync);
    234234        serialize.NumberFixed_Unbounded("anim sync repeat time", m_AnimSyncRepeatTime);
     235        serialize.NumberFixed_Unbounded("anim sync offset time", m_AnimSyncOffsetTime);
    235236
    236237        SerializeMap<SerializeString, SerializeString>()(serialize, "variation", m_VariantSelections);
    237238
     
    264265        // If we serialized a different seed or different actor, reload actor
    265266        if (oldSeed != GetActorSeed() || m_BaseActorName != m_ActorName)
    266267            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);
    274268        else
    275             SelectMovementAnimation(m_AnimRunThreshold);
     269            ReloadUnitAnimation();
    276270
    277         SetAnimationSyncRepeat(repeattime);
    278 
    279271        if (m_Unit)
    280272        {
    281273            CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle());
     
    287279    virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
    288280    {
    289281        // Quick exit for running in non-graphical mode
    290         if (m_Unit == NULL)
     282        if (!m_Unit)
    291283            return;
    292284
    293285        switch (msg.GetType())
     
    457449
    458450    virtual void SelectMovementAnimation(fixed runThreshold)
    459451    {
     452        SelectAnimation("walk", false, fixed::FromFloat(1.f), L"");
    460453        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         }
    468454    }
    469455
    470456    virtual void SetAnimationSyncRepeat(fixed repeattime)
     
    480466
    481467    virtual void SetAnimationSyncOffset(fixed actiontime)
    482468    {
     469        m_AnimSyncOffsetTime = actiontime;
     470
    483471        if (m_Unit)
    484472        {
    485473            if (m_Unit->GetAnimation())
    486                 m_Unit->GetAnimation()->SetAnimationSyncOffset(actiontime.ToFloat());
     474                m_Unit->GetAnimation()->SetAnimationSyncOffset(m_AnimSyncOffsetTime.ToFloat());
    487475        }
    488476    }
    489477
     
    546534    /// Helper method; initializes the model selection shape descriptor from XML. Factored out for readability of @ref Init.
    547535    void InitSelectionShapeDescriptor(const CParamNode& paramNode);
    548536
     537    // ReloadActor is used when the actor or seed changes.
    549538    void ReloadActor();
     539    // ReloadUnitAnimation is used for a minimal reloading upon deserialization, when the actor and seed are identical.
     540    // It is also used by ReloadActor.
     541    void ReloadUnitAnimation();
    550542
    551543    void Update(fixed turnLength);
    552544};
     
    720712
    721713    InitModel(node->GetChild("VisualActor"));
    722714
    723     m_Unit->SetEntitySelection(m_VariantSelections);
     715    ReloadUnitAnimation();
    724716
    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());
    732 
    733717    m_Unit->GetModel().SetShadingColor(shading);
    734718
    735719    m_Unit->GetModel().SetPlayerID(playerID);
     
    743727    }
    744728}
    745729
    746 void CCmpVisualActor::Update(fixed UNUSED(turnLength))
     730void CCmpVisualActor::ReloadUnitAnimation()
    747731{
    748732    if (!m_Unit)
    749733        return;
    750734
    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;
     735    m_Unit->SetEntitySelection(m_VariantSelections);
    757736
    758         CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetEntityHandle());
    759         if (!cmpUnitMotion)
    760             return;
     737    if (!m_Unit->GetAnimation())
     738        return;
    761739
    762         float speed = cmpUnitMotion->GetCurrentSpeed().ToFloat();
     740    m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
    763741
    764         std::string name;
    765         if (speed == 0.0f)
    766             name = "idle";
    767         else
    768             name = (speed < m_AnimRunThreshold.ToFloat()) ? "walk" : "run";
     742    // We'll lose the exact synchronisation but we should at least make sure it's going at the correct rate
     743    if (!m_AnimSyncRepeatTime.IsZero())
     744        m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat());
     745    if (!m_AnimSyncOffsetTime.IsZero())
     746        m_Unit->GetAnimation()->SetAnimationSyncOffset(m_AnimSyncOffsetTime.ToFloat());
     747}
    769748
    770         std::map<std::string, std::string>::const_iterator it = m_AnimOverride.find(name);
    771         if (it != m_AnimOverride.end())
    772             name = it->second;
     749void CCmpVisualActor::Update(fixed UNUSED(turnLength))
     750{
     751    // This function is currently only used to update the animation if the speed in
     752    // CCmpUnitMotion changes. This also only happens in the "special movement mode"
     753    // triggered by SelectMovementAnimation.
    773754
    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         }
     755    // TODO: This should become event based, in order to save performance and to make the code
     756    // far less hacky. We should also take into account the speed when the animation is different
     757    // from the "special movement mode" walking animation.
     758
     759    // If we're not in the special movement mode, nothing to do.
     760    if (m_AnimRunThreshold.IsZero())
     761        return;
     762
     763    CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
     764    if (!cmpPosition || !cmpPosition->IsInWorld())
     765        return;
     766
     767    CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetEntityHandle());
     768    if (!cmpUnitMotion)
     769        return;
     770
     771    fixed speed = cmpUnitMotion->GetCurrentSpeed();
     772    std::string name;
     773
     774    if (speed.IsZero())
     775    {
     776        speed = fixed::FromFloat(1.f);
     777        name = "idle";
    782778    }
     779    else
     780        name = (speed < m_AnimRunThreshold) ? "walk" : "run";
     781
     782    std::map<std::string, std::string>::const_iterator it = m_AnimOverride.find(name);
     783    if (it != m_AnimOverride.end())
     784        name = it->second;
     785
     786    // Selecting the animation is going to reset the anim run threshold, so save it
     787    fixed runThreshold = m_AnimRunThreshold;
     788    SelectAnimation(name, false, speed, L"");
     789    m_AnimRunThreshold = runThreshold;
    783790}