home *** CD-ROM | disk | FTP | other *** search
- #define __MILETOS_POSEABLEITEM_CPP__
-
- //
- // Libmiletos
- //
- // Copyright (C) Lauris Kaplinski 2009
- //
-
- #include <malloc.h>
-
- #include <sehle/renderable.h>
-
- #include "skeleton.h"
- #include "bone.h"
-
- #include "poseableitem.h"
-
- namespace Miletos {
-
- PoseableItem::PoseableItem (void)
- : Item(HAS_CHILDREN), anchor(NULL), skeletonanchoridx(-1)
- {
- }
-
- PoseableItem::~PoseableItem (void)
- {
- }
-
- static Object *
- poseableitem_factory (void)
- {
- return new PoseableItem();
- }
-
- const Object::Type *
- PoseableItem::objectType (void)
- {
- return type ();
- }
-
- const Object::Type *
- PoseableItem::type (void)
- {
- static Type *mytype = NULL;
- static const Attribute attrs[] = {
- { "anchor", NULL, 0 }
- };
- if (!mytype) mytype = new Type(Item::type (), "PoseableItem", "poseableItem", poseableitem_factory, sizeof (attrs) / sizeof (attrs[0]), attrs);
- return mytype;
- }
-
- void
- PoseableItem::build (Thera::Node *pnode, Document *doc, BuildCtx *ctx)
- {
- Item::build (pnode, doc, ctx);
-
- buildAllAttributes (type (), ctx);
-
- }
-
- void
- PoseableItem::release (void)
- {
- if (anchor) {
- free (anchor);
- anchor = NULL;
- }
-
- Item::release ();
- }
-
- Object *
- PoseableItem::childAdded (Thera::Node *cnode, Thera::Node *rnode)
- {
- Object *child = Item::childAdded (cnode, rnode);
-
- if (renderable && child->isType (Item::type ())) {
- Item *ichild = (Item *) child;
- Sehle::Renderable *rchild = ichild->invokeShow (renderable->graph, 0xffffffff);
- Sehle::RenderableGroup *rgroup = (Sehle::RenderableGroup *) renderable;
- if (rchild) rgroup->prependChild (rchild);
- }
-
- return child;
- }
-
- void
- PoseableItem::childRemoved (Thera::Node *cnode, Thera::Node *rnode)
- {
- if (renderable) {
- for (Object *child = children; child; child = child->next) {
- if (child->node == cnode) {
- if (child->isType (Item::type ())) {
- ((Item *) child)->invokeHide ((Sehle::RenderableGroup *) renderable);
- }
- break;
- }
- }
- }
-
- Item::removeChild (cnode, rnode);
- }
-
- void
- PoseableItem::set (const char *attrid, const char *val)
- {
- if (!strcmp (attrid, "anchor")) {
- if (anchor) {
- free (anchor);
- anchor = NULL;
- }
- if (val) {
- anchor = strdup (val);
- }
- requestUpdate (MODIFIED | MESH_DEFINITION_MODIFIED);
- } else {
- Item::set (attrid, val);
- }
- }
-
- void
- PoseableItem::write (const char *attrid)
- {
- if (!strcmp (attrid, "anchor")) {
- node->setAttribute (attrid, anchor);
- } else {
- Item::write (attrid);
- }
- }
-
- void
- PoseableItem::update (UpdateCtx *ctx, unsigned int flags)
- {
- // Rewrite flags
- if (flags & MODIFIED) flags |= PARENT_MODIFIED;
- flags &= MODIFIED_CASCADE;
-
- // Update children
- for (Object *child = children; child; child = child->next) {
- if (flags || child->updateFlagIsSet (MODIFIED_STATE)) {
- if (child->isType (Item::type ())) {
- Item *ichild = (Item *) child;
- UpdateCtx cctx;
- cctx.i2w = ctx->i2w * c2o * ichild->getI2P ();
- child->invokeUpdate (&cctx, flags);
- } else {
- child->invokeUpdate (ctx, flags);
- }
- }
- }
-
- bbox.setEmpty ();
- for (Object *child = children; child; child = child->next) {
- if (child->isType (Item::type ())) {
- Item *ichild = (Item *) child;
- bbox.grow (ichild->bbox);
- }
- }
-
- Item::update (ctx, flags);
- }
-
- Sehle::Renderable *
- PoseableItem::show (Sehle::Graph *graph, Sehle::u32 contextmask)
- {
- Sehle::RenderableGroup *rgroup = new Sehle::RenderableGroup(graph, contextmask);
-
- for (Object *child = children; child; child = child->next) {
- if (child->isType (Item::type ())) {
- Item *ichild = (Item *) child;
- Sehle::Renderable *rchild = ichild->invokeShow (graph, contextmask);
- if (rchild) rgroup->prependChild (rchild);
- }
- }
-
- return rgroup;
- }
-
- void
- PoseableItem::hide (Sehle::RenderableGroup *pgroup)
- {
- for (Object *child = children; child; child = child->next) {
- if (child->isType (Item::type ())) {
- Item *ichild = (Item *) child;
- ichild->invokeHide ((Sehle::RenderableGroup *) renderable);
- }
- }
- }
-
- Item *
- PoseableItem::trace (const Elea::Line3f *wray, unsigned int mask, float *distance)
- {
- Item *tchild = NULL;
- float bestd = Elea::OMEGA_F;
-
- for (Object *child = children; child; child = child->next) {
- if (child->isType (Item::type ())) {
- Item *ichild = (Item *) child;
- float d;
- Item *tch = ichild->invokeTrace (wray, mask, &d);
- if ((d > 0) && (d < bestd)) {
- bestd = d;
- tchild = tch;
- }
- }
- }
-
- if (tchild) *distance = bestd;
-
- return tchild;
- }
-
- void
- PoseableItem::getC2P (Elea::Matrix4x4f *c2p, Miletos::Item *child)
- {
- *c2p = _i2p * c2o;
- }
-
- void
- PoseableItem::setC2O (const Elea::Matrix4x4f& pc2o)
- {
- c2o = pc2o;
- requestUpdate (MODIFIED);
- }
-
- void
- PoseableItem::updateSkeletonIndices (Skeleton *skeleton)
- {
- skeletonanchoridx = skeleton->lookupBone (anchor);
- if (skeletonanchoridx >= 0) {
- setC2O (skeleton->bones[skeletonanchoridx]->getAB2O ());
- }
- }
-
- void
- PoseableItem::clearSkeletonIndices (void)
- {
- skeletonanchoridx = -1;
- }
-
- } // Namespace Miletos
-
-