Ticket #2324: ActorFormat.4.patch
File ActorFormat.4.patch, 24.6 KB (added by , 8 years ago) |
---|
-
source/graphics/UnitAnimation.h
1 /* Copyright (C) 201 1Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 95 95 struct SModelAnimState 96 96 { 97 97 CModel* model; 98 const CObjectEntry* object; 98 99 std::vector<CSkeletonAnim*> anims; 100 CStr animName; 99 101 size_t animIdx; 100 102 float time; 101 103 bool pastLoadPos; … … 111 113 */ 112 114 bool m_AnimStatesAreStatic; 113 115 114 void AddModel(CModel* model, const CObjectEntry* object );116 void AddModel(CModel* model, const CObjectEntry* object, bool useName = false, CStr* animName = NULL); 115 117 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 116 124 entity_id_t m_Entity; 117 125 CModel* m_Model; 118 126 const CObjectEntry* m_Object; -
source/graphics/UnitAnimation.cpp
1 /* Copyright (C) 201 2Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 52 52 m_Entity = ent; 53 53 } 54 54 55 void CUnitAnimation::AddModel(CModel* model, const CObjectEntry* object )55 void CUnitAnimation::AddModel(CModel* model, const CObjectEntry* object, bool useName /* = false */, CStr* animName /* = NULL */) 56 56 { 57 57 SModelAnimState state; 58 58 59 state.anims = object->GetAnimations(m_State);59 ENSURE(!object->GetStateAnimations("idle").empty()); // there must always be an idle animation 60 60 61 if (state.anims.empty())62 state.anims = object->GetAnimations("idle");63 ENSURE(!state.anims.empty()); // there must always be an idle animation64 65 61 state.model = model; 66 state. animIdx = rand(0, state.anims.size());62 state.object = object; 67 63 state.time = 0.f; 68 64 state.pastLoadPos = false; 69 65 state.pastActionPos = false; 70 66 state.pastSoundPos = false; 71 67 68 this->pickAnim(&state, m_State, useName, animName); 69 72 70 m_AnimStates.push_back(state); 73 71 74 72 model->SetAnimation(state.anims[state.animIdx], !m_Looping); 75 73 76 74 // 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) 79 77 m_AnimStatesAreStatic = false; 80 78 81 79 // 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()) 84 81 { 85 CModel* propModel = it->m_Model->ToCModel();82 CModel* propModel = prop.m_Model->ToCModel(); 86 83 if (propModel) 87 AddModel(propModel, it->m_ObjectEntry);84 AddModel(propModel, prop.m_ObjectEntry, true, &state.animName); 88 85 } 89 86 } 90 87 88 void 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 91 143 void CUnitAnimation::ReloadUnit(CModel* model, const CObjectEntry* object) 92 144 { 93 145 m_Model = model; … … 160 212 return; 161 213 162 214 // Advance all of the prop models independently 215 SModelAnimState* needLooping[m_AnimStates.size()]; 216 size_t looped = 0; 217 163 218 for (std::vector<SModelAnimState>::iterator it = m_AnimStates.begin(); it != m_AnimStates.end(); ++it) 164 219 { 165 220 CSkeletonAnimDef* animDef = it->anims[it->animIdx]->m_AnimDef; … … 228 283 else if (m_Looping) 229 284 { 230 285 // If we've finished the current animation and want to loop... 231 286 needLooping[looped++] = &(*it); 287 232 288 // Wrap the timer around 233 289 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 246 291 it->pastActionPos = false; 247 292 it->pastLoadPos = false; 248 293 it->pastSoundPos = false; 249 250 it->model->UpdateTo(it->time);251 294 } 252 295 else 253 296 { … … 262 305 } 263 306 } 264 307 } 308 309 if (looped == 0) 310 return; 311 312 // to keep our props in synch (well those that can be) 313 // we'll update them separately. 314 CStr animName = ""; 315 CStr& stateName = m_State; 316 317 for (size_t i = 0; i < looped; ++i) 318 { 319 SModelAnimState* state = needLooping[i]; 320 321 bool initializer = i == 0 ? true : false; 322 this->pickAnim(state, stateName, true, &animName, initializer); 323 324 state->model->UpdateTo(state->time); 325 } 265 326 } -
source/graphics/SkeletonAnim.h
1 /* Copyright (C) 201 0Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 33 33 { 34 34 public: 35 35 // 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; 37 39 // the raw animation frame data; may be NULL if this is a static 'animation' 38 40 CSkeletonAnimDef* m_AnimDef; 39 41 // speed at which this animation runs, as a factor of the AnimDef default speed 40 42 // (treated as 0 if m_AnimDef == NULL) 41 43 float m_Speed; 44 // how often this animation will be played. 45 size_t m_Frequency; 42 46 // Times during the animation at which the interesting bits happen, 43 47 // as msec times in the range [0, AnimDef->GetDuration], 44 48 // or special value -1 if unspecified. -
source/graphics/ObjectEntry.h
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 63 63 64 64 std::wstring m_ProjectileModelName; 65 65 66 // Returns a randomly-chosen animation matching the given name.66 // Returns a randomly-chosen animation from a given state 67 67 // If none is found, returns NULL. 68 CSkeletonAnim* GetRandomAnimation(const CStr& animationName) const;68 CSkeletonAnim* GetRandomAnimation(const CStr& stateName) const; 69 69 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; 72 75 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 73 82 // corresponding model 74 83 CModelAbstract* m_Model; 75 84 … … 80 89 private: 81 90 CSimulation2& m_Simulation; 82 91 83 typedef std::multimap<CStr, CSkeletonAnim*> SkeletonAnimMap; 84 SkeletonAnimMap m_Animations; 85 // TODO: something more memory-efficient than storing loads of similar strings for each unit? 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; 98 // TODO: something more memory-efficient than storing loads of similar strings for each unit? 86 99 }; 87 100 88 101 -
source/graphics/ObjectEntry.cpp
46 46 47 47 CObjectEntry::~CObjectEntry() 48 48 { 49 for (const std::pair<CStr, CSkeletonAnim*>& anim : m_ Animations)49 for (const std::pair<CStr, CSkeletonAnim*>& anim : m_StateAnimations) 50 50 delete anim.second; 51 51 52 52 delete m_Model; … … 133 133 if (m_Samplers.empty()) 134 134 LOGERROR("Actor '%s' has no textures.", utf8_from_wstring(m_Base->m_ShortName)); 135 135 136 for (const auto& samp : m_Samplers)136 for (const CObjectBase::Samp& samp : m_Samplers) 137 137 { 138 138 CTextureProperties textureProps(samp.m_SamplerFile); 139 139 textureProps.SetWrap(GL_CLAMP_TO_EDGE); … … 145 145 model->GetMaterial().AddSampler(CMaterial::TextureSampler(samp.m_SamplerName, texture)); 146 146 } 147 147 148 const std::vector<CStrIntern>& requiredSamplers = model->GetMaterial().GetRequiredSampler(); 149 for (const auto& requSampName : requiredSamplers) 148 for (const CStrIntern& requSampName : model->GetMaterial().GetRequiredSampler()) 150 149 { 151 150 if (std::find_if(m_Samplers.begin(), m_Samplers.end(), 152 151 [&](CObjectBase::Samp sampler) { return sampler.m_SamplerName == requSampName; }) == m_Samplers.end()) … … 159 158 // load the animations 160 159 for (std::multimap<CStr, CObjectBase::Anim>::iterator it = variation.anims.begin(); it != variation.anims.end(); ++it) 161 160 { 162 CStr name = it->first.LowerCase();161 CStr stateName = it->first.LowerCase(); 163 162 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)); 169 } 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; 170 177 } 171 178 172 179 // 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()) 174 181 { 175 182 CSkeletonAnim* anim = new CSkeletonAnim(); 176 anim->m_Name = "idle"; 183 anim->m_StateName = "idle"; 184 anim->m_AnimationName = ""; 177 185 anim->m_AnimDef = NULL; 186 anim->m_Frequency = 1; 178 187 anim->m_Speed = 0.f; 179 188 anim->m_ActionPos = 0.f; 180 189 anim->m_ActionPos2 = 0.f; 181 190 anim->m_SoundPos = 0.f; 182 m_Animations.insert(std::make_pair("idle", anim));183 191 192 m_StateAnimations.insert(std::make_pair("idle", anim)); 193 m_StateFrequencies["idle"] = 1; 194 184 195 // Ignore errors, since they're probably saying this is a non-animated model 185 196 model->SetAnimation(anim); 186 197 } … … 250 261 return true; 251 262 } 252 263 253 CSkeletonAnim* CObjectEntry::GetRandomAnimation(const CStr& animationName) const264 CSkeletonAnim* CObjectEntry::GetRandomAnimation(const CStr& stateName) const 254 265 { 255 Skeleton AnimMap::const_iterator lower = m_Animations.lower_bound(animationName);256 Skeleton AnimMap::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); 257 268 size_t count = std::distance(lower, upper); 258 269 if (count == 0) 259 270 return NULL; 260 271 272 // TODO: make this use frequencies. 261 273 size_t id = rand(0, count); 262 274 std::advance(lower, id); 263 275 return lower->second; 264 276 } 265 277 266 std::vector<CSkeletonAnim*> CObjectEntry::GetAnimations(const CStr& animationName) const278 std::vector<CSkeletonAnim*> CObjectEntry::GetAnimations(const CStr& stateName, const CStr& animationName) const 267 279 { 268 280 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 if (it->second->m_AnimationName == animationName) 286 anims.push_back(it->second); 287 return anims; 288 } 269 289 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) 290 std::vector<CSkeletonAnim*> CObjectEntry::GetStateAnimations(const CStr& stateName) const 291 { 292 std::vector<CSkeletonAnim*> anims; 293 294 SkeletonStateAnimMap::const_iterator lower = m_StateAnimations.lower_bound(stateName); 295 SkeletonStateAnimMap::const_iterator upper = m_StateAnimations.upper_bound(stateName); 296 for (SkeletonStateAnimMap::const_iterator it = lower; it != upper; ++it) 273 297 anims.push_back(it->second); 274 298 return anims; 275 299 } 300 301 size_t CObjectEntry::GetStateFrequency(const CStr& stateName) const 302 { 303 SkeletonStateFrequencies::const_iterator idx = m_StateFrequencies.find(stateName); 304 if (idx != m_StateFrequencies.end()) 305 return idx->second; 306 return 0; 307 } 308 309 size_t CObjectEntry::GetStateAnimFrequency(const CStr& stateName, const CStr& animationName) const 310 { 311 size_t total = 0; 312 313 SkeletonStateAnimMap::const_iterator lower = m_StateAnimations.lower_bound(stateName); 314 SkeletonStateAnimMap::const_iterator upper = m_StateAnimations.upper_bound(stateName); 315 for (SkeletonStateAnimMap::const_iterator it = lower; it != upper; ++it) 316 if (it->second->m_AnimationName == animationName) 317 total += it->second->m_Frequency; 318 return total; 319 } 320 -
source/graphics/ObjectBase.h
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 41 41 { 42 42 // constructor 43 43 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 // actual Name of the animation 45 47 CStr m_AnimName; 46 48 // filename of the animation - manidle.psa, manrun.psa, etc 47 49 VfsPath m_FileName; 48 50 // animation speed, as specified in XML actor file 49 51 float m_Speed; 52 // how often the animation will be chosen (if several are possible). 53 size_t m_Frequency; 50 54 // fraction [0.0, 1.0] of the way through the animation that the interesting bit(s) 51 55 // happens, or -1.0 if unspecified 52 56 float m_ActionPos; -
source/graphics/ObjectBase.cpp
100 100 m_Pathname = pathname; 101 101 m_ShortName = pathname.Basename().string(); 102 102 103 int version = root.GetAttributes()[0].Value.ToInt(); 103 104 104 105 // Set up the vector<vector<T>> m_Variants to contain the right number 105 106 // of elements, to avoid wasteful copying/reallocation later. … … 194 195 } 195 196 else if (option_name == el_animations) 196 197 { 197 XERO_ITER_EL(option, anim_element)198 if (version == 2) 198 199 { 199 ENSURE(anim_element.GetNodeName() == el_animation); 200 201 Anim anim; 202 XERO_ITER_ATTR(anim_element, ae) 200 XERO_ITER_EL(option, states) 203 201 { 204 if (ae.Name == at_name) 202 std::string stateName = XeroFile.GetElementString(states.GetNodeName()); 203 204 XERO_ITER_EL(states, anim_element) 205 205 { 206 anim.m_AnimName = ae.Value; 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); 207 249 } 208 else if (ae.Name == at_file) 250 } 251 } 252 else 253 { 254 XERO_ITER_EL(option, anim_element) 255 { 256 ENSURE(anim_element.GetNodeName() == el_animation); 257 258 Anim anim; 259 260 anim.m_Frequency = 1; 261 anim.m_AnimName = ""; 262 263 XERO_ITER_ATTR(anim_element, ae) 209 264 { 210 anim.m_FileName = VfsPath("art/animation") / ae.Value.FromUTF8(); 265 if (ae.Name == at_name) 266 { 267 anim.m_StateName = ae.Value; 268 } 269 else if (ae.Name == at_file) 270 { 271 anim.m_FileName = VfsPath("art/animation") / ae.Value.FromUTF8(); 272 } 273 else if (ae.Name == at_speed) 274 { 275 anim.m_Speed = ae.Value.ToInt() / 100.f; 276 if (anim.m_Speed <= 0.0) anim.m_Speed = 1.0f; 277 } 278 else if (ae.Name == at_event) 279 { 280 float pos = ae.Value.ToFloat(); 281 anim.m_ActionPos = clamp(pos, 0.f, 1.f); 282 } 283 else if (ae.Name == at_load) 284 { 285 float pos = ae.Value.ToFloat(); 286 anim.m_ActionPos2 = clamp(pos, 0.f, 1.f); 287 } 288 else if (ae.Name == at_sound) 289 { 290 float pos = ae.Value.ToFloat(); 291 anim.m_SoundPos = clamp(pos, 0.f, 1.f); 292 } 211 293 } 212 else if (ae.Name == at_speed) 213 { 214 anim.m_Speed = ae.Value.ToInt() / 100.f; 215 if (anim.m_Speed <= 0.0) anim.m_Speed = 1.0f; 216 } 217 else if (ae.Name == at_event) 218 { 219 float pos = ae.Value.ToFloat(); 220 anim.m_ActionPos = clamp(pos, 0.f, 1.f); 221 } 222 else if (ae.Name == at_load) 223 { 224 float pos = ae.Value.ToFloat(); 225 anim.m_ActionPos2 = clamp(pos, 0.f, 1.f); 226 } 227 else if (ae.Name == at_sound) 228 { 229 float pos = ae.Value.ToFloat(); 230 anim.m_SoundPos = clamp(pos, 0.f, 1.f); 231 } 294 currentVariant->m_Anims.push_back(anim); 232 295 } 233 currentVariant->m_Anims.push_back(anim);234 296 } 235 236 297 } 237 298 else if (option_name == el_props) 238 299 { … … 450 511 // Same idea applies for animations. 451 512 // So, erase all existing animations which are overridden by this variant: 452 513 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); 454 515 // and then insert the new ones: 455 516 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)); 457 518 458 519 // Same for samplers, though perhaps not strictly necessary: 459 520 for (std::vector<CObjectBase::Samp>::iterator it = var.m_Samplers.begin(); it != var.m_Samplers.end(); ++it) -
source/graphics/Model.h
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 200 200 * Load raw animation frame animation from given file, and build an 201 201 * animation specific to this model. 202 202 * @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 "") 204 205 * @param speed animation speed as a factor of the default animation speed 206 * @param frequency how often the animation will be chosen 205 207 * @param actionpos offset of 'action' event, in range [0, 1] 206 208 * @param actionpos2 offset of 'action2' event, in range [0, 1] 207 209 * @param sound offset of 'sound' event, in range [0, 1] 208 210 * @return new animation, or NULL on error 209 211 */ 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); 211 213 212 214 /** 213 215 * Add a prop to the model on the given point. -
source/graphics/Model.cpp
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2015 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 255 255 ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 256 256 // BuildAnimation: load raw animation frame animation from given file, and build a 257 257 // animation specific to this model 258 CSkeletonAnim* CModel::BuildAnimation(const VfsPath& pathname, const CStr& name, float speed, float actionpos, float actionpos2, float soundpos)258 CSkeletonAnim* CModel::BuildAnimation(const VfsPath& pathname, const CStr& stateName, const CStr& animName, float speed, int frequency, float actionpos, float actionpos2, float soundpos) 259 259 { 260 260 CSkeletonAnimDef* def = m_SkeletonAnimManager.GetAnimation(pathname); 261 261 if (!def) … … 262 262 return NULL; 263 263 264 264 CSkeletonAnim* anim = new CSkeletonAnim(); 265 anim->m_Name = name; 265 anim->m_StateName = stateName; 266 anim->m_AnimationName = animName; 266 267 anim->m_AnimDef = def; 267 268 anim->m_Speed = speed; 269 anim->m_Frequency = frequency; 268 270 269 271 if (actionpos == -1.f) 270 272 anim->m_ActionPos = -1.f;