home *** CD-ROM | disk | FTP | other *** search
- #define __MILETOS_DOCUMENT_CPP__
-
- //
- // Libmiletos
- //
- // Copyright (C) Lauris Kaplinski 2007
- //
-
- static const int debug = 1;
-
- #ifndef _CRT_SECURE_NO_DEPRECATE
- #define _CRT_SECURE_NO_DEPRECATE 1
- #endif
-
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <assert.h>
-
- #include <libarikkei/dict.h>
-
- #include "collada/collada.h"
- #include "scene.h"
-
- #ifdef WIN32
- #define strdup _strdup
- #endif
-
- namespace Miletos {
-
- struct IdentityChangeListener {
- char *id;
- IdentityChangeListener *prev;
- IdentityChangeListener *next;
- std::vector<Object *> objects;
- };
-
- struct Document::Dict {
- public:
- Arikkei::Dict<const char *, Object *> objectdict;
- // Identity tracking
- IdentityChangeListener *listeners;
- Arikkei::Dict<const char *, IdentityChangeListener *> listenerdict;
-
- // Constructor
- Dict(unsigned int hashsize) : objectdict(hashsize), listeners(NULL), listenerdict(109) {}
- // Access
- Object *lookup (const char *id) { return objectdict.lookup (id); }
- void insert (const char *id, Object *object) { objectdict.insert (id, object); }
- void remove (const char *id) { objectdict.remove (id); }
- // Identity change signals
- void invokeIdentityAdded (Document *pdocument, const char *pidentity, Object *pobject);
- void invokeIdentityRemoved (Document *pdocument, const char *pidentity);
- // Management
- void addIdentityChangeListener (const char *pidentity, Object *pobject);
- void removeIdentityChangeListener (const char *pidentity, Object *pobject);
- void removeIdentityChangeListeners (Object *pobject);
- unsigned int isIdentityTracked (const char *id);
- };
-
- void
- Document::Dict::addIdentityChangeListener (const char *pidentity, Object *pobject)
- {
- IdentityChangeListener *listener = listenerdict.lookup (pidentity);
- if (!listener) {
- listener = new IdentityChangeListener ();
- listener->id = strdup (pidentity);
- listener->prev = NULL;
- if (listeners) listeners->prev = listener;
- listener->next = listeners;
- listeners = listener;
- listenerdict.insert (listener->id, listener);
- }
- listener->objects.push_back (pobject);
- }
-
- void
- Document::Dict::removeIdentityChangeListener (const char *pidentity, Object *pobject)
- {
- IdentityChangeListener *listener = listenerdict.lookup (pidentity);
- if (!listener) return;
- size_t i = 0;
- while (i < listener->objects.size ()) {
- if (listener->objects[i] == pobject) {
- listener->objects.erase (listener->objects.begin () + i);
- } else {
- i += 1;
- }
- }
- if (!listener->objects.empty ()) return;
- listenerdict.remove (listener->id);
- if (listener->prev) {
- listener->prev->next = listener->next;
- } else {
- listeners = listener->next;
- }
- if (listener->next) {
- listener->next->prev = listener->prev;
- }
- free (listener->id);
- delete listener;
- }
-
- void
- Document::Dict::removeIdentityChangeListeners (Object *pobject)
- {
- IdentityChangeListener *listener = listeners;
- while (listener) {
- size_t i = 0;
- while (i < listener->objects.size ()) {
- if (listener->objects[i] == pobject) {
- listener->objects.erase (listener->objects.begin () + i);
- } else {
- i += 1;
- }
- }
- if (listener->objects.empty ()) {
- IdentityChangeListener *next = listener->next;
- if (listener->prev) {
- listener->prev->next = listener->next;
- } else {
- listeners = listener->next;
- }
- if (listener->next) {
- listener->next->prev = listener->prev;
- }
- listenerdict.remove (listener->id);
- free (listener->id);
- delete listener;
- listener = next;
- } else {
- listener = listener->next;
- }
- }
- }
-
- void
- Document::Dict::invokeIdentityAdded (Document *pdocument, const char *pidentity, Object *pobject)
- {
- IdentityChangeListener *listener = listenerdict.lookup (pidentity);
- if (listener) {
- for (size_t i = 0; i < listener->objects.size (); i++) {
- listener->objects[i]->invokeIdentityAdded (pdocument, pidentity, pobject);
- }
- }
- }
-
- void
- Document::Dict::invokeIdentityRemoved (Document *pdocument, const char *pidentity)
- {
- IdentityChangeListener *listener = listenerdict.lookup (pidentity);
- if (listener) {
- for (size_t i = 0; i < listener->objects.size (); i++) {
- listener->objects[i]->invokeIdentityRemoved (pdocument, pidentity);
- }
- }
- }
-
- unsigned int
- Document::Dict::isIdentityTracked (const char *id)
- {
- return listenerdict.lookup (id) != NULL;
- }
-
- Document::Document (Scene *scene, const char *purl)
- : _numid(0), _dict(new Dict(109)), _updatereq(true), _modifiedreq(false), sizetimers(0), sizelights(0), url(NULL), root(scene),
- numtimers(0), timers(NULL), numlights(0), lights(NULL)
- {
- if (purl) url = strdup (purl);
- #ifdef WITH_JAVA
- javaenv = NULL;
- javaobject = NULL;
- #endif
- }
-
- Document::~Document (void)
- {
- #ifdef WITH_JAVA
- if (javaenv) {
- if (javaobject) {
- releaseJavaDocument (javaenv);
- javaobject = NULL;
- }
- javaenv = NULL;
- }
- #endif
- sig_destroy.invoke (this);
- root->invokeRelease ();
- if (lights) free (lights);
- delete _dict;
- if (url) free (url);
- }
-
- Document *
- Document::newDocument (Thera::Node *node, const char *url)
- {
- if (!node) return NULL;
-
- if (strcmp (node->name, "scene")) return NULL;
- const char *defaultns = node->getAttribute ("xmlns");
- if (!defaultns || strcmp (defaultns, getDefaultNamespace ())) return NULL;
-
- Scene *root = new Scene();
- Document *doc = new Document(root, url);
-
- Object::BuildCtx ctx;
- ctx.defaultns = getDefaultNamespace ();
- root->invokeBuild (node, doc, &ctx);
-
- return doc;
- }
-
- void
- Document::requestUpdate (void)
- {
- _updatereq = true;
- }
-
- void
- Document::invokeUpdate (void)
- {
- if (_updatereq) {
- _updatereq = false;
- Object::UpdateCtx ctx;
- if (root->needUpdate ()) {
- root->invokeUpdate (&ctx, 0);
- _modifiedreq = true;
- }
- }
- if (_modifiedreq) {
- _modifiedreq = false;
- if (root->needModified ()) root->invokeModified (0);
- sig_modified.invoke (this);
- }
- }
-
- void
- Document::requestModified (void)
- {
- _modifiedreq = true;
- }
-
- void
- Document::show (Sehle::Graph *graph)
- {
- root->show (graph);
- }
-
- void
- Document::hide (void)
- {
- root->hide ();
- }
-
- void
- Document::defineObject (Object *object)
- {
- _dict->insert (object->id, object);
- }
-
- Object *
- Document::lookupObject (const char *id)
- {
- return _dict->lookup (id);
- }
-
- void
- Document::undefObject (const Object *object)
- {
- _dict->remove (object->id);
- }
-
- const char *
- Document::getUniqueId (Object *object)
- {
- const char *name = object->node->getName ();
- if (!name) name = "NULL";
- #if 1
- static int l = 0;
- static char *c = NULL;
- int nlen = (int) strlen (name);
- if ((nlen + 16) > l) {
- l = l << 1;
- if (l < 64) l = 64;
- c = (char *) realloc (c, l);
- }
- #else
- static char c[1024];
- #endif
- do {
- sprintf (c, "%s_%d", name, ++_numid);
- } while (_dict->lookup (c));
- return c;
- }
-
- void
- Document::addIdentityChangeListener (const char *pidentity, Object *pobject)
- {
- _dict->addIdentityChangeListener (pidentity, pobject);
- }
-
- void
- Document::removeIdentityChangeListener (const char *pidentity, Object *pobject)
- {
- _dict->removeIdentityChangeListener (pidentity, pobject);
- }
-
- void
- Document::removeIdentityChangeListeners (Object *pobject)
- {
- _dict->removeIdentityChangeListeners (pobject);
- }
-
- void
- Document::identityAdded (const char *pidentity, Object *pobject)
- {
- _dict->invokeIdentityAdded (this, pidentity, pobject);
- }
-
- void
- Document::identityRemoved (const char *pidentity)
- {
- _dict->invokeIdentityRemoved (this, pidentity);
- }
-
- unsigned int
- Document::isIdentityTracked (const char *id)
- {
- return _dict->isIdentityTracked (id);
- }
-
- Thera::Document *
- Document::getTheraDocument (void)
- {
- if (!root) return NULL;
- return root->node->document;
- }
-
- Thera::Node *
- Document::getTheraRootNode (void)
- {
- if (!root) return NULL;
- return root->node;
- }
-
- void
- Document::setURL (const char *purl)
- {
- if (!url && !purl) return;
- if (url && purl && !strcmp (url, purl)) return;
- char *old = url;
- url = (purl) ? strdup (purl) : NULL;
- sig_url_changed.invoke (this, old, url);
- if (old) free (old);
- }
-
- void
- Document::addLight (Light *plight)
- {
- if (numlights >= sizelights) {
- if (!sizelights) {
- sizelights = 32;
- } else {
- sizelights = sizelights << 1;
- }
- lights = (Light **) realloc (lights, sizelights * sizeof (Light *));
- }
- lights[numlights] = plight;
- numlights += 1;
- }
-
- void
- Document::removeLight (Light *plight)
- {
- for (int i = 0; i < numlights; i++) {
- if (lights[i] == plight) {
- numlights -= 1;
- if (numlights) lights[i] = lights[numlights];
- break;
- }
- }
- }
-
- void
- Document::addTimer (Object *ptimer)
- {
- if (numtimers >= sizetimers) {
- if (!sizetimers) {
- sizetimers = 32;
- } else {
- sizetimers = sizetimers << 1;
- }
- timers = (Object **) realloc (timers, sizetimers * sizeof (Object *));
- }
- timers[numtimers] = ptimer;
- numtimers += 1;
- }
-
- void
- Document::removeTimer (Object *ptimer)
- {
- for (int i = 0; i < numtimers; i++) {
- if (timers[i] == ptimer) {
- numtimers -= 1;
- if (numtimers) timers[i] = timers[numtimers];
- break;
- }
- }
- }
-
- void
- Document::ensureUpdated (int maxretries)
- {
- while ((maxretries > 0) && (_updatereq || _modifiedreq)) {
- invokeUpdate ();
- maxretries -= 1;
- }
- }
-
- void
- Document::timeStep (double time)
- {
- for (int i = 0; i < numtimers; i++) {
- timers[i]->invokeTimeStep (time);
- }
- }
-
- const char *
- Document::getDefaultNamespace (void)
- {
- return "urn:Miletos";
- }
-
- } // Namespace Miletos
-
- #include "animationdata.h"
- #include "animationgraph.h"
- #include "blockworld.h"
- #include "bone.h"
- #include "camera.h"
- #include "figure.h"
- #include "ikchain.h"
- #include "light.h"
- #include "material.h"
- #include "mesh3ds.h"
- #include "meshbsp.h"
- #include "meshcollada.h"
- #include "meshmd5.h"
- #include "meshobj.h"
- #include "meshobjm.h"
- #include "meshxx.h"
- #include "particleemitter.h"
- #include "poseableitem.h"
- #include "primitives.h"
- #include "skeleton.h"
- #include "sphere.h"
- #include "staticmesh.h"
- #include "walkcycle.h"
- #include "bvh.h"
- // Poser
- #include "poser/pose.h"
- #include "poser/poseablefigure.h"
- #include "poser/prop.h"
-
- static Arikkei::Dict<const char *, const Miletos::Object::Type *> *types = NULL;
-
- static void
- add_type (const Miletos::Object::Type *type)
- {
- if (!type->tag) {
- fprintf (stderr, "add_type: Type %s has no tag\n", type->name);
- return;
- }
- types->insert (type->tag, type);
- }
-
- Miletos::Object *
- Miletos::Document::newObject (Thera::Node::Type type, const char *defaultns, const char *name)
- {
- if (name) {
- if (!strcmp (defaultns, Document::getDefaultNamespace ())) {
- if (!types) {
- types = new Arikkei::Dict<const char *, const Object::Type *>(101);
- add_type (AreaLight::type ());
- add_type (BlockWorld::type ());
- add_type (Bone::type ());
- add_type (BoneAnimationBVH::type ());
- add_type (BoneAnimationOBJM::type ());
- add_type (BoneAnimationXA::type ());
- add_type (Box::type ());
- add_type (Camera::type ());
- add_type (DayLight::type ());
- add_type (Defs::type ());
- add_type (DirectionalLight::type ());
- add_type (Figure::type ());
- add_type (Geometry3DS::type ());
- add_type (GeometryMD5::type ());
- add_type (GeometryOBJ::type ());
- add_type (GeometryOBJM::type ());
- add_type (GeometryXX::type ());
- add_type (Group::type ());
- add_type (IKChain::type ());
- add_type (KeyFrameAnimationOBJM::type ());
- add_type (MaterialDNS::type ());
- add_type (MaterialNoise::type ());
- add_type (MeshBSP::type ());
- add_type (Morph::type ());
- add_type (MorphTargetOBJM::type ());
- add_type (MorphTargetXA::type ());
- add_type (ParticleEmitter::type ());
- add_type (PointLight::type ());
- add_type (PoseableItem::type ());
- add_type (Scene::type ());
- add_type (Skeleton::type ());
- add_type (SkinnedGeometryCollada::type ());
- add_type (StaticGeometryCollada::type ());
- add_type (Sphere::type ());
- add_type (SMesh::type ());
- add_type (SpotLight::type ());
-
- add_type (Animation::Biped::type ());
- add_type (Animation::BoneKeys::type ());
- add_type (Animation::Controller::type ());
- add_type (Animation::Graph::type ());
- add_type (Animation::Pose::type ());
- add_type (Animation::Sequence::type ());
- add_type (Animation::SkinAnimation::type ());
- add_type (Animation::Transition::type ());
- add_type (Animation::WalkCycle::type ());
- add_type (Poser::Geometry::type ());
- add_type (Poser::Pose::type ());
- add_type (Poser::Prop::type ());
- }
- const Object::Type *type = types->lookup (name);
- if (type) {
- return type->factory ();
- }
- #if 0
- } else if (!strcmp (name, "geometryOBJ")) {
- return new GeometryOBJ();
- } else if (!strcmp (name, "meshOBJ")) {
- return new MeshOBJ();
- #endif
- } else if (!strcmp (defaultns, Collada::getDefaultNamespace ())) {
- // Collada
- Object *object = Collada::newObject (type, defaultns, name);
- if (object) return object;
- }
- } else if (type == Thera::Node::TEXT) {
- return new Text();
- }
- if (debug) fprintf (stderr, "Factory::newObject: Unknown object: type %d name %s\n", type, name);
- return new Unknown();
- }
-
-