/* Moonfall Copyright (C) 2008 Alex Yatskov This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "Pch.h" #include "ActorManifest.h" #include "Actor.h" #include "ActorPropertyAnimation.h" #include "ActorPropertyPhysics.h" #include "ActorPropertyScript.h" #include "ActorPropertySprite.h" #include "Surface.h" #include "Sprite.h" bool ActorManifest::LoadManifest(const char* filename) { const boost::shared_ptr buffer = System::LoadFile(filename); if (!buffer) { TRACE_ERROR(boost::format("Cannot load actor manifest %s") % filename); return false; } TiXmlDocument document; if (!document.Parse(static_cast(buffer->Get()))) { TRACE_ERROR(boost::format("Cannot parse actor manifest %s") % filename); return false; } const TiXmlElement* rootElement = document.RootElement(); if (rootElement == NULL || strcmp(rootElement->Value(), "Manifest") != 0) { return false; } for (const TiXmlElement* actorElement = rootElement->FirstChildElement(); actorElement != NULL; actorElement = actorElement->NextSiblingElement()) { if (strcmp(actorElement->Value(), "Actor") != 0) { continue; } const char* alias = actorElement->Attribute("alias"); if (alias == NULL) { TRACE_WARNING("Actor definition is missing required fields"); continue; } if (m_manifest.find(alias) != m_manifest.end()) { TRACE_WARNING(boost::format("Duplicate actor %s") % alias); continue; } ActorEntry entry; const char* thumbnail = actorElement->Attribute("thumbnail"); if (thumbnail != NULL) { entry.thumbnail = thumbnail; } int dynamic = 0; actorElement->QueryIntAttribute("dynamic", &dynamic); entry.dynamic = dynamic != 0; int layer = ACTOR_LAYER_GROUND1; actorElement->QueryIntAttribute("layer", &layer); if (layer < ACTOR_LAYER_COUNT) { entry.layer = static_cast(layer); } for (const TiXmlElement* childElement = actorElement->FirstChildElement(); childElement != NULL; childElement = childElement->NextSiblingElement()) { if (strcmp(childElement->Value(), "Properties") == 0) { ParsePropertyElement(childElement, &entry); } } m_manifest.insert(std::make_pair(alias, entry)); } return true; } void ActorManifest::ClearManifest() { m_manifest.clear(); } void ActorManifest::ParsePropertyElement(const TiXmlElement* element, ActorEntry* actorEntry) { for (const TiXmlElement* propertyElement = element->FirstChildElement(); propertyElement != NULL; propertyElement = propertyElement->NextSiblingElement()) { if (strcmp(propertyElement->Value(), "Animation") == 0) { ParsePropertyElementAnimation(propertyElement, actorEntry); actorEntry->properties |= BIT(ACTOR_PROPERTY_TYPE_ANIMATION); } else if (strcmp(propertyElement->Value(), "Sprite") == 0) { ParsePropertyElementSprite(propertyElement, actorEntry); actorEntry->properties |= BIT(ACTOR_PROPERTY_TYPE_SPRITE); } else if (strcmp(propertyElement->Value(), "Physics") == 0) { ParsePropertyElementPhysics(propertyElement, actorEntry); actorEntry->properties |= BIT(ACTOR_PROPERTY_TYPE_PHYSICS); } else if (strcmp(propertyElement->Value(), "Script") == 0) { ParsePropertyElementScript(propertyElement, actorEntry); actorEntry->properties |= BIT(ACTOR_PROPERTY_TYPE_SCRIPT); } } } void ActorManifest::ParsePropertyElementAnimation(const TiXmlElement* element, ActorEntry* actorEntry) { int animationPlay = 0; element->QueryIntAttribute("play", &animationPlay); actorEntry->animation.play = animationPlay != 0; int animationLoop = 0; element->QueryIntAttribute("loop", &animationLoop); actorEntry->animation.loop = animationLoop != 0; const char* animationResource = element->Attribute("resource"); if (animationResource != NULL) { actorEntry->animation.resource = animationResource; } } void ActorManifest::ParsePropertyElementSprite(const TiXmlElement* element, ActorEntry* actorEntry) { const char* spriteResource = element->Attribute("resource"); if (spriteResource != NULL) { actorEntry->sprite.resource = spriteResource; } } void ActorManifest::ParsePropertyElementPhysics(const TiXmlElement* element, ActorEntry* actorEntry) { element->QueryFloatAttribute("velocityX", &actorEntry->physics.velocity.x); element->QueryFloatAttribute("velocityY", &actorEntry->physics.velocity.y); } void ActorManifest::ParsePropertyElementScript(const TiXmlElement* element, ActorEntry* actorEntry) { const char* scriptResource = element->Attribute("resource"); if (scriptResource != NULL) { actorEntry->script.resource = scriptResource; } } boost::shared_ptr ActorManifest::CreateActor(const char* actorAlias, const char* actorName, unsigned allowedProperties) const { ActorMap::const_iterator iter = m_manifest.find(actorAlias); if (iter == m_manifest.end()) { TRACE_ERROR(boost::format("Cannot create actor %s") % actorAlias); return boost::shared_ptr(); } const ActorEntry& actorEntry = iter->second; boost::shared_ptr actor(new Actor(actorAlias, actorName)); actor->SetDynamic(actorEntry.dynamic); actor->SetLayer(actorEntry.layer); if (actorEntry.properties & BIT(ACTOR_PROPERTY_TYPE_ANIMATION) & allowedProperties) { boost::shared_ptr property = actor->AddProperty().lock(); if (!actorEntry.animation.resource.empty()) { property->SetAnimation(actorEntry.animation.resource.c_str()); } if (actorEntry.animation.play) { property->PlayAnimation(actorEntry.animation.loop); } } if (actorEntry.properties & BIT(ACTOR_PROPERTY_TYPE_SPRITE) & allowedProperties) { boost::shared_ptr property = actor->AddProperty().lock(); property->SetSprite(actorEntry.sprite.resource.c_str()); } if (actorEntry.properties & BIT(ACTOR_PROPERTY_TYPE_PHYSICS) & allowedProperties) { boost::shared_ptr property = actor->AddProperty().lock(); property->SetVelocity(actorEntry.physics.velocity); } if (actorEntry.properties & BIT(ACTOR_PROPERTY_TYPE_SCRIPT) & allowedProperties) { boost::shared_ptr property = actor->AddProperty().lock(); property->SetScript(actorEntry.script.resource.c_str()); } return actor; } void ActorManifest::SummarizeActors(std::vector* summary) const { for (ActorMap::const_iterator iter = m_manifest.begin(); iter != m_manifest.end(); ++iter) { const std::string& actorAlias = iter->first; const ActorEntry& actorEntry = iter->second; boost::shared_ptr actorSurface; if (!actorEntry.thumbnail.empty()) { boost::shared_ptr actorSprite = System::LoadSprite(actorEntry.thumbnail.c_str()); if (actorSprite) { actorSurface = System::CreateSurface(actorSprite->GetSize(), COLOR_MODE_RGB_888); actorSurface->Clear(Color4b(0x00, 0x00, 0xff, 0x00)); actorSprite->Render(actorSurface); } } summary->push_back(ActorSummary(actorAlias, actorEntry.properties, actorSurface, actorEntry.layer)); } } bool ActorManifest::SummarizeActor(const char* actorAlias, ActorSummary* summary) const { ActorMap::const_iterator iter = m_manifest.find(actorAlias); if (iter == m_manifest.end()) { return false; } const ActorEntry& actorEntry = iter->second; boost::shared_ptr actorSurface; if (!actorEntry.thumbnail.empty()) { boost::shared_ptr actorSprite = System::LoadSprite(actorEntry.thumbnail.c_str()); if (actorSprite) { actorSurface = System::CreateSurface(actorSprite->GetSize(), COLOR_MODE_RGB_888); actorSurface->Clear(Color4b(0x00, 0x00, 0xff, 0x00)); actorSprite->Render(actorSurface); } } *summary = ActorSummary(actorAlias, actorEntry.properties, actorSurface, actorEntry.layer); return true; }