diff --git a/engines/grim/costume.cpp b/engines/grim/costume.cpp index 575fa4c83cc..fc15d190db6 100644 --- a/engines/grim/costume.cpp +++ b/engines/grim/costume.cpp @@ -29,7 +29,7 @@ #include "engines/grim/grim.h" #include "engines/grim/resource.h" #include "engines/grim/model.h" - +#include "engines/grim/emi/modelemi.h" #include "engines/grim/costume/chore.h" #include "engines/grim/costume/head.h" #include "engines/grim/emi/costume/emianim_component.h" @@ -105,21 +105,16 @@ namespace Grim { // marked OBJSTATE_OVERLAY. So the BitmapComponent just needs to pass // along setKey requests to the actual bitmap object. -Costume::Costume(const Common::String &fname, Common::SeekableReadStream *data, Costume *prevCost) : +Costume::Costume(const Common::String &fname, Costume *prevCost) : Object(), _head(new Head()), _chores(NULL) { _fname = fname; _lookAtRate = 200; _prevCostume = prevCost; - if (g_grim->getGameType() == GType_MONKEY4) { - loadEMI(data, prevCost); - } else { - TextSplitter ts(data); - loadGRIM(ts, prevCost); - } } -void Costume::loadGRIM(TextSplitter &ts, Costume *prevCost) { +void Costume::load(Common::SeekableReadStream *data) { + TextSplitter ts(data); ts.expectString("costume v0.1"); ts.expectString("section tags"); int numTags; @@ -152,7 +147,7 @@ void Costume::loadGRIM(TextSplitter &ts, Costume *prevCost) { // A Parent ID of "-1" indicates that the component should // use the properties of the previous costume as a base if (parentID == -1) { - if (prevCost) { + if (_prevCostume) { MainModelComponent *mmc; // However, only the first item can actually share the @@ -160,7 +155,7 @@ void Costume::loadGRIM(TextSplitter &ts, Costume *prevCost) { // that component so it knows what to do if (i == 0) parentID = -2; - prevComponent = prevCost->_components[0]; + prevComponent = _prevCostume->_components[0]; mmc = dynamic_cast(prevComponent); // Make sure that the component is valid if (!mmc) @@ -205,85 +200,6 @@ void Costume::loadGRIM(TextSplitter &ts, Costume *prevCost) { } } -void Costume::loadEMI(Common::SeekableReadStream *data, Costume *prevCost) { - Common::Listcomponents; - - _numChores = data->readUint32LE(); - _chores = new Chore *[_numChores]; - for (int i = 0; i < _numChores; i++) { - _chores[i] = new PoolChore(); - uint32 nameLength; - Component *prevComponent = NULL; - nameLength = data->readUint32LE(); - data->read(_chores[i]->_name, nameLength); - float length; - data->read(&length, 4); - _chores[i]->_length = (int)length; - - _chores[i]->_owner = this; - _chores[i]->_numTracks = data->readUint32LE(); - _chores[i]->_tracks = new ChoreTrack[_chores[i]->_numTracks]; - - for (int k = 0; k < _chores[i]->_numTracks; k++) { - int componentNameLength = data->readUint32LE(); - - char *name = new char[componentNameLength]; - data->read(name, componentNameLength); - - data->readUint32LE(); - int parentID = data->readUint32LE(); - if (parentID == -1 && prevCost) { - MainModelComponent *mmc; - - // However, only the first item can actually share the - // node hierarchy with the previous costume, so flag - // that component so it knows what to do - if (i == 0) - parentID = -2; - prevComponent = prevCost->_components[0]; - mmc = dynamic_cast(prevComponent); - // Make sure that the component is valid - if (!mmc) - prevComponent = NULL; - } - // Actually load the appropriate component - Component *component = loadComponentEMI(parentID < 0 ? NULL : _components[parentID], parentID, name, prevComponent); - - - //Component *component = loadComponentEMI(name, parent); - - components.push_back(component); - - ChoreTrack &track = _chores[i]->_tracks[k]; - track.numKeys = data->readUint32LE(); - track.keys = new TrackKey[track.numKeys]; - - // this is probably wrong - track.compID = 0; - for (int j = 0; j < track.numKeys; j++) { - float time, value; - data->read(&time, 4); - data->read(&value, 4); - track.keys[j].time = (int)time; - track.keys[j].value = (int)value; - } - delete[] name; - } - //_chores[i]._tracks->compID; - } - - _numComponents = components.size(); - _components = new Component *[_numComponents]; - int i = 0; - for (Common::List::iterator it = components.begin(); it != components.end(); ++it, ++i) { - _components[i] = *it; - if (!_components[i]) - continue; - _components[i]->setCostume(this); - _components[i]->init(); - } -} - Costume::~Costume() { if (_chores) { stopChores(); @@ -332,54 +248,6 @@ Component *Costume::loadComponent (tag32 tag, Component *parent, int parentID, c return NULL; } -Component *Costume::loadComponentEMI(Component *parent, int parentID, const char *name, Component *prevComponent) { - // some have an exclimation mark, this could mean something. - // for now, return 0 otherwise it will just crash in some other part. - //return 0; - - assert(name[0] == '!'); - ++name; - - char type[5]; - tag32 tag = 0; - memcpy(&tag, name, 4); - memcpy(&type, name, 4); - type[4] = 0; - - name += 4; - - if (FROM_BE_32(tag) == MKTAG('m','e','s','h')) { - //Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement MESH-handling: %s" , name); - return new EMIMeshComponent(parent, parentID, name, prevComponent, tag); - } else if (FROM_BE_32(tag) == MKTAG('s','k','e','l')) { - //Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement SKEL-handling: %s" , name); - return new EMISkelComponent(parent, parentID, name, prevComponent, tag); - } else if (FROM_BE_32(tag) == MKTAG('t','e','x','i')) { - Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement TEXI-handling: %s" , name); - //return new MaterialComponent(parent, parentID, name, tag); - } else if (FROM_BE_32(tag) == MKTAG('a','n','i','m')) { - //Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement ANIM-handling: %s" , name); - return new EMIAnimComponent(parent, parentID, name, prevComponent, tag); - } else if (FROM_BE_32(tag) == MKTAG('l','u','a','c')) { - Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement LUAC-handling: %s" , name); - } else if (FROM_BE_32(tag) == MKTAG('l','u','a','v')) { - Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement LUAV-handling: %s" , name); - //return new LuaVarComponent(parent, parentID, name, tag); - } else if (FROM_BE_32(tag) == MKTAG('s','p','r','t')) { - Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement SPRT-handling: %s" , name); - //return new SpriteComponent(parent, parentID, name, tag); - } else if (FROM_BE_32(tag) == MKTAG('s','h','a','d')) { - Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement SHAD-handling: %s" , name); - } else { - error("Actor::loadComponentEMI missing tag: %s for %s", name, type); - } - /* - char t[4]; - memcpy(t, &tag, sizeof(tag32)); - warning("loadComponent: Unknown tag '%c%c%c%c', name '%s'", t[0], t[1], t[2], t[3], name);*/ - return NULL; -} - ModelComponent *Costume::getMainModelComponent() const { for (int i = 0; i < _numComponents; i++) { // Needs to handle Main Models (pigeons) and normal Models diff --git a/engines/grim/costume.h b/engines/grim/costume.h index 013e53c20e4..efd7938798a 100644 --- a/engines/grim/costume.h +++ b/engines/grim/costume.h @@ -44,12 +44,10 @@ class Head; class Costume : public Object { public: - Costume(const Common::String &filename, Common::SeekableReadStream *data, Costume *prevCost); - - void loadGRIM(TextSplitter &ts, Costume *prevCost); - void loadEMI(Common::SeekableReadStream *data, Costume *prevCost); + Costume(const Common::String &filename, Costume *prevCost); virtual ~Costume(); + virtual void load(Common::SeekableReadStream *data); const Common::String &getFilename() const { return _fname; } void playChore(const char *name); @@ -77,10 +75,10 @@ public: CMap *getCMap() { return _cmap; } - int update(uint frameTime); + virtual int update(uint frameTime); void animate(); void setupTextures(); - void draw(); + virtual void draw(); void getBoundingBox(int *x1, int *y1, int *x2, int *y2); void setPosRotate(Math::Vector3d pos, const Math::Angle &pitch, const Math::Angle &yaw, const Math::Angle &roll); @@ -88,12 +86,15 @@ public: Costume *getPreviousCostume() const; - void saveState(SaveGame *state) const; - bool restoreState(SaveGame *state); + virtual void saveState(SaveGame *state) const; + virtual bool restoreState(SaveGame *state); + + Component *getComponent(int num) { return _components[num]; } +protected: + virtual Component *loadComponent(tag32 tag, Component *parent, int parentID, const char *name, Component *prevComponent); + + void load(TextSplitter &ts, Costume *prevCost); -private: - Component *loadComponent(tag32 tag, Component *parent, int parentID, const char *name, Component *prevComponent); - Component *loadComponentEMI(Component *parent, int parentID, const char *name, Component *prevComponent); ModelComponent *getMainModelComponent() const; Common::String _fname; diff --git a/engines/grim/costume/chore.cpp b/engines/grim/costume/chore.cpp index effcfcb2280..a43c771d9fb 100644 --- a/engines/grim/costume/chore.cpp +++ b/engines/grim/costume/chore.cpp @@ -174,4 +174,9 @@ void Chore::fadeOut(uint msecs) { fade(Animation::FadeOut, msecs); } +void Chore::createTracks(int num) { + _numTracks = num; + _tracks = new ChoreTrack[_numTracks]; +} + } // end of namespace Grim diff --git a/engines/grim/costume/chore.h b/engines/grim/costume/chore.h index 68b3795d0cf..d14a8910eac 100644 --- a/engines/grim/costume/chore.h +++ b/engines/grim/costume/chore.h @@ -32,6 +32,7 @@ namespace Grim { class Costume; class Animation; +class Component; struct TrackKey { int time, value; @@ -41,6 +42,7 @@ struct ChoreTrack { int compID; int numKeys; TrackKey *keys; + Component *component; }; class Chore { @@ -61,6 +63,9 @@ public: bool isPlaying() { return _playing; } virtual int getId() { return _choreId; } + + void setOwner(Costume *owner) { _owner = owner; } + void createTracks(int num); private: void setKeys(int startTime, int stopTime); @@ -78,6 +83,7 @@ private: int _currTime; friend class Costume; + friend class EMICostume; }; class PoolChore : public PoolObject, public Chore { diff --git a/engines/grim/costume/component.h b/engines/grim/costume/component.h index 073b834ec9c..19bceb311ac 100644 --- a/engines/grim/costume/component.h +++ b/engines/grim/costume/component.h @@ -71,6 +71,7 @@ protected: void resetHierCMap(); friend class Costume; + friend class EMICostume; }; } // end of namespace Grim diff --git a/engines/grim/emi/animationemi.h b/engines/grim/emi/animationemi.h index c4217afb75a..fd2e93164c2 100644 --- a/engines/grim/emi/animationemi.h +++ b/engines/grim/emi/animationemi.h @@ -8,12 +8,12 @@ * 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 diff --git a/engines/grim/emi/costume/emianim_component.cpp b/engines/grim/emi/costume/emianim_component.cpp index 8fef6dc3875..6920e613496 100644 --- a/engines/grim/emi/costume/emianim_component.cpp +++ b/engines/grim/emi/costume/emianim_component.cpp @@ -23,8 +23,12 @@ #include "common/foreach.h" #include "engines/grim/emi/costume/emianim_component.h" +#include "engines/grim/emi/costume/emiskel_component.h" #include "engines/grim/resource.h" +#include "engines/grim/costume.h" +#include "engines/grim/emi/costumeemi.h" #include "engines/grim/emi/modelemi.h" +#include "engines/grim/emi/skeleton.h" #include "engines/grim/emi/animationemi.h" namespace Grim { @@ -50,7 +54,10 @@ void EMIAnimComponent::reset() { } void EMIAnimComponent::draw() { - + EMISkelComponent *skel = ((EMICostume*) _cost)->_emiSkel; + if (skel && skel->_obj) { + skel->_obj->setAnim(_obj); + } } } // end of namespace Grim diff --git a/engines/grim/emi/costume/emimesh_component.cpp b/engines/grim/emi/costume/emimesh_component.cpp index 40e3d3a50dc..b260e2a7be2 100644 --- a/engines/grim/emi/costume/emimesh_component.cpp +++ b/engines/grim/emi/costume/emimesh_component.cpp @@ -25,6 +25,7 @@ #include "engines/grim/emi/costume/emimesh_component.h" #include "engines/grim/emi/modelemi.h" #include "engines/grim/resource.h" +#include "engines/grim/costume.h" namespace Grim { diff --git a/engines/grim/emi/costume/emimesh_component.h b/engines/grim/emi/costume/emimesh_component.h index 9840f7805a2..515fa67aefd 100644 --- a/engines/grim/emi/costume/emimesh_component.h +++ b/engines/grim/emi/costume/emimesh_component.h @@ -38,7 +38,7 @@ public: void reset(); void draw(); -private: +public: bool _hierShared; Common::List _children; EMIMeshComponent *_parentModel; diff --git a/engines/grim/emi/costume/emiskel_component.cpp b/engines/grim/emi/costume/emiskel_component.cpp index 6e56bea95cd..dde41a725af 100644 --- a/engines/grim/emi/costume/emiskel_component.cpp +++ b/engines/grim/emi/costume/emiskel_component.cpp @@ -26,6 +26,7 @@ #include "engines/grim/resource.h" #include "engines/grim/emi/modelemi.h" #include "engines/grim/emi/skeleton.h" +#include "engines/grim/costume.h" namespace Grim { @@ -42,6 +43,9 @@ void EMISkelComponent::init() { } int EMISkelComponent::update(uint time) { + if (_obj) { + _obj->animate(time/1000.f); + } return 0; } diff --git a/engines/grim/emi/costume/emiskel_component.h b/engines/grim/emi/costume/emiskel_component.h index 970c1b01494..3fe0a975a23 100644 --- a/engines/grim/emi/costume/emiskel_component.h +++ b/engines/grim/emi/costume/emiskel_component.h @@ -40,7 +40,7 @@ public: void reset(); void draw(); -private: +public: bool _hierShared; Component *_parentModel; Common::String _filename; diff --git a/engines/grim/emi/costumeemi.cpp b/engines/grim/emi/costumeemi.cpp new file mode 100644 index 00000000000..ae0f5db9bf3 --- /dev/null +++ b/engines/grim/emi/costumeemi.cpp @@ -0,0 +1,238 @@ +/* ResidualVM - A 3D game interpreter + * + * ResidualVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This library 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 + * + */ + +#include "common/endian.h" + +#include "engines/grim/debug.h" +#include "engines/grim/costume.h" +#include "engines/grim/grim.h" +#include "engines/grim/resource.h" +#include "engines/grim/emi/costumeemi.h" +#include "engines/grim/emi/modelemi.h" +#include "engines/grim/costume/chore.h" +#include "engines/grim/costume/head.h" +#include "engines/grim/emi/costume/emianim_component.h" +#include "engines/grim/emi/costume/emimesh_component.h" +#include "engines/grim/emi/costume/emiskel_component.h" +#include "engines/grim/costume/main_model_component.h" + +namespace Grim { + +EMICostume::EMICostume(const Common::String &fname, Costume *prevCost) : + Costume(fname, prevCost), _emiSkel(NULL), _emiMesh(NULL) { +} + +void EMICostume::load(Common::SeekableReadStream *data) { + Common::Listcomponents; + + _numChores = data->readUint32LE(); + _chores = new Chore *[_numChores]; + for (int i = 0; i < _numChores; i++) { + _chores[i] = new PoolChore(); + uint32 nameLength; + Component *prevComponent = NULL; + nameLength = data->readUint32LE(); + data->read(_chores[i]->_name, nameLength); + float length; + data->read(&length, 4); + _chores[i]->_length = (int)length; + + _chores[i]->setOwner(this); + _chores[i]->createTracks(data->readUint32LE()); + + for (int k = 0; k < _chores[i]->_numTracks; k++) { + int componentNameLength = data->readUint32LE(); + + char *name = new char[componentNameLength]; + data->read(name, componentNameLength); + + data->readUint32LE(); + int parentID = data->readUint32LE(); + if (parentID == -1 && _prevCostume) { + MainModelComponent *mmc; + + // However, only the first item can actually share the + // node hierarchy with the previous costume, so flag + // that component so it knows what to do + if (i == 0) + parentID = -2; + prevComponent = _prevCostume->getComponent(0); + mmc = dynamic_cast(prevComponent); + // Make sure that the component is valid + if (!mmc) + prevComponent = NULL; + } + // Actually load the appropriate component + Component *component = loadComponent(parentID < 0 ? NULL : _components[parentID], parentID, name, prevComponent); + if (component) { + component->setCostume(this); + component->init(); + + if (strcmp(_chores[i]->_name, "wear_default") == 0) { + EMIMeshComponent *m = dynamic_cast(component); + EMISkelComponent *s = dynamic_cast(component); + if (m) { + _emiMesh = m; + if (_emiSkel) { + _emiMesh->_obj->setSkeleton(_emiSkel->_obj); + } + } else if (s) { + _emiSkel = s; + if (_emiMesh) { + _emiMesh->_obj->setSkeleton(_emiSkel->_obj); + } + } + + } + } + + //Component *component = loadComponentEMI(name, parent); + + components.push_back(component); + + ChoreTrack &track = _chores[i]->_tracks[k]; + track.numKeys = data->readUint32LE(); + track.keys = new TrackKey[track.numKeys]; + track.component = component; + + // this is probably wrong + track.compID = 0; + for (int j = 0; j < track.numKeys; j++) { + float time, value; + data->read(&time, 4); + data->read(&value, 4); + track.keys[j].time = (int)time; + track.keys[j].value = (int)value; + } + delete[] name; + } + //_chores[i]._tracks->compID; + } + + _numComponents = components.size(); + _components = new Component *[_numComponents]; + int i = 0; + for (Common::List::iterator it = components.begin(); it != components.end(); ++it, ++i) { + _components[i] = *it; + if (!_components[i]) + continue; + + } +} + +Component *EMICostume::loadComponent(Component *parent, int parentID, const char *name, Component *prevComponent) { + // some have an exclimation mark, this could mean something. + // for now, return 0 otherwise it will just crash in some other part. + //return 0; + + assert(name[0] == '!'); + ++name; + + char type[5]; + tag32 tag = 0; + memcpy(&tag, name, 4); + memcpy(&type, name, 4); + type[4] = 0; + + name += 4; + + if (FROM_BE_32(tag) == MKTAG('m','e','s','h')) { + //Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement MESH-handling: %s" , name); + return new EMIMeshComponent(parent, parentID, name, prevComponent, tag); + } else if (FROM_BE_32(tag) == MKTAG('s','k','e','l')) { + //Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement SKEL-handling: %s" , name); + return new EMISkelComponent(parent, parentID, name, prevComponent, tag); + } else if (FROM_BE_32(tag) == MKTAG('t','e','x','i')) { + Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement TEXI-handling: %s" , name); + //return new MaterialComponent(parent, parentID, name, tag); + } else if (FROM_BE_32(tag) == MKTAG('a','n','i','m')) { + //Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement ANIM-handling: %s" , name); + return new EMIAnimComponent(parent, parentID, name, prevComponent, tag); + } else if (FROM_BE_32(tag) == MKTAG('l','u','a','c')) { + Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement LUAC-handling: %s" , name); + } else if (FROM_BE_32(tag) == MKTAG('l','u','a','v')) { + Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement LUAV-handling: %s" , name); + //return new LuaVarComponent(parent, parentID, name, tag); + } else if (FROM_BE_32(tag) == MKTAG('s','p','r','t')) { + Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement SPRT-handling: %s" , name); + //return new SpriteComponent(parent, parentID, name, tag); + } else if (FROM_BE_32(tag) == MKTAG('s','h','a','d')) { + Debug::warning(Debug::Costumes, "Actor::loadComponentEMI Implement SHAD-handling: %s" , name); + } else { + error("Actor::loadComponentEMI missing tag: %s for %s", name, type); + } + /* + char t[4]; + memcpy(t, &tag, sizeof(tag32)); + warning("loadComponent: Unknown tag '%c%c%c%c', name '%s'", t[0], t[1], t[2], t[3], name);*/ + return NULL; +} + +void EMICostume::draw() { + for (Common::List::iterator it = _playingChores.begin(); it != _playingChores.end(); ++it) { + Chore *c = (*it); + for (int i = 0; i < c->_numTracks; ++i) { + if (c->_tracks[i].component) { + c->_tracks[i].component->draw(); + } + } + } + + if (_emiMesh) { + _emiMesh->draw(); + } +} + +int EMICostume::update(uint time) { + for (Common::List::iterator i = _playingChores.begin(); i != _playingChores.end(); ++i) { + (*i)->update(time); + if (!(*i)->_playing) { + i = _playingChores.erase(i); + --i; + } + } + + int marker = 0; + for (int i = 0; i < _numComponents; i++) { + if (_components[i]) { + _components[i]->setMatrix(_matrix); + int m = _components[i]->update(time); + if (m > 0) { + marker = m; + } + } + } + + return marker; +} + +void EMICostume::saveState(SaveGame *state) const { + // TODO + return; +} + +bool EMICostume::restoreState(SaveGame *state) { + // TODO + return true; +} + +} // end of namespace Grim diff --git a/engines/grim/emi/costumeemi.h b/engines/grim/emi/costumeemi.h new file mode 100644 index 00000000000..adc9120d610 --- /dev/null +++ b/engines/grim/emi/costumeemi.h @@ -0,0 +1,61 @@ +/* ResidualVM - A 3D game interpreter + * + * ResidualVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This library 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 GRIM_COSTUMEEMI_H +#define GRIM_COSTUMEEMI_H + +#include "common/stream.h" + +#include "engines/grim/object.h" +#include "engines/grim/costume.h" + +namespace Grim { + +typedef uint32 tag32; + +class EMISkelComponent; +class EMIMeshComponent; + +class EMICostume : public Costume { +public: + EMICostume(const Common::String &filename, Costume *prevCost); + + void load(Common::SeekableReadStream *data); + + int update(uint frameTime); + void draw(); + + void saveState(SaveGame *state) const; + bool restoreState(SaveGame *state); + +public: + EMISkelComponent *_emiSkel; + EMIMeshComponent *_emiMesh; +private: + Component *loadComponent(Component *parent, int parentID, const char *name, Component *prevComponent); + + friend class Chore; +}; + +} // end of namespace Grim + +#endif diff --git a/engines/grim/emi/modelemi.cpp b/engines/grim/emi/modelemi.cpp index de7c2befe91..82cdbe45627 100644 --- a/engines/grim/emi/modelemi.cpp +++ b/engines/grim/emi/modelemi.cpp @@ -195,8 +195,13 @@ void EMIModel::loadMesh(Common::SeekableReadStream *data) { } void EMIModel::setSkeleton(Skeleton *skel) { + if (_skeleton == skel) { + return; + } _skeleton = skel; - + if (!skel || !_numBoneInfos) { + return; + } int boneVert = 0; delete[] _vertexBoneInfo; _vertexBoneInfo = NULL; delete[] _vertexBone; _vertexBone = NULL; @@ -226,7 +231,7 @@ void EMIModel::setSkeleton(Skeleton *skel) { } void EMIModel::prepareForRender() { - if (!_skeleton) + if (!_skeleton || !_vertexBoneInfo) return; for (int i = 0; i < _numVertices; i++) { _drawVertices[i] = _vertices[i]; diff --git a/engines/grim/emi/skeleton.cpp b/engines/grim/emi/skeleton.cpp index 8ab9d7e99d5..95d9b75e7b3 100644 --- a/engines/grim/emi/skeleton.cpp +++ b/engines/grim/emi/skeleton.cpp @@ -8,12 +8,12 @@ * 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 @@ -32,7 +32,7 @@ namespace Grim { #define ROTATE_OP 4 #define TRANSLATE_OP 3 -Skeleton::Skeleton(const Common::String &filename, Common::SeekableReadStream *data) { +Skeleton::Skeleton(const Common::String &filename, Common::SeekableReadStream *data) : _anim(NULL), _time(0) { loadSkeleton(data); } @@ -52,7 +52,7 @@ void Skeleton::loadSkeleton(Common::SeekableReadStream *data) { data->read(inString, 32); _joints[i]._parent = inString; - _joints[i]._trans.readFromStream(data); + _joints[i]._trans.readFromStream(data); _joints[i]._quat.readFromStream(data); _joints[i]._parentIndex = findJointIndex(_joints[i]._parent, i); @@ -83,13 +83,20 @@ void Skeleton::initBones() { } void Skeleton::resetAnim() { + _time = 0; for (int i = 0; i < _numJoints; i++) { _joints[i]._finalMatrix = _joints[i]._absMatrix; } } void Skeleton::setAnim(AnimationEmi *anim) { + if (_anim == anim) { + return; + } _anim = anim; + if (!_anim) { + return; + } for (int i = 0; i < _numJoints; i++) { _joints[i]._animIndex = -1; } @@ -108,16 +115,15 @@ int Skeleton::findJointIndex(Common::String name, int max) { return i; } } - } + } return -1; } -void Skeleton::animate(float time) { +void Skeleton::animate(float delta) { if (_anim == NULL) return; - - if (time > _anim->_duration) { - time = 0.0; + _time += delta; + if (_time > _anim->_duration) { resetAnim(); } @@ -143,12 +149,12 @@ void Skeleton::animate(float time) { // Find the right keyframe for (curKeyFrame = 0; curKeyFrame < _curBone->_count; curKeyFrame++) { if (_curBone->_operation == ROTATE_OP) { - if (_curBone->_rotations[curKeyFrame]->_time >= time) { + if (_curBone->_rotations[curKeyFrame]->_time >= _time) { keyfIdx = curKeyFrame; break; } } else if (_curBone->_operation == TRANSLATE_OP) { - if (_curBone->_translations[curKeyFrame]->_time >= time) { + if (_curBone->_translations[curKeyFrame]->_time >= _time) { keyfIdx = curKeyFrame; break; } @@ -166,7 +172,7 @@ void Skeleton::animate(float time) { quat = _curBone->_rotations[keyfIdx-1]->_quat; } else { timeDelta = _curBone->_rotations[keyfIdx-1]->_time - _curBone->_rotations[keyfIdx]->_time; - interpVal = (time - _curBone->_rotations[keyfIdx]->_time) / timeDelta; + interpVal = (_time - _curBone->_rotations[keyfIdx]->_time) / timeDelta; // Might be the other way around (keyfIdx - 1 slerped against keyfIdx) quat = _curBone->_rotations[keyfIdx]->_quat.slerpQuat(_curBone->_rotations[keyfIdx - 1]->_quat, interpVal); @@ -179,7 +185,7 @@ void Skeleton::animate(float time) { vec = _curBone->_translations[keyfIdx-1]->_vec; } else { timeDelta = _curBone->_translations[keyfIdx-1]->_time - _curBone->_translations[keyfIdx]->_time; - interpVal = (time - _curBone->_translations[keyfIdx]->_time) / timeDelta; + interpVal = (_time - _curBone->_translations[keyfIdx]->_time) / timeDelta; vec.x() = _curBone->_translations[keyfIdx-1]->_vec.x() + (_curBone->_translations[keyfIdx]->_vec.x() - _curBone->_translations[keyfIdx-1]->_vec.x()) * interpVal; diff --git a/engines/grim/emi/skeleton.h b/engines/grim/emi/skeleton.h index 946a6efcfb2..073818ef19e 100644 --- a/engines/grim/emi/skeleton.h +++ b/engines/grim/emi/skeleton.h @@ -8,12 +8,12 @@ * 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 @@ -64,6 +64,7 @@ public: void setAnim(AnimationEmi *anim); void animate(float time); int findJointIndex(Common::String name, int max); + float _time; }; } // end of namespace Grim diff --git a/engines/grim/module.mk b/engines/grim/module.mk index ebd29f1f154..d955f2f5e87 100644 --- a/engines/grim/module.mk +++ b/engines/grim/module.mk @@ -24,6 +24,7 @@ MODULE_OBJS := \ emi/sound/emisound.o \ emi/sound/codecs/scx.o \ emi/animationemi.o \ + emi/costumeemi.o \ emi/modelemi.o \ emi/skeleton.o \ emi/lua_v2.o \ diff --git a/engines/grim/resource.cpp b/engines/grim/resource.cpp index 93c3992f5dd..002656a8a04 100644 --- a/engines/grim/resource.cpp +++ b/engines/grim/resource.cpp @@ -35,6 +35,7 @@ #include "engines/grim/inputdialog.h" #include "engines/grim/debug.h" #include "engines/grim/emi/animationemi.h" +#include "engines/grim/emi/costumeemi.h" #include "engines/grim/emi/modelemi.h" #include "engines/grim/emi/skeleton.h" #include "engines/grim/patchr.h" @@ -330,10 +331,15 @@ Costume *ResourceLoader::loadCostume(const Common::String &filename, Costume *pr if (!stream) { error("Could not find costume \"%s\"", filename.c_str()); } - - Costume *result = new Costume(filename, stream, prevCost); + Costume *result; + if (g_grim->getGameType() == GType_MONKEY4) { + result = new EMICostume(filename, prevCost); + } else { + result = new Costume(filename, prevCost); + } + result->load(stream); delete stream; - + return result; } @@ -461,7 +467,7 @@ AnimationEmi *ResourceLoader::loadAnimationEmi(const Common::String &filename) { AnimationEmi *result = new AnimationEmi(filename, stream); delete stream; - + return result; }