EMI: Add attaching functionality to actors

This commit is contained in:
Dries Harnie 2012-03-11 15:24:52 +01:00
parent 155b7027ce
commit 34a0a1a82c
5 changed files with 66 additions and 21 deletions

View File

@ -45,6 +45,10 @@
#include "engines/grim/gfx_base.h"
#include "engines/grim/model.h"
#include "engines/grim/emi/costumeemi.h"
#include "engines/grim/emi/skeleton.h"
#include "engines/grim/emi/costume/emiskel_component.h"
#include "common/foreach.h"
namespace Grim {
@ -73,7 +77,7 @@ Actor::Actor(const Common::String &actorName) :
_visible(true), _lipSync(NULL), _turning(false), _walking(false),
_walkedLast(false), _walkedCur(false),
_lastTurnDir(0), _currTurnDir(0),
_sayLineText(0) {
_sayLineText(0), _attachedActor(NULL), _attachedJoint("") {
_lookingMode = false;
_constrain = false;
_talkSoundName = "";
@ -107,6 +111,9 @@ Actor::Actor() :
_collisionMode = CollisionOff;
_collisionScale = 1.f;
_attachedActor = NULL;
_attachedJoint = "";
for (int i = 0; i < MAX_SHADOWS; i++) {
_shadowArray[i].active = false;
_shadowArray[i].dontNegate = false;
@ -1636,6 +1643,33 @@ void Actor::collisionHandlerCallback(Actor *other) const {
LuaBase::instance()->callback("collisionHandler", objects);
}
void Actor::attachToActor(Actor *other, const char *joint) {
assert(other != NULL);
if (other == _attachedActor)
return;
if (_attachedActor != NULL)
detach();
EMICostume * cost = dynamic_cast<EMICostume *>(other->getCurrentCostume());
assert(cost != NULL);
Common::String jointStr = joint ? joint : "";
// If 'other' has a skeleton, check if it has the joint.
// Some models (pile o' boulders) don't have a skeleton,
// so we don't make the check in that case.
if (cost->_emiSkel && cost->_emiSkel->_obj)
assert(cost->_emiSkel->_obj->hasJoint(jointStr));
_attachedActor = other;
_attachedJoint = jointStr;
}
void Actor::detach() {
if (_attachedActor != NULL) {
_attachedJoint = "";
_attachedActor = NULL;
}
}
unsigned const int Actor::Chore::fadeTime = 150;

View File

@ -37,6 +37,7 @@ class Costume;
class LipSync;
class Font;
class Set;
class Joint;
struct Plane {
Common::String setName;
@ -455,6 +456,8 @@ public:
static void saveStaticState(SaveGame *state);
static void restoreStaticState(SaveGame *state);
void attachToActor(Actor *other, const char *joint);
void detach();
private:
void costumeMarkerCallback(int marker);
@ -581,6 +584,8 @@ private:
bool _puckOrient;
static bool _isTalkingBackground;
Actor *_attachedActor;
Common::String _attachedJoint;
friend class GrimEngine;
};

View File

@ -712,7 +712,7 @@ void Lua_V2::AttachActor() {
// Missing lua parts
lua_Object attachedObj = lua_getparam(1);
lua_Object actorObj = lua_getparam(2);
lua_Object targetObj = lua_getparam(3);
lua_Object jointObj = lua_getparam(3);
if (!lua_isuserdata(actorObj) || lua_tag(actorObj) != MKTAG('A','C','T','R'))
return;
@ -728,22 +728,13 @@ void Lua_V2::AttachActor() {
if (!attached)
return;
const char * target = NULL;
if (!lua_isnil(targetObj)) {
target = lua_getstring(targetObj);
const char * joint = NULL;
if (!lua_isnil(jointObj)) {
joint = lua_getstring(jointObj);
}
bool hasJoint = true;
if (target != NULL) {
EMICostume * cost = dynamic_cast<EMICostume *>(actor->getCurrentCostume());
EMISkelComponent * skelc = cost->_emiSkel;
if (!skelc) goto blah;
Skeleton * skel = skelc->_obj;
if (!skel) goto blah;
hasJoint = skel->hasJoint(target);
}
blah:
warning("Lua_V2::AttachActor: attaching %s to %s (on %s) joint %s", attached->getName().c_str(), actor->getName().c_str(), target ? target : "(none)", hasJoint ? "FOUND" : "NOT FOUND");
attached->attachToActor(actor, joint);
warning("Lua_V2::AttachActor: attaching %s to %s (on %s)", attached->getName().c_str(), actor->getName().c_str(), joint ? joint : "(none)");
}
void Lua_V2::DetachActor() {
@ -758,6 +749,7 @@ void Lua_V2::DetachActor() {
return;
warning("Lua_V2::DetachActor: detaching %s from parent actor", attached->getName().c_str());
attached->detach();
}
} // end of namespace Grim

View File

@ -114,10 +114,10 @@ void Skeleton::setAnim(AnimationEmi *anim) {
resetAnim();
}
int Skeleton::findJointIndex(Common::String name, int max) {
int Skeleton::findJointIndex(const Common::String & name, int max) const {
if (_numJoints > 0) {
for (int i = 0; i < max; i++) {
if (_joints[i]._name == name) {
for(int i = 0; i < max; i++) {
if(!_joints[i]._name.compareToIgnoreCase(name)) {
return i;
}
}
@ -213,4 +213,16 @@ void Skeleton::animate(float delta) {
} // end for
}
bool Skeleton::hasJoint(const Common::String & name) const {
return name.empty() || findJointIndex(name, _numJoints) >= 0;
}
Joint * Skeleton::getJointNamed(const Common::String & name) const {
if (name.empty()) {
return & _joints[0];
} else {
return & _joints[findJointIndex(name, _numJoints)];
}
}
} // end of namespace Grim

View File

@ -26,6 +26,7 @@
#include "math/mathfwd.h"
#include "math/quat.h"
#include "engines/grim/object.h"
#include "engines/grim/actor.h"
namespace Common {
class SeekableReadStream;
@ -63,8 +64,9 @@ public:
void resetAnim();
void setAnim(AnimationEmi *anim);
void animate(float time);
int findJointIndex(Common::String name, int max);
bool hasJoint(const Common::String & name) { return findJointIndex(name, _numJoints) >= 0; }
int findJointIndex(const Common::String & name, int max) const;
bool hasJoint(const Common::String & name) const;
Joint * getJointNamed(const Common::String & name) const;
float _time;
};