OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
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 ()
 
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 50 of file StdMeshLoader.h.

Member Typedef Documentation

typedef SkeletonMap::const_iterator StdMeshSkeletonLoader::skeleton_iterator

Definition at line 84 of file StdMeshLoader.h.

Definition at line 83 of file StdMeshLoader.h.

Constructor & Destructor Documentation

virtual StdMeshSkeletonLoader::~StdMeshSkeletonLoader ( )
inlinevirtual

Definition at line 53 of file StdMeshLoader.h.

53 {}

Member Function Documentation

void StdMeshSkeletonLoader::Clear ( )
inline

Definition at line 75 of file StdMeshLoader.h.

76  {
77  Skeletons.clear();
78  AppendtoSkeletons.clear();
79  IncludeSkeletons.clear();
80  }
virtual StdMeshSkeleton* StdMeshSkeletonLoader::GetSkeletonByDefinition ( const char *  definition) const
pure virtual
std::shared_ptr< StdMeshSkeleton > StdMeshSkeletonLoader::GetSkeletonByName ( const StdStrBuf name) const

Definition at line 297 of file StdMeshLoaderBinary.cpp.

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

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

Here is the caller graph for this function:

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

Definition at line 306 of file StdMeshLoaderBinary.cpp.

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, 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(), Ogre::Skeleton::ChunkBone::scale, StoreSkeleton(), StdMeshBone::Transformation, StdMeshKeyFrame::Transformation, and OgreToClonk::TransformTransformation().

Referenced by C4DefGraphics::LoadSkeleton().

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

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 382 of file StdMeshLoaderXml.cpp.

References FormatString(), StdStrBuf::getData(), StdMeshBone::ID, StdMeshBone::Index, StdMeshBone::InverseTransformation, StdMeshAnimation::Length, StdMeshBone::Name, StdMeshAnimation::Name, s, StdMeshBone::Transformation, StdMeshKeyFrame::Transformation, OgreToClonk::TransformTransformation(), StdMeshVector::UnitScale(), StdMeshVector::x, StdMeshVector::y, and StdMeshVector::z.

Referenced by C4DefGraphics::LoadSkeleton().

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

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 67 of file StdMeshLoader.h.

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

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

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

Here is the call graph for this function:

Here is the caller graph for this function:

void StdMeshSkeletonLoader::RemoveSkeleton ( const StdCopyStrBuf filepath)

Definition at line 263 of file StdMeshLoaderBinary.cpp.

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

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

Here is the caller graph for this function:

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

Definition at line 256 of file StdMeshLoaderBinary.cpp.

References MakeFullSkeletonPath(), and RemoveSkeleton().

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

Here is the call graph for this function:

void StdMeshSkeletonLoader::RemoveSkeletonsInGroup ( const char *  groupname)

Definition at line 226 of file StdMeshLoaderBinary.cpp.

References GetParentPath(), and RemoveSkeleton().

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

Here is the call graph for this function:

void StdMeshSkeletonLoader::ResolveIncompleteSkeletons ( )

Definition at line 601 of file StdMeshLoaderBinary.cpp.

602 {
603  DoResetSkeletons();
604  DoAppendSkeletons();
605  DoIncludeSkeletons();
606 }
skeleton_iterator StdMeshSkeletonLoader::skeletons_begin ( ) const
inline

Definition at line 86 of file StdMeshLoader.h.

Referenced by StdMeshAnimationUpdate::StdMeshAnimationUpdate().

86 { return Skeletons.begin(); }

Here is the caller graph for this function:

skeleton_iterator StdMeshSkeletonLoader::skeletons_end ( ) const
inline

Definition at line 87 of file StdMeshLoader.h.

Referenced by StdMeshAnimationUpdate::StdMeshAnimationUpdate().

87 { return Skeletons.end(); }

Here is the caller graph for this function:

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

Definition at line 183 of file StdMeshLoaderBinary.cpp.

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

Referenced by LoadSkeletonBinary().

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

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: