# HG changeset patch # User phoku@33b003aa-7bff-0310-803a-e67f0ece8222 # Date 1223726639 0 # Node ID 6e7d228def303cb6b5dc1ba877e505137351ab3c # Parent 823544621b5bc9f6f923f196358e6dae2b4e58c6 Lazy loading for animations. Uses a Resource-Pointer class that behaves like a pointer to an IResource, but only loads the resource on demand. There's a slight change of API, which is already adapted to in the XML loaders. If you use Animation.addFrame directly, either adapt to the change or wait a few hours for a backwards compatibility solution. diff -r 823544621b5b -r 6e7d228def30 doc/dependencies/filedeps.dot --- a/doc/dependencies/filedeps.dot Sat Oct 11 06:23:45 2008 +0000 +++ b/doc/dependencies/filedeps.dot Sat Oct 11 12:03:59 2008 +0000 @@ -350,6 +350,8 @@ "engine/core/util/resource/pool.h" -> "resource.h" "engine/core/util/resource/pool.h" -> "resource_location.h" "engine/core/util/resource/resource.h" -> "resource_location.h" + "engine/core/util/resource/resource_ptr.h" -> "pool.h" + "engine/core/util/resource/resource_ptr.h" -> "resource.h" "engine/core/util/structures/point.h" -> "util/base/fife_stdint.h" "engine/core/util/structures/point.h" -> "util/math/fife_math.h" "engine/core/util/structures/quadtree.h" -> "rect.h" @@ -455,6 +457,7 @@ "engine/core/video/animation.cpp" -> "util/time/timemanager.h" "engine/core/video/animation.h" -> "util/base/fife_stdint.h" "engine/core/video/animation.h" -> "util/base/resourceclass.h" + "engine/core/video/animation.h" -> "util/resource/resource_ptr.h" "engine/core/video/animationpool.h" -> "animation.h" "engine/core/video/animationpool.h" -> "util/resource/pool.h" "engine/core/video/cursor.cpp" -> "animation.h" diff -r 823544621b5b -r 6e7d228def30 engine/core/util/resource/resource.i --- a/engine/core/util/resource/resource.i Sat Oct 11 06:23:45 2008 +0000 +++ b/engine/core/util/resource/resource.i Sat Oct 11 12:03:59 2008 +0000 @@ -22,6 +22,7 @@ %{ #include "util/resource/resource.h" +#include "util/resource/resource_ptr.h" #include "util/resource/resource_location.h" #include "util/resource/pool.h" %} @@ -96,4 +97,14 @@ private: Pool(); }; + + class ResourcePtr { + public: + ResourcePtr(IResource* ptr = 0); + ResourcePtr(Pool* pool,int index); + ResourcePtr(const ResourcePtr& r); + void release(); + void load(); + void unload(); + }; } diff -r 823544621b5b -r 6e7d228def30 engine/core/util/resource/resource_ptr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/util/resource/resource_ptr.h Sat Oct 11 12:03:59 2008 +0000 @@ -0,0 +1,154 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_RESOURE_PTR_H +#define FIFE_RESOURE_PTR_H + +// Standard C++ library includes + +// 3rd party library includes + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +#include "resource.h" +#include "pool.h" + +namespace FIFE { + + /** A lazy loading resource. + */ + class ResourcePtr { + public: + ResourcePtr(IResource* ptr = 0) : m_ptr(ptr),m_pool(0),m_index(Pool::INVALID_ID) { + if( m_ptr ) + m_ptr->addRef(); + } + + ResourcePtr(Pool* pool,int index) : m_ptr(0),m_pool(pool),m_index(index) { + } + + ResourcePtr(const ResourcePtr& r) + : m_ptr(r.m_ptr),m_pool(r.m_pool),m_index(r.m_index) { + if(m_ptr) { + m_ptr->addRef(); + } + } + + ResourcePtr& operator=(const ResourcePtr& r) { + if( this == &r ) + return *this; + release(); + m_ptr = r.m_ptr; + m_pool = r.m_pool; + m_index = r.m_index; + if(m_ptr) { + m_ptr->addRef(); + } + return *this; + } + + ~ResourcePtr() { + release(); + } + + IResource& operator->() { + load(); + return *m_ptr; + } + + const IResource& operator->() const { + constLoad(); + return *m_ptr; + } + + operator bool() const { + return isValid(); + } + + bool isValid() const { + return m_ptr || isLoadable(); + } + + bool isLoadable() const { + return m_pool && m_index != Pool::INVALID_ID; + } + + bool operator==(const ResourcePtr& r) const { + if( isLoadable() && r.isLoadable() ) + return m_index == r.m_index && m_pool == r.m_pool; + if( !isLoadable() && !r.isLoadable() ) + return m_ptr == r.m_ptr; + return false; + } + + bool operator<(const ResourcePtr& r) const { + if( isLoadable() && r.isLoadable() ) + { + if( m_pool == r.m_pool ) + return m_index < r.m_index; + return m_pool < r.m_pool; + } + if( !isLoadable() && !r.isLoadable() ) + return m_ptr < r.m_ptr; + return isLoadable() < r.isLoadable(); + } + + void release() { + if(m_ptr) { + m_ptr->decRef(); + } + m_ptr = 0; + } + + void load() { + constLoad(); + } + + void unload() { + release(); + if( isLoadable() ) { + m_pool->release(m_index); + } + } + + template + T* get() { + if( isValid() ) + load(); + return dynamic_cast(m_ptr); + } + + private: + void constLoad() const { + if( m_ptr ) + return; + m_ptr = &m_pool->get(m_index); + m_ptr->addRef(); + } + mutable IResource* m_ptr; + Pool* m_pool; + int m_index; + }; +} +#endif + diff -r 823544621b5b -r 6e7d228def30 engine/core/video/animation.cpp --- a/engine/core/video/animation.cpp Sat Oct 11 06:23:45 2008 +0000 +++ b/engine/core/video/animation.cpp Sat Oct 11 12:03:59 2008 +0000 @@ -46,20 +46,22 @@ } Animation::~Animation() { - std::vector::const_iterator i(m_frames.begin()); - while (i != m_frames.end()) { - i->img->decRef(); - i++; - } +// std::vector::const_iterator i(m_frames.begin()); +// while (i != m_frames.end()) { +// i->img->decRef(); +// i++; +// } } - void Animation::addFrame(Image* image, unsigned int duration) { - image->addRef(); +// void Animation::addFrame(Image* image, unsigned int duration) { +// addFrame(ResourcePtr(image),duration); +// } + void Animation::addFrame(ResourcePtr image, unsigned int duration) { FrameInfo info; info.index = m_frames.size(); info.duration = duration; - info.img = image; + info.image = image; m_frames.push_back(info); std::map::const_iterator i(m_framemap.end()); @@ -95,7 +97,7 @@ Image* Animation::getFrame(int index) { if (isValidIndex(index)) { - return m_frames[index].img; + return m_frames[index].image.get(); } else { return NULL; } diff -r 823544621b5b -r 6e7d228def30 engine/core/video/animation.h --- a/engine/core/video/animation.h Sat Oct 11 06:23:45 2008 +0000 +++ b/engine/core/video/animation.h Sat Oct 11 12:03:59 2008 +0000 @@ -37,6 +37,7 @@ // First block: files included from the FIFE root src directory // Second block: files included from the same folder #include "util/base/resourceclass.h" +#include "util/resource/resource_ptr.h" namespace FIFE { @@ -72,7 +73,7 @@ * @param image Pointer to Image. Does not transfer the ownership * @param duration Duration for given frame in the animation */ - void addFrame(Image* image, unsigned int duration); + void addFrame(ResourcePtr image, unsigned int duration); /** Get the frame index that matches given timestamp. In case there is no exact match, * correct frame is calculated. E.g. if there are frames for timestamps 50 and 100 @@ -137,7 +138,7 @@ struct FrameInfo { unsigned int index; unsigned int duration; - Image* img; + ResourcePtr image; }; ResourceLocation m_location; diff -r 823544621b5b -r 6e7d228def30 engine/core/video/image_location.cpp --- a/engine/core/video/image_location.cpp Sat Oct 11 06:23:45 2008 +0000 +++ b/engine/core/video/image_location.cpp Sat Oct 11 12:03:59 2008 +0000 @@ -41,9 +41,9 @@ } bool ImageLocation::operator ==(const ResourceLocation& loc) const { - if (!ResourceLocation::operator==(loc)) { + if( m_type != loc.getType() ) return false; - } + const ImageLocation* r = dynamic_cast(&loc); if (!r) { return false; @@ -64,6 +64,8 @@ if (m_parent_image != r->m_parent_image) { return false; } + if( getFilename() != loc.getFilename() ) + return false; return true; } diff -r 823544621b5b -r 6e7d228def30 engine/core/video/video.i --- a/engine/core/video/video.i Sat Oct 11 06:23:45 2008 +0000 +++ b/engine/core/video/video.i Sat Oct 11 12:03:59 2008 +0000 @@ -89,7 +89,7 @@ public: explicit Animation(); ~Animation(); - void addFrame(Image* image, unsigned int duration); + void addFrame(ResourcePtr image, unsigned int duration); int getFrameIndex(unsigned int timestamp); Image* getFrame(int index); Image* getFrameByTimestamp(unsigned int timestamp); diff -r 823544621b5b -r 6e7d228def30 engine/extensions/serializers/xmlanimation.py --- a/engine/extensions/serializers/xmlanimation.py Sat Oct 11 06:23:45 2008 +0000 +++ b/engine/extensions/serializers/xmlanimation.py Sat Oct 11 12:03:59 2008 +0000 @@ -44,10 +44,13 @@ path.pop() path.append(str(source)) - image = self.imagepool.getImage(self.imagepool.getIndex('/'.join(path))) - image.setXShift(frame_x_offset) - image.setYShift(frame_y_offset) - animation.addFrame(image, frame_delay); + image_location = fife.ImageLocation('/'.join(path)) + image_location.setXShift(frame_x_offset) + image_location.setYShift(frame_y_offset) + + image_index = self.imagepool.addResourceFromLocation(image_location) + animation.addFrame(fife.ResourcePtr(self.imagepool,image_index), frame_delay) + #print "...",image_index,image_location.getFilename() animation.thisown = 0 return animation diff -r 823544621b5b -r 6e7d228def30 engine/extensions/serializers/xmlmap.py --- a/engine/extensions/serializers/xmlmap.py Sat Oct 11 06:23:45 2008 +0000 +++ b/engine/extensions/serializers/xmlmap.py Sat Oct 11 12:03:59 2008 +0000 @@ -85,7 +85,9 @@ return self.map def parse_imports(self, mapelt, map): - if self.callback is not None: + parsedImports = {} + + if self.callback: tmplist = mapelt.findall('import') i = float(0) @@ -97,6 +99,12 @@ if dir: dir = reverse_root_subfile(self.source, dir) + # Don't parse duplicate imports + if (dir,file) in parsedImports: + print "Duplicate import:" ,(dir,file) + continue + parsedImports[(dir,file)] = 1 + if file and dir: loaders.loadImportFile('/'.join(dir, file), self.engine) elif file: @@ -107,14 +115,10 @@ else: print 'Empty import statement?' - if self.callback is not None: + if self.callback: i += 1 self.callback('loaded imports', float( i / float(len(tmplist)) * 0.25 + 0.25 ) ) - - # cleanup - if self.callback is not None: - del tmplist - del i + def parse_layers(self, mapelt, map): if self.callback is not None: @@ -261,7 +265,7 @@ inst.act('default', target, True) def parse_cameras(self, mapelt, map): - if self.callback is not None: + if self.callback: tmplist = mapelt.findall('camera') i = float(0) @@ -297,11 +301,7 @@ except fife.Exception, e: print e.getMessage() - if self.callback is not None: + if self.callback: i += 1 self.callback('loaded camera: ' + str(id), float( i / len(tmplist) * 0.25 + 0.75 ) ) - # cleanup - if self.callback is not None: - del tmplist - del i