[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