OpenClonk
StdMeshSkeletonLoader Class Referenceabstract

#include <StdMeshLoader.h>

Public Types

typedef std::map< StdCopyStrBuf, std::shared_ptr< StdMeshSkeleton > > SkeletonMap
 
typedef SkeletonMap::const_iterator skeleton_iterator
 

Public Member Functions

virtual ~StdMeshSkeletonLoader ()=default
 
void StoreSkeleton (const char *groupname, const char *filename, std::shared_ptr< StdMeshSkeleton > skeleton)
 
void RemoveSkeleton (const StdCopyStrBuf &filepath)
 
void RemoveSkeleton (const char *groupname, const char *filename)
 
void RemoveSkeletonsInGroup (const char *groupname)
 
virtual StdMeshSkeletonGetSkeletonByDefinition (const char *definition) const =0
 
std::shared_ptr< StdMeshSkeletonGetSkeletonByName (const StdStrBuf &name) const
 
void LoadSkeletonXml (const char *groupname, const char *filename, const char *sourcefile, size_t size)
 
void LoadSkeletonBinary (const char *groupname, const char *filename, const char *sourcefile, size_t size)
 
void ResolveIncompleteSkeletons ()
 
void Clear ()
 
skeleton_iterator skeletons_begin () const
 
skeleton_iterator skeletons_end () const
 

Static Public Member Functions

static void MakeFullSkeletonPath (StdCopyStrBuf &out, const char *groupname, const char *filename)
 

Detailed Description

Definition at line 49 of file StdMeshLoader.h.

Member Typedef Documentation

◆ skeleton_iterator

typedef SkeletonMap::const_iterator StdMeshSkeletonLoader::skeleton_iterator

Definition at line 83 of file StdMeshLoader.h.

◆ SkeletonMap

Definition at line 82 of file StdMeshLoader.h.

Constructor & Destructor Documentation

◆ ~StdMeshSkeletonLoader()

virtual StdMeshSkeletonLoader::~StdMeshSkeletonLoader ( )
virtualdefault

Member Function Documentation

◆ Clear()

void StdMeshSkeletonLoader::Clear ( )
inline

Definition at line 74 of file StdMeshLoader.h.

75  {
76  Skeletons.clear();
77  AppendtoSkeletons.clear();
78  IncludeSkeletons.clear();
79  }

◆ GetSkeletonByDefinition()

virtual StdMeshSkeleton* StdMeshSkeletonLoader::GetSkeletonByDefinition ( const char *  definition) const
pure virtual

◆ GetSkeletonByName()

std::shared_ptr< StdMeshSkeleton > StdMeshSkeletonLoader::GetSkeletonByName ( const StdStrBuf name) const

Definition at line 295 of file StdMeshLoaderBinary.cpp.

296 {
297  StdCopyStrBuf filename(name);
298 
299  std::map<StdCopyStrBuf, std::shared_ptr<StdMeshSkeleton>>::const_iterator iter = Skeletons.find(filename);
300  if (iter == Skeletons.end()) return nullptr;
301  return iter->second;
302 }

Referenced by StdMeshLoader::LoadMeshBinary(), and StdMeshLoader::LoadMeshXml().

Here is the caller graph for this function:

◆ LoadSkeletonBinary()

void StdMeshSkeletonLoader::LoadSkeletonBinary ( const char *  groupname,
const char *  filename,
const char *  sourcefile,
size_t  size 
)

Definition at line 304 of file StdMeshLoaderBinary.cpp.

305 {
306  std::unique_ptr<Ogre::Skeleton::Chunk> chunk;
307  Ogre::DataStream stream(sourcefile, size);
308 
309  std::shared_ptr<StdMeshSkeleton> Skeleton(new StdMeshSkeleton);
310 
311  // First chunk must be the header
312  chunk = Ogre::Skeleton::Chunk::Read(&stream);
313  if (chunk->GetType() != Ogre::Skeleton::CID_Header)
314  throw Ogre::Skeleton::InvalidVersion();
315 
316  std::map<uint16_t, std::unique_ptr<StdMeshBone>> bones;
317  unique_ptr_vector<Ogre::Skeleton::ChunkAnimation> animations;
320  id = Ogre::Skeleton::Chunk::Peek(&stream)
321  )
322  {
323  std::unique_ptr<Ogre::Skeleton::Chunk> chunk(Ogre::Skeleton::Chunk::Read(&stream));
324  switch (chunk->GetType())
325  {
327  {
328  Ogre::Skeleton::ChunkBlendMode& cblend = *static_cast<Ogre::Skeleton::ChunkBlendMode*>(chunk.get());
329  // TODO: Handle it
330  if (cblend.blend_mode != 0) // 0 is average, 1 is cumulative. I'm actually not sure what the difference really is... anyway we implement only one method yet. I think it's average, but not 100% sure.
331  LogF("StdMeshLoader: CID_BlendMode not implemented.");
332  }
333  break;
335  {
336  Ogre::Skeleton::ChunkBone &cbone = *static_cast<Ogre::Skeleton::ChunkBone*>(chunk.get());
337  // Check that the bone ID is unique
338  if (bones.find(cbone.handle) != bones.end())
339  throw Ogre::Skeleton::IdNotUnique();
340  auto bone = std::make_unique<StdMeshBone>();
341  bone->Parent = nullptr;
342  bone->ID = cbone.handle;
343  bone->Name = cbone.name.c_str();
344  bone->Transformation.translate = cbone.position;
345  bone->Transformation.rotate = cbone.orientation;
346  bone->Transformation.scale = cbone.scale;
347  bone->InverseTransformation = StdMeshTransformation::Inverse(bone->Transformation);
348  bones.insert(std::make_pair(cbone.handle, std::move(bone)));
349  }
350  break;
352  {
353  Ogre::Skeleton::ChunkBoneParent &cbparent = *static_cast<Ogre::Skeleton::ChunkBoneParent*>(chunk.get());
354  if (bones.find(cbparent.parentHandle) == bones.end() || bones.find(cbparent.childHandle) == bones.end())
355  throw Ogre::Skeleton::BoneNotFound();
356  bones[cbparent.parentHandle]->Children.push_back(bones[cbparent.childHandle].get());
357  bones[cbparent.childHandle]->Parent = bones[cbparent.parentHandle].get();
358  }
359  break;
361  // Collect animations for later (need bone table index, which we don't know yet)
362  animations.emplace_back(static_cast<Ogre::Skeleton::ChunkAnimation*>(chunk.release()));
363  break;
364  default:
365  assert(!"Unexpected enum value");
366  break;
367  }
368  if (stream.AtEof()) break;
369  }
370 
371  // Find master bone (i.e., the one without a parent)
372  StdMeshBone *master = nullptr;
373  for (auto& b: bones)
374  {
375  if (!b.second->Parent)
376  {
377  master = b.second.get();
378  Skeleton->AddMasterBone(master);
379  }
380  }
381  if (!master)
382  throw Ogre::Skeleton::MissingMasterBone();
383 
384  // Transfer bone ownership to mesh
385  for (auto& b: bones) b.second.release();
386  bones.clear();
387 
388  // Build handle->index quick access table
389  std::map<uint16_t, size_t> handle_lookup;
390  for (size_t i = 0; i < Skeleton->GetNumBones(); ++i)
391  {
392  handle_lookup[Skeleton->GetBone(i).ID] = i;
393  }
394 
395  // Fixup animations
396  for(auto &canim: animations)
397  {
398  StdMeshAnimation &anim = Skeleton->Animations[StdCopyStrBuf(canim->name.c_str())];
399  anim.Name = canim->name.c_str();
400  anim.Length = canim->duration;
401  anim.Tracks.resize(Skeleton->GetNumBones());
402  anim.OriginSkeleton = &(*Skeleton);
403 
404  for(auto &catrack: canim->tracks)
405  {
406  const StdMeshBone &bone = Skeleton->GetBone(handle_lookup[catrack->bone]);
407  StdMeshTrack *&track = anim.Tracks[bone.Index];
408  if (track != nullptr)
409  throw Ogre::Skeleton::MultipleBoneTracks();
410  track = new StdMeshTrack;
411  for(auto &catkf: catrack->keyframes)
412  {
413  StdMeshKeyFrame &kf = track->Frames[catkf->time];
414  kf.Transformation.rotate = catkf->rotation;
415  kf.Transformation.scale = catkf->scale;
416  kf.Transformation.translate = bone.InverseTransformation.rotate * (bone.InverseTransformation.scale * catkf->translation);
418  }
419  }
420  }
421 
422  // Fixup bone transforms
423  for(StdMeshBone *bone: Skeleton->Bones)
424  {
425  if (bone->Parent)
427  else
429 
431  }
432 
433  StoreSkeleton(groupname, filename, Skeleton);
434 }
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:262
#define b
StdMeshTransformation Transformation
Definition: StdMesh.h:68
static Type Peek(const DataStream *stream)
static std::unique_ptr< Chunk > Read(DataStream *stream)
StdCopyStrBuf Name
Definition: StdMesh.h:97
float Length
Definition: StdMesh.h:98
StdMeshTransformation InverseTransformation
Definition: StdMesh.h:39
StdMeshTransformation Transformation
Definition: StdMesh.h:37
unsigned int Index
Definition: StdMesh.h:32
void StoreSkeleton(const char *groupname, const char *filename, std::shared_ptr< StdMeshSkeleton > skeleton)
StdMeshTransformation TransformTransformation(const StdMeshTransformation &trans)
StdMeshVector translate
Definition: StdMeshMath.h:76
static StdMeshTransformation Inverse(const StdMeshTransformation &transform)
StdMeshQuaternion rotate
Definition: StdMeshMath.h:75
StdMeshVector scale
Definition: StdMeshMath.h:74

References Ogre::DataStream::AtEof(), b, Ogre::Skeleton::ChunkBlendMode::blend_mode, Ogre::Skeleton::ChunkBoneParent::childHandle, Ogre::Skeleton::CID_Animation, Ogre::Skeleton::CID_BlendMode, Ogre::Skeleton::CID_Bone, Ogre::Skeleton::CID_Bone_Parent, Ogre::Skeleton::CID_Header, Ogre::Skeleton::ChunkBone::handle, StdMeshBone::Index, StdMeshTransformation::Inverse(), StdMeshBone::InverseTransformation, StdMeshAnimation::Length, LogF(), StdMeshAnimation::Name, Ogre::Skeleton::ChunkBone::name, Ogre::Skeleton::ChunkBone::orientation, Ogre::Skeleton::ChunkBoneParent::parentHandle, Ogre::ChunkBase< ChunkID >::Peek(), Ogre::Skeleton::ChunkBone::position, Ogre::Skeleton::Chunk::Read(), StdMeshTransformation::rotate, Ogre::Skeleton::ChunkBone::scale, StdMeshTransformation::scale, StoreSkeleton(), StdMeshBone::Transformation, StdMeshKeyFrame::Transformation, OgreToClonk::TransformTransformation(), and StdMeshTransformation::translate.

Referenced by C4DefGraphics::LoadSkeleton().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LoadSkeletonXml()

void StdMeshSkeletonLoader::LoadSkeletonXml ( const char *  groupname,
const char *  filename,
const char *  sourcefile,
size_t  size 
)

Definition at line 381 of file StdMeshLoaderXml.cpp.

382 {
383  if (sourcefile == nullptr)
384  {
385  throw Ogre::InsufficientData(FormatString("Failed to load '%s/%s'", groupname, filename).getData());
386  }
387 
388  std::shared_ptr<StdMeshLoader::StdMeshXML> skeleton(new StdMeshLoader::StdMeshXML(filename, sourcefile));
389 
390  TiXmlElement* skeleton_elem = skeleton->RequireFirstChild(nullptr, "skeleton");
391  TiXmlElement* bones_elem = skeleton->RequireFirstChild(skeleton_elem, "bones");
392 
393  // Read bones. Don't insert into Master bone table yet, as the master bone
394  // table is sorted hierarchically, and we will read the hierarchy only
395  // afterwards.
396  std::vector<StdMeshBone*> bones;
397  for (TiXmlElement* bone_elem = bones_elem->FirstChildElement("bone"); bone_elem != nullptr; bone_elem = bone_elem->NextSiblingElement("bone"))
398  {
399  StdMeshBone* bone = new StdMeshBone;
400  bones.push_back(bone);
401 
402  bone->ID = skeleton->RequireIntAttribute(bone_elem, "id");
403  bone->Name = skeleton->RequireStrAttribute(bone_elem, "name");
404  // TODO: Make sure ID and name are unique
405 
406  bone->Parent = nullptr;
407  // Index of bone will be set when building Master Bone Table later
408 
409  TiXmlElement* position_elem = skeleton->RequireFirstChild(bone_elem, "position");
410  TiXmlElement* rotation_elem = skeleton->RequireFirstChild(bone_elem, "rotation");
411  TiXmlElement* axis_elem = skeleton->RequireFirstChild(rotation_elem, "axis");
412 
413  StdMeshVector d, r;
414  d.x = skeleton->RequireFloatAttribute(position_elem, "x");
415  d.y = skeleton->RequireFloatAttribute(position_elem, "y");
416  d.z = skeleton->RequireFloatAttribute(position_elem, "z");
417  float angle = skeleton->RequireFloatAttribute(rotation_elem, "angle");
418  r.x = skeleton->RequireFloatAttribute(axis_elem, "x");
419  r.y = skeleton->RequireFloatAttribute(axis_elem, "y");
420  r.z = skeleton->RequireFloatAttribute(axis_elem, "z");
421 
424  bone->Transformation.translate = d;
425 
426  // We need this later for applying animations, and attaching meshes, therefore cache it here
428  }
429 
430  // Bone hierarchy
431  TiXmlElement* bonehierarchy_elem = skeleton->RequireFirstChild(skeleton_elem, "bonehierarchy");
432  for (TiXmlElement* boneparent_elem = bonehierarchy_elem->FirstChildElement("boneparent"); boneparent_elem != nullptr; boneparent_elem = boneparent_elem->NextSiblingElement("boneparent"))
433  {
434  const char* child_name = skeleton->RequireStrAttribute(boneparent_elem, "bone");
435  const char* parent_name = skeleton->RequireStrAttribute(boneparent_elem, "parent");
436 
437  // Lookup the two bones
438  StdMeshBone* child = nullptr;
439  StdMeshBone* parent = nullptr;
440  for (unsigned int i = 0; i < bones.size() && (!child || !parent); ++i)
441  {
442  if (!child && bones[i]->Name == child_name)
443  child = bones[i];
444  if (!parent && bones[i]->Name == parent_name)
445  parent = bones[i];
446  }
447 
448  if (!child) skeleton->Error(FormatString("There is no such bone with name '%s'", child_name), boneparent_elem);
449  if (!parent) skeleton->Error(FormatString("There is no such bone with name '%s'", parent_name), boneparent_elem);
450 
451  child->Parent = parent;
452  parent->Children.push_back(child);
453  }
454 
455  std::shared_ptr<StdMeshSkeleton> Skeleton(new StdMeshSkeleton);
456 
457  // Fill master bone table in hierarchical order:
458  for (auto & bone : bones)
459  if (bone->Parent == nullptr)
460  Skeleton->AddMasterBone(bone);
461 
462  // Load Animations
463  TiXmlElement* animations_elem = skeleton_elem->FirstChildElement("animations");
464  if (animations_elem)
465  {
466  for (TiXmlElement* animation_elem = animations_elem->FirstChildElement("animation"); animation_elem != nullptr; animation_elem = animation_elem->NextSiblingElement("animation"))
467  {
468  StdCopyStrBuf name(skeleton->RequireStrAttribute(animation_elem, "name"));
469  if (Skeleton->Animations.find(name) != Skeleton->Animations.end())
470  skeleton->Error(FormatString("There is already an animation with name '%s'", name.getData()), animation_elem);
471 
472  StdMeshAnimation& animation = Skeleton->Animations.insert(std::make_pair(name, StdMeshAnimation())).first->second;
473  animation.Name = name;
474  animation.Length = skeleton->RequireFloatAttribute(animation_elem, "length");
475  animation.Tracks.resize(Skeleton->GetNumBones());
476  animation.OriginSkeleton = &(*Skeleton);
477 
478  TiXmlElement* tracks_elem = skeleton->RequireFirstChild(animation_elem, "tracks");
479  for (TiXmlElement* track_elem = tracks_elem->FirstChildElement("track"); track_elem != nullptr; track_elem = track_elem->NextSiblingElement("track"))
480  {
481  const char* bone_name = skeleton->RequireStrAttribute(track_elem, "bone");
482  StdMeshBone* bone = nullptr;
483  for (unsigned int i = 0; !bone && i < Skeleton->GetNumBones(); ++i)
484  if (Skeleton->Bones[i]->Name == bone_name)
485  bone = Skeleton->Bones[i];
486  if (!bone) skeleton->Error(FormatString("There is no such bone with name '%s'", bone_name), track_elem);
487 
488  if (animation.Tracks[bone->Index] != nullptr) skeleton->Error(FormatString("There is already a track for bone '%s' in animation '%s'", bone_name, animation.Name.getData()), track_elem);
489 
490  StdMeshTrack* track = new StdMeshTrack;
491  animation.Tracks[bone->Index] = track;
492 
493  TiXmlElement* keyframes_elem = skeleton->RequireFirstChild(track_elem, "keyframes");
494  for (TiXmlElement* keyframe_elem = keyframes_elem->FirstChildElement("keyframe"); keyframe_elem != nullptr; keyframe_elem = keyframe_elem->NextSiblingElement("keyframe"))
495  {
496  float time = skeleton->RequireFloatAttribute(keyframe_elem, "time");
497  StdMeshKeyFrame& frame = track->Frames[time];
498 
499  TiXmlElement* translate_elem = keyframe_elem->FirstChildElement("translate");
500  TiXmlElement* rotate_elem = keyframe_elem->FirstChildElement("rotate");
501  TiXmlElement* scale_elem = keyframe_elem->FirstChildElement("scale");
502 
503  StdMeshVector d, s, r;
504  d.x = d.y = d.z = 0.0f;
506  r.x = r.y = 0.0f; r.z = 1.0f;
507  float angle = 0.0f;
508 
509  if (translate_elem)
510  {
511  d.x = skeleton->RequireFloatAttribute(translate_elem, "x");
512  d.y = skeleton->RequireFloatAttribute(translate_elem, "y");
513  d.z = skeleton->RequireFloatAttribute(translate_elem, "z");
514  }
515 
516  if (rotate_elem)
517  {
518  TiXmlElement* axis_elem = skeleton->RequireFirstChild(rotate_elem, "axis");
519  angle = skeleton->RequireFloatAttribute(rotate_elem, "angle");
520  r.x = skeleton->RequireFloatAttribute(axis_elem, "x");
521  r.y = skeleton->RequireFloatAttribute(axis_elem, "y");
522  r.z = skeleton->RequireFloatAttribute(axis_elem, "z");
523  }
524 
525  if (scale_elem)
526  {
527  s.x = skeleton->RequireFloatAttribute(scale_elem, "x");
528  s.y = skeleton->RequireFloatAttribute(scale_elem, "y");
529  s.z = skeleton->RequireFloatAttribute(scale_elem, "z");
530  }
531 
532  frame.Transformation.scale = s;
536  }
537  }
538  }
539  }
540 
541  // is there even any xml file that we load from?
542  // it looks like this could never work: if the mesh has no skeleton, then the code below will fail because of a null pointer...
543 
544  // Apply parent transformation to each bone transformation. We need to
545  // do this late since animation keyframe computation needs the bone
546  // transformations, not bone+parent.
547  for (unsigned int i = 0; i < Skeleton->GetNumBones(); ++i)
548  {
549  // Apply parent transformation
550  if (Skeleton->Bones[i]->Parent)
551  Skeleton->Bones[i]->Transformation = Skeleton->Bones[i]->Parent->Transformation * OgreToClonk::TransformTransformation(Skeleton->Bones[i]->Transformation);
552  else
553  Skeleton->Bones[i]->Transformation = OgreToClonk::TransformTransformation(Skeleton->Bones[i]->Transformation);
554 
555  // Update inverse
556  Skeleton->Bones[i]->InverseTransformation = StdMeshTransformation::Inverse(Skeleton->Bones[i]->Transformation);
557  }
558 
559  StoreSkeleton(groupname, filename, Skeleton);
560 }
#define s
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
StdCopyStrBuf Name
Definition: StdMesh.h:34
int ID
Definition: StdMesh.h:33
const char * getData() const
Definition: StdBuf.h:442
static StdMeshQuaternion AngleAxis(float theta, const StdMeshVector &axis)
Definition: StdMeshMath.cpp:72
static StdMeshVector UnitScale()
Definition: StdMeshMath.cpp:29

References StdMeshQuaternion::AngleAxis(), FormatString(), StdStrBuf::getData(), StdMeshBone::ID, StdMeshBone::Index, StdMeshTransformation::Inverse(), StdMeshBone::InverseTransformation, StdMeshAnimation::Length, StdMeshBone::Name, StdMeshAnimation::Name, StdMeshTransformation::rotate, s, StdMeshTransformation::scale, StdMeshBone::Transformation, StdMeshKeyFrame::Transformation, OgreToClonk::TransformTransformation(), StdMeshTransformation::translate, StdMeshVector::UnitScale(), StdMeshVector::x, StdMeshVector::y, and StdMeshVector::z.

Referenced by C4DefGraphics::LoadSkeleton().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ MakeFullSkeletonPath()

static void StdMeshSkeletonLoader::MakeFullSkeletonPath ( StdCopyStrBuf out,
const char *  groupname,
const char *  filename 
)
inlinestatic

Definition at line 66 of file StdMeshLoader.h.

67  {
68  out = StdCopyStrBuf(groupname);
69  out.AppendBackslash();
70  out.Append(filename);
71  out.ToLowerCase();
72  }
void ToLowerCase()
Definition: StdBuf.cpp:385
void AppendBackslash()
Definition: StdBuf.cpp:248
void Append(const char *pnData, size_t iChars)
Definition: StdBuf.h:519

References StdStrBuf::Append(), StdStrBuf::AppendBackslash(), and StdStrBuf::ToLowerCase().

Referenced by StdMeshLoader::LoadMeshBinary(), StdMeshLoader::LoadMeshXml(), RemoveSkeleton(), and StoreSkeleton().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ RemoveSkeleton() [1/2]

void StdMeshSkeletonLoader::RemoveSkeleton ( const char *  groupname,
const char *  filename 
)

Definition at line 254 of file StdMeshLoaderBinary.cpp.

255 {
256  StdCopyStrBuf filepath;
257  MakeFullSkeletonPath(filepath, groupname, filename);
258  RemoveSkeleton(filepath);
259 }
static void MakeFullSkeletonPath(StdCopyStrBuf &out, const char *groupname, const char *filename)
Definition: StdMeshLoader.h:66
void RemoveSkeleton(const StdCopyStrBuf &filepath)

References MakeFullSkeletonPath(), and RemoveSkeleton().

Here is the call graph for this function:

◆ RemoveSkeleton() [2/2]

void StdMeshSkeletonLoader::RemoveSkeleton ( const StdCopyStrBuf filepath)

Definition at line 261 of file StdMeshLoaderBinary.cpp.

262 {
263  std::map<StdCopyStrBuf, std::shared_ptr<StdMeshSkeleton>>::iterator existing_skeleton = Skeletons.find(filepath);
264  if (existing_skeleton != Skeletons.end())
265  {
266  Skeletons.erase(existing_skeleton);
267  }
268 
269  std::map<StdCopyStrBuf, StdCopyStrBuf>::iterator appendto_skeleton = AppendtoSkeletons.find(filepath);
270  if (appendto_skeleton != AppendtoSkeletons.end())
271  {
272  AppendtoSkeletons.erase(appendto_skeleton);
273  }
274 
275  std::map<StdCopyStrBuf, StdCopyStrBuf>::iterator include_skeleton = IncludeSkeletons.find(filepath);
276  if (include_skeleton != IncludeSkeletons.end())
277  {
278  IncludeSkeletons.erase(include_skeleton);
279  }
280 }

Referenced by C4DefGraphics::LoadSkeleton(), RemoveSkeleton(), and RemoveSkeletonsInGroup().

Here is the caller graph for this function:

◆ RemoveSkeletonsInGroup()

void StdMeshSkeletonLoader::RemoveSkeletonsInGroup ( const char *  groupname)

Definition at line 224 of file StdMeshLoaderBinary.cpp.

225 {
226  // DebugLogF("Removing skeletons in group: %s", groupname);
227 
228  std::vector<StdCopyStrBuf> delete_skeletons;
229 
230  std::map<StdCopyStrBuf, std::shared_ptr<StdMeshSkeleton>>::iterator it;
231  for (it = Skeletons.begin(); it != Skeletons.end(); it++)
232  {
233  StdCopyStrBuf skeletonpath(it->first.getData());
234  StdCopyStrBuf group(groupname);
235  group.ToLowerCase();
236 
237  StdCopyStrBuf skeletongroup;
238  GetParentPath(skeletonpath.getData(), &skeletongroup);
239 
240  if (skeletongroup == group)
241  {
242  // DebugLogF("Found skeleton in group: %s", it->first.getData());
243 
244  delete_skeletons.push_back(skeletonpath);
245  }
246  }
247 
248  for (const auto & delete_skeleton : delete_skeletons)
249  {
250  RemoveSkeleton(delete_skeleton);
251  }
252 }
bool GetParentPath(const char *szFilename, char *szBuffer)
Definition: StdFile.cpp:186

References StdStrBuf::getData(), GetParentPath(), RemoveSkeleton(), and StdStrBuf::ToLowerCase().

Here is the call graph for this function:

◆ ResolveIncompleteSkeletons()

void StdMeshSkeletonLoader::ResolveIncompleteSkeletons ( )

Definition at line 597 of file StdMeshLoaderBinary.cpp.

598 {
599  DoResetSkeletons();
600  DoAppendSkeletons();
601  DoIncludeSkeletons();
602 }

◆ skeletons_begin()

skeleton_iterator StdMeshSkeletonLoader::skeletons_begin ( ) const
inline

Definition at line 85 of file StdMeshLoader.h.

85 { return Skeletons.begin(); }

Referenced by StdMeshAnimationUpdate::StdMeshAnimationUpdate().

Here is the caller graph for this function:

◆ skeletons_end()

skeleton_iterator StdMeshSkeletonLoader::skeletons_end ( ) const
inline

Definition at line 86 of file StdMeshLoader.h.

86 { return Skeletons.end(); }

Referenced by StdMeshAnimationUpdate::StdMeshAnimationUpdate().

Here is the caller graph for this function:

◆ StoreSkeleton()

void StdMeshSkeletonLoader::StoreSkeleton ( const char *  groupname,
const char *  filename,
std::shared_ptr< StdMeshSkeleton skeleton 
)

Definition at line 181 of file StdMeshLoaderBinary.cpp.

182 {
183  assert(groupname != nullptr);
184  assert(filename != nullptr);
185  assert(skeleton != nullptr);
186 
187  // Create mirrored animations (#401)
188  // this is still going to be somewhere else, but for now it will keep moving around
189  skeleton->PostInit();
190 
191 
192  // save in map
193  StdCopyStrBuf filepath;
194  MakeFullSkeletonPath(filepath, groupname, filename);
195 
196  AddSkeleton(filepath, skeleton);
197 
198  // memorize which skeletons can be appended
199  // skins get broken down to their original definition, which is a little messy at the moment.
200  StdCopyStrBuf buf_filename(GetFilenameOnly(filename));
201  StdCopyStrBuf command_with_definition(GetFilenameOnly(buf_filename.getData())); // include.Clonk becomes include, include.Clonk.Farmer becomes include.Clonk
202  StdCopyStrBuf command(GetFilenameOnly(command_with_definition.getData())); // include stays include, include.Clonk becomes include
203  StdCopyStrBuf definition(GetExtension(buf_filename.getData())); // include.Clonk becomes Clonk, include.Clonk.Farmer becomes Farmer
204 
205  if (!(command_with_definition == command)) // include.Clonk != include?
206  {
207  definition = StdCopyStrBuf(GetExtension(command_with_definition.getData())); // change definition to the part behind the .: Clonk
208  }
209 
210  const char* appendto = "appendto"; // has to be a constant
211  const char* include = "include"; // dito
212 
213  // check where to store
214  if (command == appendto)
215  {
216  AppendtoSkeletons.insert(std::make_pair(filepath, definition));
217  }
218  else if (command == include)
219  {
220  IncludeSkeletons.insert(std::make_pair(filepath, definition));
221  }
222 }
char * GetExtension(char *szFilename)
Definition: StdFile.cpp:118
const char * GetFilenameOnly(const char *strFilename)
Definition: StdFile.cpp:57

References StdStrBuf::getData(), GetExtension(), GetFilenameOnly(), and MakeFullSkeletonPath().

Referenced by LoadSkeletonBinary().

Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following files: