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

File fix-visualactor-save-reload.3.patch, 8.9 KB (added by Itms, 8 years ago)

squashed version for testing

  • source/simulation2/components/CCmpUnitMotion.cpp

     
    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

     
    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
     
    225225        serialize.NumberFixed_Unbounded("g", m_G);
    226226        serialize.NumberFixed_Unbounded("b", m_B);
    227227
     228        SerializeMap<SerializeString, SerializeString>()(serialize, "anim overrrides", 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);
     
    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
     
    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);
     271            ReloadUnitAnimation();
    276272
    277         SetAnimationSyncRepeat(repeattime);
    278 
    279273        if (m_Unit)
    280274        {
    281275            CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle());
     
    287281    virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
    288282    {
    289283        // Quick exit for running in non-graphical mode
    290         if (m_Unit == NULL)
    291             return;
     284        //if (!m_Unit)
     285        //  return;
    292286
    293287        switch (msg.GetType())
    294288        {
     
    301295        case MT_OwnershipChanged:
    302296        {
    303297            const CMessageOwnershipChanged& msgData = static_cast<const CMessageOwnershipChanged&> (msg);
    304             m_Unit->GetModel().SetPlayerID(msgData.to);
     298            if (m_Unit) { m_Unit->GetModel().SetPlayerID(msgData.to); }
    305299            break;
    306300        }
    307301        case MT_TerrainChanged:
    308302        {
    309303            const CMessageTerrainChanged& msgData = static_cast<const CMessageTerrainChanged&> (msg);
    310             m_Unit->GetModel().SetTerrainDirty(msgData.i0, msgData.j0, msgData.i1, msgData.j1);
     304            if (m_Unit) { m_Unit->GetModel().SetTerrainDirty(msgData.i0, msgData.j0, msgData.i1, msgData.j1); }
    311305            break;
    312306        }
    313307        case MT_ValueModification:
     
    435429        m_AnimDesync = fixed::FromInt(1)/20; // TODO: make this an argument
    436430        m_AnimSyncRepeatTime = fixed::Zero();
    437431
     432        SetVariant("animation", m_AnimName);
     433
    438434        if (m_Unit)
    439435        {
    440             SetVariant("animation", m_AnimName);
    441436            if (m_Unit->GetAnimation())
    442437                m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
    443438        }
     
    457452
    458453    virtual void SelectMovementAnimation(fixed runThreshold)
    459454    {
     455        SelectAnimation("walk", false, fixed::FromFloat(1.f), L"");
    460456        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         }
    468457    }
    469458
    470459    virtual void SetAnimationSyncRepeat(fixed repeattime)
     
    480469
    481470    virtual void SetAnimationSyncOffset(fixed actiontime)
    482471    {
     472        m_AnimSyncOffsetTime = actiontime;
     473
    483474        if (m_Unit)
    484475        {
    485476            if (m_Unit->GetAnimation())
    486                 m_Unit->GetAnimation()->SetAnimationSyncOffset(actiontime.ToFloat());
     477                m_Unit->GetAnimation()->SetAnimationSyncOffset(m_AnimSyncOffsetTime.ToFloat());
    487478        }
    488479    }
    489480
     
    546537    /// Helper method; initializes the model selection shape descriptor from XML. Factored out for readability of @ref Init.
    547538    void InitSelectionShapeDescriptor(const CParamNode& paramNode);
    548539
     540    // ReloadActor is used when the actor or seed changes.
    549541    void ReloadActor();
     542    // ReloadUnitAnimation is used for a minimal reloading upon deserialization, when the actor and seed are identical.
     543    // It is also used by ReloadActor.
     544    void ReloadUnitAnimation();
    550545
    551546    void Update(fixed turnLength);
    552547};
     
    720715
    721716    InitModel(node->GetChild("VisualActor"));
    722717
    723     m_Unit->SetEntitySelection(m_VariantSelections);
     718    ReloadUnitAnimation();
    724719
    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 
    733720    m_Unit->GetModel().SetShadingColor(shading);
    734721
    735722    m_Unit->GetModel().SetPlayerID(playerID);
     
    743730    }
    744731}
    745732
    746 void CCmpVisualActor::Update(fixed UNUSED(turnLength))
     733void CCmpVisualActor::ReloadUnitAnimation()
    747734{
    748735    if (!m_Unit)
    749736        return;
    750737
    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;
     738    m_Unit->SetEntitySelection(m_VariantSelections);
    757739
    758         CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetEntityHandle());
    759         if (!cmpUnitMotion)
    760             return;
     740    if (!m_Unit->GetAnimation())
     741        return;
    761742
    762         float speed = cmpUnitMotion->GetCurrentSpeed().ToFloat();
     743    m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str());
    763744
    764         std::string name;
    765         if (speed == 0.0f)
    766             name = "idle";
    767         else
    768             name = (speed < m_AnimRunThreshold.ToFloat()) ? "walk" : "run";
     745    // We'll lose the exact synchronisation but we should at least make sure it's going at the correct rate
     746    if (!m_AnimSyncRepeatTime.IsZero())
     747        m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat());
     748    if (!m_AnimSyncOffsetTime.IsZero())
     749        m_Unit->GetAnimation()->SetAnimationSyncOffset(m_AnimSyncOffsetTime.ToFloat());
     750}
    769751
    770         std::map<std::string, std::string>::const_iterator it = m_AnimOverride.find(name);
    771         if (it != m_AnimOverride.end())
    772             name = it->second;
     752void CCmpVisualActor::Update(fixed UNUSED(turnLength))
     753{
     754    // This function is currently only used to update the animation if the speed in
     755    // CCmpUnitMotion changes. This also only happens in the "special movement mode"
     756    // triggered by SelectMovementAnimation.
    773757
    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         }
     758    // TODO: This should become event based, in order to save performance and to make the code
     759    // far less hacky. We should also take into account the speed when the animation is different
     760    // from the "special movement mode" walking animation.
     761
     762    // If we're not in the special movement mode, nothing to do.
     763    if (m_AnimRunThreshold.IsZero())
     764        return;
     765
     766    CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
     767    if (!cmpPosition || !cmpPosition->IsInWorld())
     768        return;
     769
     770    CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetEntityHandle());
     771    if (!cmpUnitMotion)
     772        return;
     773
     774    fixed speed = cmpUnitMotion->GetCurrentSpeed();
     775    std::string name;
     776
     777    if (speed.IsZero())
     778    {
     779        speed = fixed::FromFloat(1.f);
     780        name = "idle";
    782781    }
     782    else
     783        name = (speed < m_AnimRunThreshold) ? "walk" : "run";
     784
     785    std::map<std::string, std::string>::const_iterator it = m_AnimOverride.find(name);
     786    if (it != m_AnimOverride.end())
     787        name = it->second;
     788
     789    // Selecting the animation is going to reset the anim run threshold, so save it
     790    fixed runThreshold = m_AnimRunThreshold;
     791    SelectAnimation(name, false, speed, L"");
     792    m_AnimRunThreshold = runThreshold;
    783793}