[Scummvm-cvs-logs] CVS: residual actor.cpp,1.4,1.5 actor.h,1.1,1.2 costume.cpp,1.5,1.6 costume.h,1.3,1.4 lua.cpp,1.12,1.13 resource.cpp,1.2,1.3 resource.h,1.2,1.3
Daniel Schepler
dschepler at users.sourceforge.net
Wed Aug 20 08:35:24 CEST 2003
Update of /cvsroot/scummvm/residual
In directory sc8-pr-cvs1:/tmp/cvs-serv13778
Modified Files:
actor.cpp actor.h costume.cpp costume.h lua.cpp resource.cpp
resource.h
Log Message:
Major overhaul and simplification of the construction method for
costumes.
I also added a bit of documentation on the design of the costume class,
along with how I think the bitmap objects should be handled.
Index: actor.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/actor.cpp,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- actor.cpp 20 Aug 2003 06:59:11 -0000 1.4
+++ actor.cpp 20 Aug 2003 14:29:59 -0000 1.5
@@ -91,29 +91,35 @@
return true;
}
-void Actor::pushCostume(Costume *c) {
- Costume *copy = new Costume(*c, currentCostume());
- costumeStack_.push_back(copy);
+void Actor::pushCostume(const char *name) {
+ Costume *newCost = ResourceLoader::instance()->
+ loadCostume(name, currentCostume());
+ costumeStack_.push_back(newCost);
}
-void Actor::setCostume(Costume *c) {
+void Actor::setCostume(const char *name) {
if (! costumeStack_.empty())
popCostume();
- pushCostume(c);
+ pushCostume(name);
}
void Actor::popCostume() {
- costumeStack_.pop_back();
+ if (! costumeStack_.empty()) {
+ delete costumeStack_.back();
+ costumeStack_.pop_back();
+ }
}
void Actor::clearCostumes() {
// Make sure to destroy costume copies in reverse order
- while (! costumeStack_.empty())
+ while (! costumeStack_.empty()) {
+ delete costumeStack_.back();
costumeStack_.pop_back();
+ }
}
Costume *Actor::findCostume(const char *name) {
- for (std::list<ResPtr<Costume> >::iterator i = costumeStack_.begin();
+ for (std::list<Costume *>::iterator i = costumeStack_.begin();
i != costumeStack_.end(); i++)
if (std::strcmp((*i)->filename(), name) == 0)
return *i;
@@ -121,7 +127,7 @@
}
void Actor::update() {
- for (std::list<ResPtr<Costume> >::iterator i = costumeStack_.begin();
+ for (std::list<Costume *>::iterator i = costumeStack_.begin();
i != costumeStack_.end(); i++)
(*i)->update();
}
Index: actor.h
===================================================================
RCS file: /cvsroot/scummvm/residual/actor.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- actor.h 15 Aug 2003 19:41:26 -0000 1.1
+++ actor.h 20 Aug 2003 14:29:59 -0000 1.2
@@ -62,8 +62,8 @@
void sayLine(const char *msg);
bool talking();
- void pushCostume(Costume *c);
- void setCostume(Costume *c);
+ void pushCostume(const char *name);
+ void setCostume(const char *name);
void popCostume();
void clearCostumes();
Costume *currentCostume() {
@@ -89,7 +89,7 @@
float walkRate_, turnRate_;
bool visible_;
ResPtr<Sound> talkSound_;
- std::list<ResPtr<Costume> > costumeStack_;
+ std::list<Costume *> costumeStack_;
friend class Engine;
};
Index: costume.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/costume.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- costume.cpp 20 Aug 2003 01:15:36 -0000 1.5
+++ costume.cpp 20 Aug 2003 14:29:59 -0000 1.6
@@ -29,11 +29,64 @@
#include <cstdio>
#include <map>
+// A costume in the Residual/GrimE engine consists of a set of
+// components, and a set of chores. Each component represents an
+// on-screen object, or a keyframe animation, or a sound effect; each
+// chore gives a set of instructions for how to move and/or activate
+// or deactivate each component at certain times.
+//
+// Each actor contains a stack of costumes, on which a new costume can
+// be pushed or from which an old costume can be popped at any time.
+// For the most part, these costumes are independent. The exception
+// is the main model component ('MMDL'), for which multiple costumes
+// share the same base 3D object (if they refer to the same file).
+//
+// This is complicated by the fact that multiple keyframe animations
+// can have an effect on the positions of the 3D objects. Each
+// keyframe animation has certain nodes internally "tagged", and the
+// keyframe components specify precedences for the tagged nodes and
+// for the non-tagged nodes. If the highest precedence for a given
+// node is given by multiple keyframe animations, their contributions
+// are averaged.
+//
+// Each component can implement several virtual methods which are
+// called by the costume:
+//
+// init() -- allows the component to initialize itself. This is
+// separate from the constructor since there are cases where
+// information from child components may be needed before
+// the object can be fully constructed. This is particularly
+// the case with colormaps, which are needed before even
+// starting to load a 3D model.
+// setKey(val) -- notifies the component of a change in the "state"
+// given by a playing chore
+// update() -- gives the component a chance to update its internal
+// state once every frame
+// draw() -- actually draws the component onto the screen
+// reset() -- notifies the component that a chore controlling it
+// has stopped
+//
+// For the 3D objects, a model's component first initializes internal
+// state for the model's nodes in its update() method. Then the
+// keyframes' update() methods work with this data to implement the
+// precedence and add up all contributions for the highest precedence.
+// Then the model's draw() method does the averaging and draws the
+// polygons accordingly. (Actually, this is a lie -- the top-level
+// 3D objects draw themselves and all their children. This makes it
+// easier to move objects Manny is holding when his hands move, for
+// example.)
+//
+// For bitmaps, the actual drawing is handled by the Scene class. The
+// bitmaps to be drawn are associated to the needed camera setups
+// using NewObjectState; bitmaps marked OBJSTATE_UNDERLAY and
+// OBJSTATE_STATE are drawn first, then the 3D objects, then bitmaps
+// marked OBJSTATE_OVERLAY. So the BitmapComponent just needs to pass
+// along setKey requests to the actual bitmap object.
+
class BitmapComponent : public Costume::Component {
public:
BitmapComponent(Costume::Component *parent, int parentID,
const char *filename);
- BitmapComponent *copy(Costume::Component *newParent);
void update();
void draw();
@@ -49,12 +102,11 @@
public:
ModelComponent(Costume::Component *parent, int parentID,
const char *filename);
- ModelComponent *copy(Costume::Component *newParent);
+ void init();
void setKey(int val);
void update();
void reset();
void setColormap(Colormap *c);
- void loadModel();
~ModelComponent();
Model::HierNode *hierarchy() { return hier_; }
@@ -71,8 +123,9 @@
public:
MainModelComponent(Costume::Component *parent, int parentID,
const char *filename);
- MainModelComponent *copy(Costume::Component *newParent);
- MainModelComponent *copy(Model *prevObj, Model::HierNode *prevHier);
+ MainModelComponent(const char *filename, Model *prevObj,
+ Model::HierNode *prevHier);
+ void init();
void update();
void reset();
~MainModelComponent();
@@ -87,7 +140,7 @@
public:
MeshComponent(Costume::Component *parent, int parentID,
const char *name);
- MeshComponent *copy(Costume::Component *newParent);
+ void init();
void setKey(int val);
void reset();
~MeshComponent() { }
@@ -107,12 +160,6 @@
warning("Instanced BitmapComponenet from Costume renderer: NOT IMPLEMENTED YET");
}
-BitmapComponent *BitmapComponent::copy(Costume::Component *newParent) {
- BitmapComponent *result = new BitmapComponent(*this);
- result->setParent(newParent);
- return result;
-}
-
void BitmapComponent::draw() {
;
}
@@ -127,20 +174,28 @@
cmap_(NULL), hier_(NULL) {
}
-ModelComponent *ModelComponent::copy(Costume::Component *newParent) {
- loadModel();
- ModelComponent *result = new ModelComponent(*this);
- result->setParent(newParent);
- result->hier_ = obj_->copyHierarchy();
- result->hier_->hierVisible_ = false;
- if (newParent != NULL) {
- MeshComponent *mc = dynamic_cast<MeshComponent *>(newParent);
+void ModelComponent::init() {
+ if (obj_ == NULL) { // Skip loading if it was initialized
+ // by the sharing MainModelComponent
+ // constructor before
+ if (cmap_ == NULL) {
+ warning("No colormap specified for %s\n", filename_.c_str());
+ cmap_ = ResourceLoader::instance()->loadColormap("item.cmp");
+ }
+ obj_ = ResourceLoader::instance()->loadModel(filename_.c_str(), *cmap_);
+ hier_ = obj_->copyHierarchy();
+ hier_->hierVisible_ = false;
+ }
+
+ // If we're the child of a mesh component, put our nodes in the
+ // parent object's tree.
+ if (parent_ != NULL) {
+ MeshComponent *mc = dynamic_cast<MeshComponent *>(parent_);
if (mc != NULL)
- mc->node()->addChild(result->hier_);
+ mc->node()->addChild(hier_);
else
warning("Parent of model %s wasn't a mesh\n", filename_.c_str());
}
- return result;
}
void ModelComponent::setKey(int val) {
@@ -166,15 +221,6 @@
void ModelComponent::setColormap(Colormap *c) {
cmap_ = c;
- obj_ = ResourceLoader::instance()->loadModel(filename_.c_str(), *c);
- hier_ = obj_->copyHierarchy();
-}
-
-void ModelComponent::loadModel() {
- if (obj_ == NULL) {
- warning("No colormap specified for %s\n", filename_.c_str());
- setColormap(ResourceLoader::instance()->loadColormap("item.cmp"));
- }
}
ModelComponent::~ModelComponent() {
@@ -184,7 +230,6 @@
}
void ModelComponent::draw() {
- loadModel();
if (parent_ == NULL) // Otherwise it was already drawn by
// being included in the parent's hierarchy
hier_->draw();
@@ -197,23 +242,18 @@
{
}
-MainModelComponent *MainModelComponent::copy(Costume::Component *newParent) {
- loadModel();
- MainModelComponent *result = new MainModelComponent(*this);
- result->setParent(newParent);
- result->hier_ = obj_->copyHierarchy();
- result->hierShared_ = false;
- return result;
+// Constructor used if sharing the main model with the previous costume
+MainModelComponent::MainModelComponent(const char *filename, Model *prevObj,
+ Model::HierNode *prevHier) :
+ ModelComponent(NULL, -1, filename), hierShared_(true)
+{
+ obj_ = prevObj;
+ hier_ = prevHier;
}
-MainModelComponent *MainModelComponent::copy(Model *prevObj,
- Model::HierNode *prevHier) {
- MainModelComponent *result = new MainModelComponent(*this);
- result->setParent(NULL);
- result->obj_ = prevObj;
- result->hier_ = prevHier;
- result->hierShared_ = true;
- return result;
+void MainModelComponent::init() {
+ ModelComponent::init();
+ hier_->hierVisible_ = true;
}
void MainModelComponent::update() {
@@ -255,12 +295,6 @@
mc->setColormap(cmap_);
}
-ColormapComponent *ColormapComponent::copy(Costume::Component *newParent) {
- ColormapComponent *result = new ColormapComponent(*this);
- result->setParent(newParent);
- return result;
-}
-
ColormapComponent::~ColormapComponent() {
}
@@ -268,7 +302,7 @@
public:
KeyframeComponent(Costume::Component *parent, int parentID,
const char *filename);
- KeyframeComponent *copy(Costume::Component *newParent);
+ void init();
void setKey(int val);
void update();
void reset();
@@ -350,17 +384,14 @@
keyf_->animate(hier_, currTime_ / 1000.0, priority1_, priority2_);
}
-KeyframeComponent *KeyframeComponent::copy(Costume::Component *newParent) {
- KeyframeComponent *result = new KeyframeComponent(*this);
- result->setParent(newParent);
- ModelComponent *mc = dynamic_cast<ModelComponent *>(newParent);
+void KeyframeComponent::init() {
+ ModelComponent *mc = dynamic_cast<ModelComponent *>(parent_);
if (mc != NULL)
- result->hier_ = mc->hierarchy();
+ hier_ = mc->hierarchy();
else {
warning("Parent of %s was not a model\n", keyf_->filename());
- result->hier_ = NULL;
+ hier_ = NULL;
}
- return result;
}
MeshComponent::MeshComponent(Costume::Component *parent, int parentID,
@@ -370,17 +401,14 @@
error("Couldn't parse mesh name %s\n", name);
}
-MeshComponent *MeshComponent::copy(Costume::Component *newParent) {
- MeshComponent *result = new MeshComponent(*this);
- result->setParent(newParent);
- ModelComponent *mc = dynamic_cast<ModelComponent *>(newParent);
+void MeshComponent::init() {
+ ModelComponent *mc = dynamic_cast<ModelComponent *>(parent_);
if (mc != NULL)
- result->node_ = mc->hierarchy() + num_;
+ node_ = mc->hierarchy() + num_;
else {
warning("Parent of mesh %d was not a model\n", num_);
- result->node_ = NULL;
+ node_ = NULL;
}
- return result;
}
void MeshComponent::setKey(int val) {
@@ -395,7 +423,6 @@
public:
LuaVarComponent(Costume::Component *parent, int parentID,
const char *name);
- LuaVarComponent *copy(Costume::Component *newParent);
void setKey(int val);
~LuaVarComponent() { }
@@ -408,12 +435,6 @@
Costume::Component(parent, parentID), name_(name) {
}
-LuaVarComponent *LuaVarComponent::copy(Costume::Component *newParent) {
- LuaVarComponent *result = new LuaVarComponent(*this);
- result->setParent(newParent);
- return result;
-}
-
void LuaVarComponent::setKey(int val) {
lua_pushnumber(val);
lua_setglobal(const_cast<char *>(name_.c_str()));
@@ -423,7 +444,6 @@
public:
SoundComponent(Costume::Component *parent, int parentID,
const char *name);
- SoundComponent *copy(Costume::Component *newParent);
void setKey(int val);
void reset();
~SoundComponent() { }
@@ -444,12 +464,6 @@
sound_ = ResourceLoader::instance()->loadSound(filename);
}
-SoundComponent *SoundComponent::copy(Costume::Component *newParent) {
- SoundComponent *result = new SoundComponent(*this);
- result->setParent(newParent);
- return result;
-}
-
void SoundComponent::setKey(int val) {
switch (val) {
case 0:
@@ -467,8 +481,9 @@
Mixer::instance()->stopSfx(sound_);
}
-Costume::Costume(const char *filename, const char *data, int len) :
- Resource(filename), orig_(NULL)
+Costume::Costume(const char *filename, const char *data, int len,
+ Costume *prevCost) :
+ fname_(filename)
{
TextSplitter ts(data, len);
ts.expectString("costume v0.1");
@@ -496,12 +511,32 @@
&namePos) < 4)
error("Bad component specification line: `%s'\n", line);
ts.nextLine();
+
+ // Check for sharing a main model with the previous costume
+ if (id == 0 && prevCost != NULL &&
+ std::memcmp(tags[tagID], "mmdl", 4) == 0) {
+ MainModelComponent *mmc =
+ dynamic_cast<MainModelComponent *>(prevCost->components_[0]);
+ if (mmc != NULL && mmc->filename_ == std::string(line + namePos)) {
+ components_[id] = new MainModelComponent(line + namePos,
+ mmc->obj_,
+ mmc->hier_);
+ continue;
+ }
+ }
+
components_[id] =
loadComponent(tags[tagID],
parentID == -1 ? NULL : components_[parentID], parentID,
line + namePos);
}
+ delete[] tags;
+
+ for (int i = 0; i < numComponents_; i++)
+ if (components_[i] != NULL)
+ components_[i]->init();
+
ts.expectString("section chores");
ts.scanString(" numchores %d", 1, &numChores_);
chores_ = new Chore[numChores_];
@@ -524,8 +559,6 @@
for (int i=0; i < MAX_TALK_CHORES; i++)
talkChores_[i] = -1;
-
-delete[] tags;
}
Costume::~Costume() {
@@ -651,42 +684,6 @@
warning("Unknown tag '%.4s', name '%s'\n", tag, name);
return NULL;
-}
-
-Costume::Costume(Costume &orig, Costume *prev) : Resource(orig), orig_(&orig) {
- numComponents_ = orig.numComponents_;
- components_ = new Component*[numComponents_];
- int start = 0;
-
- MainModelComponent *mmc =
- dynamic_cast<MainModelComponent *>(orig.components_[0]);
- MainModelComponent *prev_mmc =
- (prev == NULL ? NULL :
- dynamic_cast<MainModelComponent *>(prev->components_[0]));
- if (mmc != NULL && prev_mmc != NULL &&
- mmc->filename_ == prev_mmc->filename_) {
- prev_mmc->loadModel();
- components_[0] = mmc->copy(prev_mmc->obj_, prev_mmc->hier_);
- start = 1;
- }
-
- for (int i = start; i < numComponents_; i++) {
- if (orig.components_[i] != NULL) {
- Component *newParent;
- if (orig.components_[i]->parentID_ >= 0)
- newParent = components_[orig.components_[i]->parentID_];
- else
- newParent = NULL;
- components_[i] = orig.components_[i]->copy(newParent);
- }
- else
- components_[i] = NULL;
- }
- numChores_ = orig.numChores_;
- chores_ = new Chore[numChores_];
- std::memcpy(chores_, orig.chores_, numChores_ * sizeof(Chore));
- for (int i = 0; i < numChores_; i++)
- chores_[i].owner_ = this;
}
void Costume::stopChores() {
Index: costume.h
===================================================================
RCS file: /cvsroot/scummvm/residual/costume.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- costume.h 19 Aug 2003 17:51:37 -0000 1.3
+++ costume.h 20 Aug 2003 14:29:59 -0000 1.4
@@ -18,22 +18,21 @@
#ifndef COSTUME_H
#define COSTUME_H
-#include "resource.h"
+#include <string>
#define MAX_TALK_CHORES 10
class TextSplitter;
class Actor;
-class Costume : public Resource {
+class Costume {
public:
- Costume(const char *filename, const char *data, int len);
-
- // Create a copy of orig, sharing the model data from prev if
- // appropriate
- Costume(Costume &orig, Costume *prev);
+ Costume(const char *filename, const char *data, int len,
+ Costume *prevCost);
~Costume();
+ const char *filename() const { return fname_.c_str(); }
+
void playChore(int num) { chores_[num].play(); }
void playChoreLooping(int num) { chores_[num].playLooping(); }
void setChoreLooping(int num, bool val) { chores_[num].setLooping(val); }
@@ -52,28 +51,26 @@
class Component {
public:
Component(Component *parent, int parentID);
- virtual Component *copy(Component *newParent) = 0;
+ virtual void init() { }
virtual void setKey(int /* val */) { }
virtual void update() { }
virtual void draw() { }
virtual void reset() { }
virtual ~Component() { }
- void setParent(Component *newParent);
-
protected:
int parentID_;
Component *parent_, *child_, *sibling_;
+ void setParent(Component *newParent);
friend class Costume;
};
private:
- // Reference the original copy of the costume in the cache
- ResPtr<Costume> orig_;
-
Component *loadComponent(char tag[4], Component *parent, int parentID,
const char *name);
+
+ std::string fname_;
int numComponents_;
Component **components_;
Index: lua.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/lua.cpp,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- lua.cpp 20 Aug 2003 10:38:30 -0000 1.12
+++ lua.cpp 20 Aug 2003 14:29:59 -0000 1.13
@@ -323,8 +323,7 @@
static void PushActorCostume() {
Actor *act = check_actor(1);
const char *costumeName = luaL_check_string(2);
- Costume *c = ResourceLoader::instance()->loadCostume(costumeName);
- act->pushCostume(c);
+ act->pushCostume(costumeName);
}
static void SetActorCostume() {
@@ -333,8 +332,7 @@
act->clearCostumes();
else {
const char *costumeName = luaL_check_string(2);
- Costume *c = ResourceLoader::instance()->loadCostume(costumeName);
- act->setCostume(c);
+ act->setCostume(costumeName);
}
}
Index: resource.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/resource.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- resource.cpp 16 Aug 2003 11:10:40 -0000 1.2
+++ resource.cpp 20 Aug 2003 14:29:59 -0000 1.3
@@ -144,20 +144,14 @@
return result;
}
-Costume *ResourceLoader::loadCostume(const char *filename) {
+Costume *ResourceLoader::loadCostume(const char *filename, Costume *prevCost) {
std::string fname = filename;
makeLower(fname);
- cache_type::iterator i = cache_.find(fname);
- if (i != cache_.end()) {
- return dynamic_cast<Costume *>(i->second);
- }
-
Block *b = getFileBlock(filename);
if (b == NULL)
- error("Could not find colormap %s\n", filename);
- Costume *result = new Costume(filename, b->data(), b->len());
+ error("Could not find costume %s\n", filename);
+ Costume *result = new Costume(filename, b->data(), b->len(), prevCost);
delete b;
- cache_[fname] = result;
return result;
}
Index: resource.h
===================================================================
RCS file: /cvsroot/scummvm/residual/resource.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- resource.h 17 Aug 2003 02:48:07 -0000 1.2
+++ resource.h 20 Aug 2003 14:29:59 -0000 1.3
@@ -95,7 +95,7 @@
Bitmap *loadBitmap(const char *fname);
Colormap *loadColormap(const char *fname);
- Costume *loadCostume(const char *fname);
+ Costume *loadCostume(const char *fname, Costume *prevCost);
KeyframeAnim *loadKeyframe(const char *fname);
Material *loadMaterial(const char *fname, const Colormap &c);
Model *loadModel(const char *fname, const Colormap &c);
More information about the Scummvm-git-logs
mailing list