diff options
author | Eugene Sandulenko | 2010-07-29 19:53:02 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-10-12 21:38:20 +0000 |
commit | a683a420a9e43705c972b5e74d55e319729e1a81 (patch) | |
tree | bde6e4abd417bdfaec120aa951da9a19be36b654 /engines/sword25/gfx/animationresource.cpp | |
parent | 7723d91c957d07205c51be32498d45cd0a78568f (diff) | |
download | scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.gz scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.bz2 scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.zip |
SWORD25: Importing original sources
svn-id: r53171
Diffstat (limited to 'engines/sword25/gfx/animationresource.cpp')
-rwxr-xr-x | engines/sword25/gfx/animationresource.cpp | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/engines/sword25/gfx/animationresource.cpp b/engines/sword25/gfx/animationresource.cpp new file mode 100755 index 0000000000..f1f88eaf2f --- /dev/null +++ b/engines/sword25/gfx/animationresource.cpp @@ -0,0 +1,323 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 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 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "animationresource.h" + +#include "kernel/kernel.h" +#include "kernel/string.h" +#include "package/packagemanager.h" +#include "util/tinyxml/tinyxml.h" +#include "bitmapresource.h" + +// ----------------------------------------------------------------------------- + +#define BS_LOG_PREFIX "ANIMATIONRESOURCE" + +// ----------------------------------------------------------------------------- +// Constants +// ----------------------------------------------------------------------------- + +namespace +{ + const int DEFAULT_FPS = 10; + const int MIN_FPS = 1; + const int MAX_FPS = 200; +} + +// ----------------------------------------------------------------------------- +// Construction / Destruction +// ----------------------------------------------------------------------------- + +BS_AnimationResource::BS_AnimationResource(const std::string& FileName) : + BS_Resource(FileName, BS_Resource::TYPE_ANIMATION), + m_Valid(false) +{ + // Pointer auf den Package-Manager bekommen + BS_PackageManager* PackagePtr = BS_Kernel::GetInstance()->GetPackage(); + BS_ASSERT(PackagePtr); + + // Animations-XML laden + TiXmlDocument Doc; + { + // Die Daten werden zunächst über den Package-Manager gelesen und dann in einen um ein Byte größeren Buffer kopiert und + // NULL-Terminiert, da TinyXML NULL-Terminierte Daten benötigt. + unsigned int FileSize; + char * LoadBuffer = (char *) PackagePtr->GetFile(GetFileName(), &FileSize); + if (!LoadBuffer) + { + BS_LOG_ERRORLN("Could not read \"%s\".", GetFileName().c_str()); + return; + } + std::vector<char> WorkBuffer(FileSize + 1); + memcpy(&WorkBuffer[0], LoadBuffer, FileSize); + delete LoadBuffer; + WorkBuffer[FileSize] = '\0'; + + // Datei parsen + Doc.Parse(&WorkBuffer[0]); + if (Doc.Error()) + { + BS_LOG_ERRORLN("The following TinyXML-Error occured while parsing \"%s\": %s", GetFileName().c_str(), Doc.ErrorDesc()); + return; + } + } + + // Wurzelknoten des Animations-Tags finden, prüfen und Attribute auslesen. + TiXmlElement* pElement; + { + TiXmlNode* pNode = Doc.FirstChild("animation"); + if (!pNode || pNode->Type() != TiXmlNode::ELEMENT) + { + BS_LOG_ERRORLN("No <animation> tag found in \"%s\".", GetFileName().c_str()); + return; + } + pElement = pNode->ToElement(); + + // Animation-Tag parsen + if (!ParseAnimationTag(*pElement, m_FPS, m_AnimationType)) + { + BS_LOG_ERRORLN("An error occurred while parsing <animation> tag in \"%s\".", GetFileName().c_str()); + return; + } + } + + // Zeit (in Millisekunden) bestimmen für die ein einzelner Frame angezeigt wird + m_MillisPerFrame = 1000000 / m_FPS; + + // In das Verzeichnis der Eingabedatei wechseln, da die Dateiverweise innerhalb der XML-Datei relativ zu diesem Verzeichnis sind. + std::string OldDirectory = PackagePtr->GetCurrentDirectory(); + int LastSlash = GetFileName().rfind('/'); + if (LastSlash != std::string::npos) + { + std::string Dir = GetFileName().substr(0, LastSlash); + PackagePtr->ChangeDirectory(Dir); + } + + // Nacheinander alle Frames-Informationen erstellen. + TiXmlElement* pFrameElement = pElement->FirstChild("frame")->ToElement(); + while (pFrameElement) + { + Frame CurFrame; + + if (!ParseFrameTag(*pFrameElement, CurFrame, *PackagePtr)) + { + BS_LOG_ERRORLN("An error occurred in \"%s\" while parsing <frame> tag.", GetFileName().c_str()); + return; + } + + m_Frames.push_back(CurFrame); + pFrameElement = pFrameElement->NextSiblingElement("frame"); + } + + // Ursprungsverzeichnis wieder herstellen + PackagePtr->ChangeDirectory(OldDirectory); + + // Sicherstellen, dass die Animation mindestens einen Frame besitzt + if (m_Frames.empty()) + { + BS_LOG_ERRORLN("\"%s\" does not have any frames.", GetFileName().c_str()); + return; + } + + // Alle Frame-Dateien werden vorgecached + if (!PrecacheAllFrames()) + { + BS_LOG_ERRORLN("Could not precache all frames of \"%s\".", GetFileName().c_str()); + return; + } + + // Feststellen, ob die Animation skalierbar ist + if (!ComputeFeatures()) + { + BS_LOG_ERRORLN("Could not determine the features of \"%s\".", GetFileName().c_str()); + return; + } + + m_Valid = true; +} + +// ----------------------------------------------------------------------------- +// Dokument-Parsermethoden +// ----------------------------------------------------------------------------- + +bool BS_AnimationResource::ParseAnimationTag(TiXmlElement& AnimationTag, int& FPS, BS_Animation::ANIMATION_TYPES & AnimationType) +{ + // FPS einlesen + const char* FPSString; + if (FPSString = AnimationTag.Attribute("fps")) + { + int TempFPS; + if (!BS_String::ToInt(std::string(FPSString), TempFPS) || TempFPS < MIN_FPS || TempFPS > MAX_FPS) + { + BS_LOG_WARNINGLN("Illegal fps value (\"%s\") in <animation> tag in \"%s\". Assuming default (\"%d\"). " + "The fps value has to be between %d and %d.", + FPSString, GetFileName().c_str(), DEFAULT_FPS, MIN_FPS, MAX_FPS); + } + else + FPS = TempFPS; + } + + // Loop-Typ einlesen + const char* LoopTypeString; + if (LoopTypeString = AnimationTag.Attribute("type")) + { + if (strcmp(LoopTypeString, "oneshot") == 0) + AnimationType = BS_Animation::AT_ONESHOT; + else if (strcmp(LoopTypeString, "loop") == 0) + AnimationType = BS_Animation::AT_LOOP; + else if (strcmp(LoopTypeString, "jojo") == 0) + AnimationType = BS_Animation::AT_JOJO; + else + BS_LOG_WARNINGLN("Illegal type value (\"%s\") in <animation> tag in \"%s\". Assuming default (\"loop\").", + LoopTypeString, GetFileName().c_str()); + } + + return true; +} + +// ----------------------------------------------------------------------------- + +bool BS_AnimationResource::ParseFrameTag(TiXmlElement& FrameTag, Frame& Frame, BS_PackageManager& PackageManager) +{ + const char* FileString = FrameTag.Attribute("file"); + if (!FileString) + { + BS_LOG_ERRORLN("<frame> tag without file attribute occurred in \"%s\".", GetFileName().c_str()); + return false; + } + Frame.FileName = PackageManager.GetAbsolutePath(FileString); + if (Frame.FileName == "") + { + BS_LOG_ERRORLN("Could not create absolute path for file specified in <frame> tag in \"%s\": \"%s\".", GetFileName().c_str(), FileString); + return false; + } + + const char* ActionString = FrameTag.Attribute("action"); + if (ActionString) + Frame.Action = ActionString; + + const char* HotspotxString = FrameTag.Attribute("hotspotx"); + const char* HotspotyString = FrameTag.Attribute("hotspoty"); + if ((!HotspotxString && HotspotyString) || + (HotspotxString && !HotspotyString)) + BS_LOG_WARNINGLN("%s attribute occurred without %s attribute in <frame> tag in \"%s\". Assuming default (\"0\").", + HotspotxString ? "hotspotx" : "hotspoty", + !HotspotyString ? "hotspoty" : "hotspotx", + GetFileName().c_str()); + + Frame.HotspotX = 0; + if (HotspotxString && !BS_String::ToInt(std::string(HotspotxString), Frame.HotspotX)) + BS_LOG_WARNINGLN("Illegal hotspotx value (\"%s\") in frame tag in \"%s\". Assuming default (\"%s\").", + HotspotxString,GetFileName().c_str(), Frame.HotspotX); + + Frame.HotspotY = 0; + if (HotspotyString && !BS_String::ToInt(std::string(HotspotyString), Frame.HotspotY)) + BS_LOG_WARNINGLN("Illegal hotspoty value (\"%s\") in frame tag in \"%s\". Assuming default (\"%s\").", + HotspotyString, GetFileName().c_str(), Frame.HotspotY); + + const char* FlipVString = FrameTag.Attribute("flipv"); + if (FlipVString) + { + if (!BS_String::ToBool(std::string(FlipVString), Frame.FlipV)) + { + BS_LOG_WARNINGLN("Illegal flipv value (\"%s\") in <frame> tag in \"%s\". Assuming default (\"false\").", + FlipVString, GetFileName().c_str()); + Frame.FlipV = false; + } + } + else + Frame.FlipV = false; + + const char* FlipHString = FrameTag.Attribute("fliph"); + if (FlipHString) + { + if (!BS_String::ToBool(FlipHString, Frame.FlipH)) + { + BS_LOG_WARNINGLN("Illegal fliph value (\"%s\") in <frame> tag in \"%s\". Assuming default (\"false\").", + FlipHString, GetFileName().c_str()); + Frame.FlipH = false; + } + } + else + Frame.FlipH = false; + + return true; +} + +// ----------------------------------------------------------------------------- + +BS_AnimationResource::~BS_AnimationResource() +{ +} + +// ----------------------------------------------------------------------------- + +bool BS_AnimationResource::PrecacheAllFrames() const +{ + std::vector<Frame>::const_iterator Iter = m_Frames.begin(); + for (; Iter != m_Frames.end(); ++Iter) + { + if (!BS_Kernel::GetInstance()->GetResourceManager()->PrecacheResource((*Iter).FileName)) + { + BS_LOG_ERRORLN("Could not precache \"%s\".", (*Iter).FileName.c_str()); + return false; + } + } + + return true; +} + +// ----------------------------------------------------------------------------- + +bool BS_AnimationResource::ComputeFeatures() +{ + BS_ASSERT(m_Frames.size()); + + // Alle Features werden als vorhanden angenommen + m_ScalingAllowed = true; + m_AlphaAllowed = true; + m_ColorModulationAllowed = true; + + // Alle Frame durchgehen und alle Features deaktivieren, die auch nur von einem Frame nicht unterstützt werden. + std::vector<Frame>::const_iterator Iter = m_Frames.begin(); + for (; Iter != m_Frames.end(); ++Iter) + { + BS_BitmapResource* pBitmap; + if (!(pBitmap = static_cast<BS_BitmapResource*> (BS_Kernel::GetInstance()->GetResourceManager()->RequestResource((*Iter).FileName)))) + { + BS_LOG_ERRORLN("Could not request \"%s\".", (*Iter).FileName.c_str()); + return false; + } + + if (!pBitmap->IsScalingAllowed()) + m_ScalingAllowed = false; + if (!pBitmap->IsAlphaAllowed()) + m_AlphaAllowed = false; + if (!pBitmap->IsColorModulationAllowed()) + m_ColorModulationAllowed = false; + + pBitmap->Release(); + } + + return true; +} |