XMLNode* XMLNode::GetNext(const char* name) { return XMLNode_GetNext(this, name); }
SpriteObj* Sprite_Create(const std::string& name, bool immediate) { immediate = immediate || !g_supportAsynchronousResourceLoading; SpriteResource* resource = static_cast<SpriteResource*>(Resource_Find("sprite", name)); if (resource) Resource_IncRefCount(resource); // Create sprite from XML else if (!strstr(name.c_str(), ".")) { const std::string path = name + ".sprite.xml"; XMLDoc doc; if (!doc.Load(path)) { Log::Error("Failed to load sprite resource from " + path); return NULL; } XMLNode* spriteNode = doc.AsNode()->GetFirstNode("sprite"); if (!spriteNode) { Log::Error("Failed to load sprite resource from " + path + ", reason: root node 'sprite' not found."); return NULL; } MaterialObj* material = NULL; if (const char* materialName = XMLNode_GetAttributeValue(spriteNode, "material")) { material = Material_Create(materialName); if (!material) { Log::Error("Failed to load sprite resource from " + path + ", reason: can't load material " + materialName); return NULL; } } resource = new SpriteResource(); resource->state = ResourceState_CreationInProgress; resource->name = name; Material_SetHandle(material, resource->material); Resource_IncRefCount(resource); // Load animations std::string defaultAnimationName; for (XMLNode* animNode = XMLNode_GetFirstNode(spriteNode, "animation"); animNode; animNode = XMLNode_GetNext(animNode, "animation")) { const std::string name = XMLNode_GetAttributeValue(animNode, "name"); SpriteResource::Animation& anim = map_add(resource->animations, name); anim.name = name; // Get frame time XMLNode_GetAttributeValueFloat(animNode, "frameTime", anim.frameTime, 0.1f); // Check blend mode //XMLNode_GetAttributeValueBool(animNode, "blending", anim->blendFrames); // Check if default bool isDefault; if (defaultAnimationName.empty() || (XMLNode_GetAttributeValueBool(animNode, "isDefault", isDefault) && isDefault)) defaultAnimationName = anim.name; // Load all frames and events float time = 0.0f; for (XMLNode* elemNode = XMLNode_GetFirstNode(animNode); elemNode; elemNode = XMLNode_GetNext(elemNode)) { const char* elemName = XMLNode_GetName(elemNode); if (!strcmp(elemName, "frame")) { SpriteResource::Frame& frame = vector_add(anim.frames); const char* textureName = XMLNode_GetAttributeValue(elemNode, "texture"); frame.texture.Create(textureName, immediate); if (!frame.texture.IsValid()) { Log::Error("Failed to load sprite resource from " + path + ", reason: failed to load texture " + textureName); delete resource; return NULL; } time += anim.frameTime; } else if (!strcmp(elemName, "event")) { SpriteResource::Event& ev = vector_add(anim.events); ev.time = time; ev.name = XMLNode_GetAttributeValue(elemNode, "name"); } } anim.totalTime = (float) anim.frames.size() * anim.frameTime; } resource->defaultAnimation = &resource->animations[defaultAnimationName]; SpriteResource_CheckCreated(resource); } // Create sprite from texture else { TextureObj* texture = Texture_Create(name, immediate); if (!texture) { Log::Error("Failed to create sprite resource from texture " + name); return NULL; } resource = new SpriteResource(); resource->state = ResourceState_CreationInProgress; resource->name = name; Resource_IncRefCount(resource); // Add simple animation with one animation frame SpriteResource::Animation& animation = map_add(resource->animations, resource->name); animation.frameTime = 1.0f; animation.totalTime = 1.0f; SpriteResource::Frame& frame = vector_add(animation.frames); Texture_SetHandle(texture, frame.texture); resource->defaultAnimation = &animation; SpriteResource_CheckCreated(resource); Texture_Destroy(texture); } if (!resource) return NULL; // Create sprite SpriteObj* sprite = new SpriteObj(); sprite->resource = resource; Sprite_PlayAnimation(sprite); return sprite; }