Ticket #2324: ActorFormat.3.patch

File ActorFormat.3.patch, 22.7 KB (added by wraitii, 8 years ago)
  • source/graphics/UnitAnimation.h

     
    1 /* Copyright (C) 2011 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    9595    struct SModelAnimState
    9696    {
    9797        CModel* model;
     98        const CObjectEntry* object;
    9899        std::vector<CSkeletonAnim*> anims;
     100        CStr animName;
    99101        size_t animIdx;
    100102        float time;
    101103        bool pastLoadPos;
     
    111113     */
    112114    bool m_AnimStatesAreStatic;
    113115
    114     void AddModel(CModel* model, const CObjectEntry* object);
     116    void AddModel(CModel* model, const CObjectEntry* object, bool useName = false, CStr* animName = NULL);
    115117
     118    /**
     119     * called in AddModel and Update.
     120     * Will try to choose animations, fitting the animName if needed.
     121     */
     122    void pickAnim(SModelAnimState* state, const CStr& stateName, bool useName = false, CStr* animName = NULL, bool changeName = false);
     123   
    116124    entity_id_t m_Entity;
    117125    CModel* m_Model;
    118126    const CObjectEntry* m_Object;
  • source/graphics/UnitAnimation.cpp

     
    1 /* Copyright (C) 2012 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    5252    m_Entity = ent;
    5353}
    5454
    55 void CUnitAnimation::AddModel(CModel* model, const CObjectEntry* object)
     55void CUnitAnimation::AddModel(CModel* model, const CObjectEntry* object, bool useName /* = false */, CStr* animName /* = NULL */)
    5656{
    5757    SModelAnimState state;
    5858
    59     state.anims = object->GetAnimations(m_State);
     59    ENSURE(!object->GetStateAnimations("idle").empty()); // there must always be an idle animation
    6060
    61     if (state.anims.empty())
    62         state.anims = object->GetAnimations("idle");
    63     ENSURE(!state.anims.empty()); // there must always be an idle animation
    64 
    6561    state.model = model;
    66     state.animIdx = rand(0, state.anims.size());
     62    state.object = object;
    6763    state.time = 0.f;
    6864    state.pastLoadPos = false;
    6965    state.pastActionPos = false;
    7066    state.pastSoundPos = false;
    7167
     68    this->pickAnim(&state, m_State, useName, animName);
     69   
    7270    m_AnimStates.push_back(state);
    7371
    7472    model->SetAnimation(state.anims[state.animIdx], !m_Looping);
    7573
    7674    // Detect if this unit has any non-static animations
    77     for (size_t i = 0; i < state.anims.size(); i++)
    78         if (state.anims[i]->m_AnimDef != NULL)
     75    for (const CSkeletonAnim* animation : state.anims)
     76        if (animation->m_AnimDef != NULL)
    7977            m_AnimStatesAreStatic = false;
    8078
    8179    // Recursively add all props
    82     const std::vector<CModel::Prop>& props = model->GetProps();
    83     for (std::vector<CModel::Prop>::const_iterator it = props.begin(); it != props.end(); ++it)
     80    for (const CModel::Prop& prop : model->GetProps())
    8481    {
    85         CModel* propModel = it->m_Model->ToCModel();
     82        CModel* propModel = prop.m_Model->ToCModel();
    8683        if (propModel)
    87             AddModel(propModel, it->m_ObjectEntry);
     84            AddModel(propModel, prop.m_ObjectEntry, true, &state.animName);
    8885    }
    8986}
    9087
     88void CUnitAnimation::pickAnim(SModelAnimState* state, const CStr& stateName, bool useName /* = false */, CStr* animName /* = NULL */, bool changeName /* = false */)
     89{
     90    ENSURE(!(animName == NULL && useName));
     91   
     92        // get the proper animations.
     93    if (useName)
     94        state->anims = state->object->GetAnimations(stateName, *animName);
     95    else
     96        state->anims = state->object->GetStateAnimations(stateName);
     97
     98    // if empty and we used a specific anim name, try something more general
     99    // else try the idle animation, there is at least one by construction.
     100    if (state->anims.size() == 0)
     101    {
     102        if (useName)
     103            state->anims = state->object->GetAnimations(stateName, *animName);
     104        useName = false;
     105        if (state->anims.size() == 0)
     106            state->anims = state->object->GetStateAnimations("idle");
     107    }
     108
     109    // choose an animation. This is done randomly, but we respect the frequencies defined.
     110    // in case frequencies are all 0, we pick the first.
     111    size_t total = 0;
     112    if (useName)
     113        total = state->object->GetStateAnimFrequency(stateName, *animName);
     114    else
     115        total = state->object->GetStateFrequency(stateName);
     116   
     117    size_t sum = 0;
     118    size_t randv = 0;
     119    if (total != 0)
     120        randv = rand(1, total+1);
     121   
     122    for (size_t i = 0; i < state->anims.size(); ++i)
     123    {
     124        sum += state->anims[i]->m_Frequency;
     125        if (sum < randv)
     126            continue;
     127
     128        if (i != state->animIdx || state->anims[i]->m_AnimationName != state->animName)
     129        {
     130            state->animIdx = i;
     131            state->animName = state->anims[i]->m_AnimationName;
     132            state->model->SetAnimation(state->anims[state->animIdx], !m_Looping);
     133        }
     134       
     135        if (changeName)
     136            *animName = state->animName;
     137       
     138        break;
     139    }
     140}
     141
     142
    91143void CUnitAnimation::ReloadUnit(CModel* model, const CObjectEntry* object)
    92144{
    93145    m_Model = model;
     
    160212        return;
    161213
    162214    // Advance all of the prop models independently
     215    SModelAnimState* needLooping[m_AnimStates.size()];
     216    size_t looped = 0;
     217
    163218    for (std::vector<SModelAnimState>::iterator it = m_AnimStates.begin(); it != m_AnimStates.end(); ++it)
    164219    {
    165220        CSkeletonAnimDef* animDef = it->anims[it->animIdx]->m_AnimDef;
     
    228283        else if (m_Looping)
    229284        {
    230285            // If we've finished the current animation and want to loop...
    231 
     286            needLooping[looped++] = &(*it);
     287           
    232288            // Wrap the timer around
    233289            it->time = fmod(it->time + advance, duration);
    234 
    235             // If there's a choice of multiple animations, pick a new random one
    236             if (it->anims.size() > 1)
    237             {
    238                 size_t newAnimIdx = rand(0, it->anims.size());
    239                 if (newAnimIdx != it->animIdx)
    240                 {
    241                     it->animIdx = newAnimIdx;
    242                     it->model->SetAnimation(it->anims[it->animIdx], !m_Looping);
    243                 }
    244             }
    245 
     290           
    246291            it->pastActionPos = false;
    247292            it->pastLoadPos = false;
    248293            it->pastSoundPos = false;
    249 
    250             it->model->UpdateTo(it->time);
    251294        }
    252295        else
    253296        {
     
    262305            }
    263306        }
    264307    }
     308   
     309   
     310    if (looped == 0)
     311        return;
     312   
     313    // to keep our props in synch (well those that can be)
     314    // we'll update them separately.
     315    CStr animName = "";
     316    CStr& stateName = m_State;
     317
     318    // the first one is the initializer so out of the loop.
     319    SModelAnimState* oState = needLooping[0];
     320    this->pickAnim(oState, stateName, false, &animName, true);
     321    oState->model->UpdateTo(oState->time);
     322   
     323    for (size_t i = 1; i < looped; ++i)
     324    {
     325        SModelAnimState* state = needLooping[i];
     326       
     327        this->pickAnim(state, stateName, true, &animName);
     328       
     329        state->model->UpdateTo(state->time);
     330    }
    265331}
  • source/graphics/SkeletonAnim.h

     
    1 /* Copyright (C) 2010 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    3333{
    3434public:
    3535    // the name of the action which uses this animation (e.g. "idle")
    36     CStr m_Name;
     36    CStr m_StateName;
     37    // the name of the animation ("" is default, and you can then specify)
     38    CStr m_AnimationName;
    3739    // the raw animation frame data; may be NULL if this is a static 'animation'
    3840    CSkeletonAnimDef* m_AnimDef;
    3941    // speed at which this animation runs, as a factor of the AnimDef default speed
    4042    // (treated as 0 if m_AnimDef == NULL)
    4143    float m_Speed;
     44    // how often this animation will be played.
     45    size_t m_Frequency;
    4246    // Times during the animation at which the interesting bits happen,
    4347    // as msec times in the range [0, AnimDef->GetDuration],
    4448    // or special value -1 if unspecified.
  • source/graphics/ObjectEntry.h

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    6363
    6464    std::wstring m_ProjectileModelName;
    6565
    66     // Returns a randomly-chosen animation matching the given name.
     66    // Returns a randomly-chosen animation from a given state
    6767    // If none is found, returns NULL.
    68     CSkeletonAnim* GetRandomAnimation(const CStr& animationName) const;
     68    CSkeletonAnim* GetRandomAnimation(const CStr& stateName) const;
    6969
    70     // Returns all the animations matching the given name.
    71     std::vector<CSkeletonAnim*> GetAnimations(const CStr& animationName) const;
     70    // Returns all the animations for a given state and name
     71    std::vector<CSkeletonAnim*> GetAnimations(const CStr& stateName, const CStr& animationName) const;
     72   
     73    // Returns all the animations for a given state.
     74    std::vector<CSkeletonAnim*> GetStateAnimations(const CStr& stateName) const;
    7275
     76    // Returns total frequencies for a state and anim name
     77    size_t GetStateAnimFrequency(const CStr& stateName, const CStr& animationName) const;
     78
     79    // Returns total frequencies for a state
     80    size_t GetStateFrequency(const CStr& stateName) const;
     81
    7382    // corresponding model
    7483    CModelAbstract* m_Model;
    7584
     
    8089private:
    8190    CSimulation2& m_Simulation;
    8291
    83     typedef std::multimap<CStr, CSkeletonAnim*> SkeletonAnimMap;
    84     SkeletonAnimMap m_Animations;
     92    // stores animations for each state. We'll iterate if we need to find a specific one.
     93    // TODO: maybe someday if we have lots of anims use something cleverer.
     94    typedef std::multimap<CStr, CSkeletonAnim*> SkeletonStateAnimMap;
     95    SkeletonStateAnimMap m_StateAnimations;
     96    typedef std::map<CStr, size_t> SkeletonStateFrequencies;
     97    SkeletonStateFrequencies m_StateFrequencies;
    8598        // TODO: something more memory-efficient than storing loads of similar strings for each unit?
    8699};
    87100
  • source/graphics/ObjectEntry.cpp

     
    4646
    4747CObjectEntry::~CObjectEntry()
    4848{
    49     for (const std::pair<CStr, CSkeletonAnim*>& anim : m_Animations)
     49    for (const std::pair<CStr, CSkeletonAnim*>& anim : m_StateAnimations)
    5050        delete anim.second;
    5151
    5252    delete m_Model;
     
    145145        model->GetMaterial().AddSampler(CMaterial::TextureSampler(samp.m_SamplerName, texture));
    146146    }
    147147
    148     const std::vector<CStrIntern>& requiredSamplers = model->GetMaterial().GetRequiredSampler();
    149     for (const auto& requSampName : requiredSamplers)
     148    for (const auto& requSampName : model->GetMaterial().GetRequiredSampler())
    150149    {
    151150        if (std::find_if(m_Samplers.begin(), m_Samplers.end(),
    152151                         [&](CObjectBase::Samp sampler) { return sampler.m_SamplerName == requSampName; }) == m_Samplers.end())
     
    159158    // load the animations
    160159    for (std::multimap<CStr, CObjectBase::Anim>::iterator it = variation.anims.begin(); it != variation.anims.end(); ++it)
    161160    {
    162         CStr name = it->first.LowerCase();
     161        CStr stateName = it->first.LowerCase();
    163162
    164         if (!it->second.m_FileName.empty())
    165         {
    166             CSkeletonAnim* anim = model->BuildAnimation(it->second.m_FileName, name, it->second.m_Speed, it->second.m_ActionPos, it->second.m_ActionPos2, it->second.m_SoundPos);
    167             if (anim)
    168                 m_Animations.insert(std::make_pair(name, anim));
     163        if (it->second.m_FileName.empty())
     164            continue;
     165
     166        CSkeletonAnim* anim = model->BuildAnimation(it->second.m_FileName, stateName, it->second.m_AnimName, it->second.m_Speed,
     167                                                    it->second.m_Frequency, it->second.m_ActionPos, it->second.m_ActionPos2, it->second.m_SoundPos);
     168        if (!anim)
     169            continue;
     170
     171        m_StateAnimations.insert(std::make_pair(stateName, anim));
     172        SkeletonStateFrequencies::const_iterator idx = m_StateFrequencies.find(stateName);
     173        if (idx == m_StateFrequencies.end())
     174            m_StateFrequencies[stateName] = it->second.m_Frequency;
     175        else
     176            m_StateFrequencies[stateName] += it->second.m_Frequency;
    169177        }
    170     }
    171178
    172179    // ensure there's always an idle animation
    173     if (m_Animations.find("idle") == m_Animations.end())
     180    if (m_StateAnimations.find("idle") == m_StateAnimations.end())
    174181    {
    175182        CSkeletonAnim* anim = new CSkeletonAnim();
    176         anim->m_Name = "idle";
     183        anim->m_StateName = "idle";
     184        anim->m_AnimationName = "";
    177185        anim->m_AnimDef = NULL;
     186        anim->m_Frequency = 1;
    178187        anim->m_Speed = 0.f;
    179188        anim->m_ActionPos = 0.f;
    180189        anim->m_ActionPos2 = 0.f;
    181190        anim->m_SoundPos = 0.f;
    182         m_Animations.insert(std::make_pair("idle", anim));
    183191
     192        m_StateAnimations.insert(std::make_pair("idle", anim));
     193        m_StateFrequencies["idle"] = 1;
     194
    184195        // Ignore errors, since they're probably saying this is a non-animated model
    185196        model->SetAnimation(anim);
    186197    }
     
    250261    return true;
    251262}
    252263
    253 CSkeletonAnim* CObjectEntry::GetRandomAnimation(const CStr& animationName) const
     264CSkeletonAnim* CObjectEntry::GetRandomAnimation(const CStr& stateName) const
    254265{
    255     SkeletonAnimMap::const_iterator lower = m_Animations.lower_bound(animationName);
    256     SkeletonAnimMap::const_iterator upper = m_Animations.upper_bound(animationName);
     266    SkeletonStateAnimMap::const_iterator lower = m_StateAnimations.lower_bound(stateName);
     267    SkeletonStateAnimMap::const_iterator upper = m_StateAnimations.upper_bound(stateName);
    257268    size_t count = std::distance(lower, upper);
    258269    if (count == 0)
    259270        return NULL;
    260271
     272    // TODO: make this use frequencies.
    261273    size_t id = rand(0, count);
    262274    std::advance(lower, id);
    263275    return lower->second;
    264276}
    265277
    266 std::vector<CSkeletonAnim*> CObjectEntry::GetAnimations(const CStr& animationName) const
     278std::vector<CSkeletonAnim*> CObjectEntry::GetAnimations(const CStr& stateName, const CStr& animationName) const
    267279{
    268280    std::vector<CSkeletonAnim*> anims;
     281   
     282    SkeletonStateAnimMap::const_iterator lower = m_StateAnimations.lower_bound(stateName);
     283    SkeletonStateAnimMap::const_iterator upper = m_StateAnimations.upper_bound(stateName);
     284    for (SkeletonStateAnimMap::const_iterator it = lower; it != upper; ++it)
     285    {
     286        if (it->second->m_AnimationName == animationName)
     287            anims.push_back(it->second);
     288    }
     289    return anims;
     290}
    269291
    270     SkeletonAnimMap::const_iterator lower = m_Animations.lower_bound(animationName);
    271     SkeletonAnimMap::const_iterator upper = m_Animations.upper_bound(animationName);
    272     for (SkeletonAnimMap::const_iterator it = lower; it != upper; ++it)
     292std::vector<CSkeletonAnim*> CObjectEntry::GetStateAnimations(const CStr& stateName) const
     293{
     294    std::vector<CSkeletonAnim*> anims;
     295
     296    SkeletonStateAnimMap::const_iterator lower = m_StateAnimations.lower_bound(stateName);
     297    SkeletonStateAnimMap::const_iterator upper = m_StateAnimations.upper_bound(stateName);
     298    for (SkeletonStateAnimMap::const_iterator it = lower; it != upper; ++it)
    273299        anims.push_back(it->second);
    274300    return anims;
    275301}
     302
     303size_t CObjectEntry::GetStateFrequency(const CStr& stateName) const
     304{
     305    SkeletonStateFrequencies::const_iterator idx =  m_StateFrequencies.find(stateName);
     306    if (idx != m_StateFrequencies.end())
     307        return idx->second;
     308    return 0;
     309}
     310
     311size_t CObjectEntry::GetStateAnimFrequency(const CStr& stateName, const CStr& animationName) const
     312{
     313    size_t total = 0;
     314   
     315    SkeletonStateAnimMap::const_iterator lower = m_StateAnimations.lower_bound(stateName);
     316    SkeletonStateAnimMap::const_iterator upper = m_StateAnimations.upper_bound(stateName);
     317    for (SkeletonStateAnimMap::const_iterator it = lower; it != upper; ++it)
     318        if (it->second->m_AnimationName == animationName)
     319            total += it->second->m_Frequency;
     320   
     321    return total;
     322}
     323
  • source/graphics/ObjectBase.h

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    4141    {
    4242        // constructor
    4343        Anim() : m_Speed(1.f), m_ActionPos(-1.f), m_ActionPos2(-1.f), m_SoundPos(-1.f) {}
    44         // name of the animation - "Idle", "Run", etc
     44        // unit State the animation is used for — "Idle", "Run",…
     45        CStr m_StateName;
     46        // ctual Name of the animation
    4547        CStr m_AnimName;
    4648        // filename of the animation - manidle.psa, manrun.psa, etc
    4749        VfsPath m_FileName;
    4850        // animation speed, as specified in XML actor file
    4951        float m_Speed;
     52        // how often the animation will be chosen (if several are possible).
     53        size_t m_Frequency;
    5054        // fraction [0.0, 1.0] of the way through the animation that the interesting bit(s)
    5155        // happens, or -1.0 if unspecified
    5256        float m_ActionPos;
  • source/graphics/ObjectBase.cpp

     
    100100    m_Pathname = pathname;
    101101    m_ShortName = pathname.Basename().string();
    102102
     103    int version = root.GetAttributes()[0].Value.ToInt();
    103104
    104105    // Set up the vector<vector<T>> m_Variants to contain the right number
    105106    // of elements, to avoid wasteful copying/reallocation later.
     
    194195                    }
    195196                    else if (option_name == el_animations)
    196197                    {
     198                        if (version == 2)
     199                        {
     200                            XERO_ITER_EL(option, states)
     201                            {
     202                                std::string stateName = XeroFile.GetElementString(states.GetNodeName());
     203                               
     204                                XERO_ITER_EL(states, anim_element)
     205                                {
     206                                    Anim anim;
     207                                    ENSURE(anim_element.GetNodeName() == el_animation);
     208                                   
     209                                    anim.m_StateName = stateName;
     210                                    anim.m_Frequency = 1;
     211                                    anim.m_AnimName = "";
     212                                   
     213                                    XERO_ITER_ATTR(anim_element, ae)
     214                                    {
     215                                        if (ae.Name == at_name)
     216                                        {
     217                                            anim.m_AnimName = ae.Value;
     218                                        }
     219                                        else if (ae.Name == at_file)
     220                                        {
     221                                            anim.m_FileName = VfsPath("art/animation") / ae.Value.FromUTF8();
     222                                        }
     223                                        else if (ae.Name == at_speed)
     224                                        {
     225                                            anim.m_Speed = ae.Value.ToInt() / 100.f;
     226                                            if (anim.m_Speed <= 0.0) anim.m_Speed = 1.0f;
     227                                        }
     228                                        else if (ae.Name == at_frequency)
     229                                        {
     230                                            anim.m_Frequency = ae.Value.ToUInt();
     231                                        }
     232                                        else if (ae.Name == at_event)
     233                                        {
     234                                            float pos = ae.Value.ToFloat();
     235                                            anim.m_ActionPos = clamp(pos, 0.f, 1.f);
     236                                        }
     237                                        else if (ae.Name == at_load)
     238                                        {
     239                                            float pos = ae.Value.ToFloat();
     240                                            anim.m_ActionPos2 = clamp(pos, 0.f, 1.f);
     241                                        }
     242                                        else if (ae.Name == at_sound)
     243                                        {
     244                                            float pos = ae.Value.ToFloat();
     245                                            anim.m_SoundPos = clamp(pos, 0.f, 1.f);
     246                                        }
     247                                    }
     248                                    currentVariant->m_Anims.push_back(anim);
     249                                }
     250                            }
     251                        }
     252                        else
     253                        {
    197254                        XERO_ITER_EL(option, anim_element)
    198255                        {
    199256                            ENSURE(anim_element.GetNodeName() == el_animation);
    200257
    201258                            Anim anim;
     259                               
     260                                anim.m_Frequency = 1;
     261                                anim.m_AnimName = "";
     262                               
    202263                            XERO_ITER_ATTR(anim_element, ae)
    203264                            {
    204265                                if (ae.Name == at_name)
    205266                                {
    206                                     anim.m_AnimName = ae.Value;
     267                                        anim.m_StateName = ae.Value;
    207268                                }
    208269                                else if (ae.Name == at_file)
    209270                                {
     
    232293                            }
    233294                            currentVariant->m_Anims.push_back(anim);
    234295                        }
    235 
    236296                    }
     297                    }
    237298                    else if (option_name == el_props)
    238299                    {
    239300                        XERO_ITER_EL(option, prop_element)
     
    450511        // Same idea applies for animations.
    451512        // So, erase all existing animations which are overridden by this variant:
    452513        for (std::vector<CObjectBase::Anim>::iterator it = var.m_Anims.begin(); it != var.m_Anims.end(); ++it)
    453             variation.anims.erase(it->m_AnimName);
     514            variation.anims.erase(it->m_StateName);
    454515        // and then insert the new ones:
    455516        for (std::vector<CObjectBase::Anim>::iterator it = var.m_Anims.begin(); it != var.m_Anims.end(); ++it)
    456             variation.anims.insert(make_pair(it->m_AnimName, *it));
     517            variation.anims.insert(make_pair(it->m_StateName, *it));
    457518       
    458519        // Same for samplers, though perhaps not strictly necessary:
    459520        for (std::vector<CObjectBase::Samp>::iterator it = var.m_Samplers.begin(); it != var.m_Samplers.end(); ++it)
  • source/graphics/Model.h

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    200200     * Load raw animation frame animation from given file, and build an
    201201     * animation specific to this model.
    202202     * @param pathname animation file to load
    203      * @param name animation name (e.g. "idle")
     203     * @param stateName state name (e.g. "idle")
     204     * @param animName animation name (default is "")
    204205     * @param speed animation speed as a factor of the default animation speed
     206     * @param frequency how often the animation will be chosen
    205207     * @param actionpos offset of 'action' event, in range [0, 1]
    206208     * @param actionpos2 offset of 'action2' event, in range [0, 1]
    207209     * @param sound offset of 'sound' event, in range [0, 1]
    208210     * @return new animation, or NULL on error
    209211     */
    210     CSkeletonAnim* BuildAnimation(const VfsPath& pathname, const CStr& name, float speed, float actionpos, float actionpos2, float soundpos);
     212    CSkeletonAnim* BuildAnimation(const VfsPath& pathname, const CStr& stateName, const CStr& animName, float speed, int frequency, float actionpos, float actionpos2, float soundpos);
    211213
    212214    /**
    213215     * Add a prop to the model on the given point.
  • source/graphics/Model.cpp

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2015 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    255255/////////////////////////////////////////////////////////////////////////////////////////////////////////////
    256256// BuildAnimation: load raw animation frame animation from given file, and build a
    257257// animation specific to this model
    258 CSkeletonAnim* CModel::BuildAnimation(const VfsPath& pathname, const CStr& name, float speed, float actionpos, float actionpos2, float soundpos)
     258CSkeletonAnim* CModel::BuildAnimation(const VfsPath& pathname, const CStr& stateName, const CStr& animName, float speed, int frequency, float actionpos, float actionpos2, float soundpos)
    259259{
    260260    CSkeletonAnimDef* def = m_SkeletonAnimManager.GetAnimation(pathname);
    261261    if (!def)
     
    262262        return NULL;
    263263
    264264    CSkeletonAnim* anim = new CSkeletonAnim();
    265     anim->m_Name = name;
     265    anim->m_StateName = stateName;
     266    anim->m_AnimationName = animName;
    266267    anim->m_AnimDef = def;
    267268    anim->m_Speed = speed;
     269    anim->m_Frequency = frequency;
    268270
    269271    if (actionpos == -1.f)
    270272        anim->m_ActionPos = -1.f;