aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/gfx/animationresource.cpp
diff options
context:
space:
mode:
authorEugene Sandulenko2010-07-29 19:53:02 +0000
committerEugene Sandulenko2010-10-12 21:38:20 +0000
commita683a420a9e43705c972b5e74d55e319729e1a81 (patch)
treebde6e4abd417bdfaec120aa951da9a19be36b654 /engines/sword25/gfx/animationresource.cpp
parent7723d91c957d07205c51be32498d45cd0a78568f (diff)
downloadscummvm-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-xengines/sword25/gfx/animationresource.cpp323
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;
+}