/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see .
*/
#include "CaelumPrecompiled.h"
#include "CaelumPrerequisites.h"
#if CAELUM_SCRIPT_SUPPORT
#include "CaelumScriptTranslator.h"
#include "CaelumSystem.h"
#include "CaelumExceptions.h"
using namespace Ogre;
namespace Caelum
{
PropScriptResource::PropScriptResource
(
Ogre::ResourceManager* creator, const Ogre::String& name, Ogre::ResourceHandle handle,
const Ogre::String& group, bool isManual, Ogre::ManualResourceLoader* loader
):
Ogre::Resource (creator, name, handle, group, isManual, loader)
{
//Ogre::LogManager::getSingleton().logMessage(
// "PropScriptResource::PropScriptResource");
}
PropScriptResource::~PropScriptResource() {
//Ogre::LogManager::getSingleton().logMessage(
// "PropScriptResource::~PropScriptResource");
}
PropScriptResourceManager::PropScriptResourceManager() {
mLoadOrder = 1000;
mResourceType = "PropertyScript";
}
PropScriptResource* PropScriptResourceManager::createImpl(
const String& name, ResourceHandle handle, const String& group,
bool isManual, ManualResourceLoader* loader, const NameValuePairList* createParams)
{
//Ogre::LogManager::getSingleton().logMessage(
// "PropScriptResourceManager::createImpl");
return new PropScriptResource (this, name, handle, group, isManual, loader);
}
TypeDescriptorScriptTranslator::TypeDescriptorScriptTranslator (TypeDescriptor* typeDescriptor):
mTypeDescriptor(typeDescriptor)
{
}
bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
bool& value)
{
if (prop->values.empty ()) {
compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
return false;
}
if (prop->values.size () > 1) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at most 1 argument");
return false;
}
if (!Ogre::ScriptTranslator::getBoolean(prop->values.front(), &value)) {
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
prop->values.front()->getValue() + " is not a valid number");
return false;
}
return true;
}
bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
ColourValue& value)
{
if (prop->values.empty ()) {
compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
return false;
}
if (prop->values.size () > 4) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at most 4 arguments");
return false;
}
if (prop->values.size () < 3) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at least 3 arguments");
}
if (!getColour(prop->values.begin(), prop->values.end(), &value)) {
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
prop->name + " requires a colour argument");
}
return true;
}
bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
float& value)
{
if (prop->values.empty ()) {
compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
return false;
}
if (prop->values.size () > 1) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at most 1 argument");
return false;
}
if (!Ogre::ScriptTranslator::getFloat(prop->values.front(), &value)) {
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
prop->values.front()->getValue() + " is not a valid number");
return false;
}
return true;
}
bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
int& value)
{
if (prop->values.empty ()) {
compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
return false;
}
if (prop->values.size () > 1) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at most 1 argument");
return false;
}
if (!Ogre::ScriptTranslator::getInt(prop->values.front(), &value)) {
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
prop->values.front()->getValue() + " is not a valid integer");
return false;
}
return true;
}
bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
double& value)
{
if (prop->values.empty ()) {
compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
return false;
}
if (prop->values.size () > 1) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at most 1 argument");
return false;
}
// We do need a string stream here for the extra precision.
std::stringstream strStream (std::string(prop->values.front()->getValue()));
strStream >> value;
if (strStream.fail()) {
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
prop->values.front()->getValue() + " is not a valid number");
return false;
}
return true;
}
bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
Ogre::Degree& value)
{
if (prop->values.size () == 0) {
compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
return false;
}
if (prop->values.size () > 3) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at most 3 arguments");
return false;
}
// Allow 3 components.
float degMinSec[3] = { 0, 0, 0 };
int k = 0;
for (AbstractNodeList::const_iterator it = prop->values.begin(), endIt = prop->values.end(); it != endIt; ++it, ++k) {
if (!Ogre::ScriptTranslator::getFloat(*it, °MinSec[k])) {
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
(*it)->getValue () + " is not a valid number");
return false;
}
}
value = Ogre::Degree(degMinSec[0] + degMinSec[1] / 60.0 + degMinSec[2] / 3600);
return true;
}
bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
Ogre::String& value)
{
if (prop->values.size () == 0) {
compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
return false;
}
if (prop->values.size () > 1) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at most 1 arguments");
return false;
}
if (!Ogre::ScriptTranslator::getString(prop->values.front(), &value)) {
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
prop->values.front()->getValue() + " is not a valid string");
return false;
}
return true;
}
bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
Ogre::Vector3& value)
{
if (prop->values.size () == 0) {
compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
return false;
}
if (prop->values.size () > 3) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at most 3 arguments");
return false;
}
float floats[3];
if (!Ogre::ScriptTranslator::getFloats(prop->values.begin(), prop->values.end(), floats, 3)) {
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
"incorrect vector parameters.");
return false;
}
value.x = floats[0];
value.y = floats[1];
value.z = floats[2];
return true;
}
bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
Ogre::Vector2& value)
{
if (prop->values.size () == 0) {
compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
return false;
}
if (prop->values.size () > 2) {
compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
prop->name + " must have at most 3 arguments");
return false;
}
float floats[2];
if (!Ogre::ScriptTranslator::getFloats(prop->values.begin(), prop->values.end(), floats, 2)) {
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
"incorrect vector parameters.");
return false;
}
value.x = floats[0];
value.y = floats[1];
return true;
}
template
static bool tryHandlePropertyType (
ScriptCompiler* compiler, PropertyAbstractNode* propNode,
void* targetObject, const ValuePropertyDescriptor* propDesc)
{
if (propDesc->getValueTypeId () == typeid(T)) {
T val;
if (TypeDescriptorScriptTranslator::getPropValueOrAddError (compiler, propNode, val)) {
propDesc->setValue (targetObject, Ogre::Any(val));
}
return true;
}
return false;
}
void TypeDescriptorScriptTranslator::translateProperty (
ScriptCompiler* compiler,
PropertyAbstractNode* prop,
void* targetObject,
const TypeDescriptor* typeDescriptor)
{
const ValuePropertyDescriptor* propDesc = typeDescriptor->getPropertyDescriptor (prop->name);
if (!propDesc) {
compiler->addError (ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
"property \"" + prop->name + "\" not recognized; missing from type descriptor.");
return;
}
if (!propDesc->canSetValue ()) {
compiler->addError (ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
"property \"" + prop->name + "\" is read-only and can't be set from a script.");
return;
}
//LogManager::getSingleton ().logMessage ("TypeDescriptorScriptTranslator::translateProperty"
// " name '" + prop->name + "'");
bool handled = false
|| tryHandlePropertyType (compiler, prop, targetObject, propDesc)
|| tryHandlePropertyType (compiler, prop, targetObject, propDesc)
|| tryHandlePropertyType (compiler, prop, targetObject, propDesc)
|| tryHandlePropertyType (compiler, prop, targetObject, propDesc)
|| tryHandlePropertyType (compiler, prop, targetObject, propDesc)
|| tryHandlePropertyType (compiler, prop, targetObject, propDesc)
|| tryHandlePropertyType (compiler, prop, targetObject, propDesc)
|| tryHandlePropertyType (compiler, prop, targetObject, propDesc)
|| tryHandlePropertyType (compiler, prop, targetObject, propDesc);
if (!handled) {
compiler->addError (ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
"property \"" + prop->name + "\" is found in type descriptor but has "
"unsupported type. Mangled typeid is '" + propDesc->getValueTypeId().name() + "'");
}
}
void TypeDescriptorScriptTranslator::translate (ScriptCompiler* compiler, const AbstractNodePtr& node)
{
//LogManager::getSingleton ().logMessage ("TypeDescriptorScriptTranslator::translate begin");
// Check type descriptor was set.
assert (getTypeDescriptor () && "Type descriptor must be set before we can translate.");
// Fetch target object.
ObjectAbstractNode *objNode = reinterpret_cast(node.get());
assert (!objNode->context.isEmpty ());
void* targetObject = any_cast (objNode->context);
assert (targetObject);
for (AbstractNodeList::iterator i = objNode->children.begin(); i != objNode->children.end(); ++i)
{
if ((*i)->type == ANT_PROPERTY)
{
PropertyAbstractNode *prop = reinterpret_cast((*i).get());
translateProperty (compiler, prop, targetObject, getTypeDescriptor());
}
else if((*i)->type == ANT_OBJECT)
{
compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, (*i)->file, (*i)->line);
}
}
//LogManager::getSingleton ().logMessage ("TypeDescriptorScriptTranslator::translate end");
}
CaelumSystemScriptTranslator::CaelumSystemScriptTranslator ():
mResourceManager(),
mTranslationTarget(0),
mTranslationTargetFound(false),
mTypeDescriptor(0)
{
}
void CaelumSystemScriptTranslator::setTranslationTarget (CaelumSystem* target, const Ogre::String& name)
{
assert (target != 0);
this->mTranslationTarget = target;
this->mTranslationTargetName = name;
this->mTranslationTargetFound = false;
}
void CaelumSystemScriptTranslator::clearTranslationTarget () {
this->mTranslationTarget = 0;
this->mTranslationTargetName.clear();
this->mTranslationTargetFound = false;
}
void CaelumSystemScriptTranslator::translate (ScriptCompiler* compiler, const AbstractNodePtr& node)
{
//LogManager::getSingleton ().logMessage ("CaelumSystemScriptTranslator::translate begin");
ObjectAbstractNode *objNode = reinterpret_cast(node.get());
CaelumSystem* sys = 0;
// Check for a translation target.
if (this->getTranslationTarget ()) {
sys = this->getTranslationTarget ();
// Check for a name match.
if (this->getTranslationTargetName () != objNode->name) {
//LogManager::getSingleton ().logMessage (
// "Caelum: Skipped " + objNode->cls + " name " + objNode->name + " while loading");
return;
}
// Clear the target; this ensure that properties which are not
// mentioned are set to their default values.
// We only do this after we found a target; this ensure that if
// the target is not found it's not modified either.
sys->clear();
//LogManager::getSingleton ().logMessage (
// "Caelum: Found " + objNode->cls + " name " + objNode->name + "; filling properties.");
mTranslationTargetFound = true;
} else if (this->getResourceManager ()) {
// If we don't have a target but have a resource manager then create a resource.
//LogManager::getSingleton ().logMessage (
// "Caelum: Saved " + objNode->cls + " name " + objNode->name + " as a resource");
PropScriptResourceManager* mgr = this->getResourceManager ();
#if OGRE_VERSION >= 0x00010900
ResourcePtr resource = mgr->createResource (objNode->name, compiler->getResourceGroup());
#else
ResourcePtr resource = mgr->create (objNode->name, compiler->getResourceGroup());
#endif
resource->_notifyOrigin (objNode->file);
return;
}
objNode->context = sys;
for (AbstractNodeList::iterator i = objNode->children.begin(); i != objNode->children.end(); ++i)
{
if ((*i)->type == ANT_PROPERTY)
{
PropertyAbstractNode *prop = reinterpret_cast((*i).get());
// Properties implemented through type descriptor.
TypeDescriptorScriptTranslator::translateProperty(
compiler, prop,
static_cast(sys),
getTypeDescriptor ());
}
else if((*i)->type == ANT_OBJECT)
{
ObjectAbstractNode *childObjNode = reinterpret_cast((*i).get());
//LogManager::getSingleton ().logMessage ("CaelumSystemScriptTranslator::translate child object"
// " value '" + childObjNode->getValue () + "'"
// " name '" + childObjNode->name + "'"
// " cls '" + childObjNode->cls + "'"
// " base '" + childObjNode->base + "'");
// Only allow declarations with one class token; like "moon { }"
#if OGRE_VERSION < 0x010700
if (childObjNode->name.empty () == false || childObjNode->base.empty () == false) {
#else
if (childObjNode->name.empty () == false || childObjNode->bases.size () != 0) {
#endif
compiler->addError (
ScriptCompiler::CE_FEWERPARAMETERSEXPECTED,
childObjNode->file, childObjNode->line,
"caelum_sky_system components can't have names or bases");
continue;
}
const String& className = childObjNode->cls;
try {
if (className == "sun") {
sys->setSun (new Sun (sys->getSceneMgr (), sys->getCaelumCameraNode ()));
childObjNode->context = static_cast (sys->getSun ());
} else if (className == "sky_dome") {
sys->setSkyDome (new SkyDome (sys->getSceneMgr (), sys->getCaelumCameraNode ()));
childObjNode->context = static_cast(sys->getSkyDome ());
} else if (className == "moon") {
sys->setMoon (new Moon (sys->getSceneMgr (), sys->getCaelumCameraNode ()));
childObjNode->context = static_cast(sys->getMoon ());
} else if (className == "ground_fog") {
sys->setGroundFog (new GroundFog (sys->getSceneMgr (), sys->getCaelumCameraNode ()));
childObjNode->context = static_cast(sys->getGroundFog ());
} else if (className == "depth_composer") {
sys->setDepthComposer (new DepthComposer (sys->getSceneMgr ()));
childObjNode->context = static_cast(sys->getDepthComposer ());
} else if (className == "point_starfield") {
sys->setPointStarfield (new PointStarfield (sys->getSceneMgr (), sys->getCaelumCameraNode()));
childObjNode->context = static_cast(sys->getPointStarfield ());
} else if (className == "precipitation") {
sys->setPrecipitationController (new PrecipitationController (sys->getSceneMgr ()));
childObjNode->context = static_cast(sys->getPrecipitationController ());
} else if (className == "cloud_system") {
sys->setCloudSystem (new CloudSystem (sys->getSceneMgr (), sys->getCaelumGroundNode ()));
childObjNode->context = static_cast(sys->getCloudSystem ());
} else {
LogManager::getSingleton ().logMessage ("CaelumSystemScriptTranslator::translate "
"unknown child object class '" + className + "'");
}
} catch (Caelum::UnsupportedException& ex) {
// Catch all unsupported exceptions and report them.
// This should usually happen because the proper shaders are not supported by hardware.
//
// Script parsing should still succeed.
compiler->addError (
ScriptCompiler::CE_UNSUPPORTEDBYRENDERSYSTEM,
childObjNode->file, childObjNode->line,
"Failed to create component \"" + className + "\": " + ex.getFullDescription ());
continue;
}
processNode (compiler, *i);
}
}
//LogManager::getSingleton ().logMessage ("SkySystemScriptTranslator::translate END");
}
void CloudSystemScriptTranslator::translate (ScriptCompiler* compiler, const AbstractNodePtr& node)
{
//LogManager::getSingleton ().logMessage ("SkySystemScriptTranslator::translate begin");
ObjectAbstractNode *objNode = reinterpret_cast(node.get());
assert (!objNode->context.isEmpty ());
void* rawTargetObject = any_cast (objNode->context);
assert (rawTargetObject);
CloudSystem* target = static_cast(rawTargetObject);
for (AbstractNodeList::iterator i = objNode->children.begin(); i != objNode->children.end(); ++i)
{
if ((*i)->type == ANT_PROPERTY)
{
compiler->addError (
ScriptCompiler::CE_INVALIDPARAMETERS,
objNode->file, objNode->line,
"cloud_system doesn't have any properties");
}
else if((*i)->type == ANT_OBJECT)
{
ObjectAbstractNode *childObjNode = reinterpret_cast((*i).get());
/*
LogManager::getSingleton ().logMessage ("CloudSystemScriptTranslator::translate child object"
" value '" + childObjNode->getValue () + "'"
" name '" + childObjNode->name + "'"
" cls '" + childObjNode->cls + "'"
" base '" + childObjNode->base + "'");
*/
const Ogre::String& className = childObjNode->cls;
if (className == "cloud_layer") {
// Don't allow names.
#if OGRE_VERSION < 0x010700
if (childObjNode->base.empty () == false) {
#else
if (childObjNode->bases.size () != 0) {
#endif
compiler->addError (
ScriptCompiler::CE_FEWERPARAMETERSEXPECTED,
childObjNode->file, childObjNode->line,
"cloud_layer can't have a base");
continue;
}
// Height here is irrelevant. It's silly to have it as a FlatCloudLayer ctor parameter.
target->createLayerAtHeight (0);
FlatCloudLayer* layer = target->getLayer (target->getLayerCount () - 1);
// Add the new layer as a context for the object node.
// This will eventually pass to the TypeDescriptorScriptTranslator for a cloud layer.
childObjNode->context = static_cast(layer);
} else {
LogManager::getSingleton ().logMessage ("CloudSystemScriptTranslator::translate "
"unknown child object class '" + className + "'");
}
processNode (compiler, *i);
}
}
//LogManager::getSingleton ().logMessage ("CloudSystemScriptTranslator::translate END");
}
CaelumScriptTranslatorManager::CaelumScriptTranslatorManager
(
CaelumDefaultTypeDescriptorData* typeData
):
mCaelumSystemTranslator(),
mCloudSystemTranslator(),
mFlatCloudLayerTranslator(typeData->FlatCloudLayerTypeDescriptor),
mSunTranslator(typeData->BaseSkyLightTypeDescriptor),
mMoonTranslator(typeData->BaseSkyLightTypeDescriptor),
mPointStarfieldTranslator(typeData->PointStarfieldTypeDescriptor),
mGroundFogTranslator(typeData->GroundFogTypeDescriptor),
mDepthComposerTranslator(typeData->DepthComposerTypeDescriptor),
mPrecipitationTranslator(typeData->PrecipitationTypeDescriptor),
mSkyDomeTranslator(typeData->SkyDomeTypeDescriptor)
{
mCaelumSystemTranslator.setTypeDescriptor(typeData->CaelumSystemTypeDescriptor);
// Build translator map to member translators.
mTranslatorMap.insert (std::make_pair ("caelum_sky_system", &mCaelumSystemTranslator));
mTranslatorMap.insert (std::make_pair ("cloud_system", &mCloudSystemTranslator));
mTranslatorMap.insert (std::make_pair ("cloud_layer", &mFlatCloudLayerTranslator));
mTranslatorMap.insert (std::make_pair ("sun", &mSunTranslator));
mTranslatorMap.insert (std::make_pair ("moon", &mMoonTranslator));
mTranslatorMap.insert (std::make_pair ("point_starfield", &mPointStarfieldTranslator));
mTranslatorMap.insert (std::make_pair ("ground_fog", &mGroundFogTranslator));
mTranslatorMap.insert (std::make_pair ("depth_composer", &mDepthComposerTranslator));
mTranslatorMap.insert (std::make_pair ("precipitation", &mPrecipitationTranslator));
mTranslatorMap.insert (std::make_pair ("sky_dome", &mSkyDomeTranslator));
}
size_t CaelumScriptTranslatorManager::getNumTranslators () const {
// Turns out this is never called.
assert(0 && "This method should be removed from Ogre::ScriptTranslatorManager");
return mTranslatorMap.size ();
}
void CaelumScriptTranslatorManager::_setPropScriptResourceManager (PropScriptResourceManager* mgr)
{
mCaelumSystemTranslator.setResourceManager (mgr);
}
ScriptTranslator* CaelumScriptTranslatorManager::getTranslator (const AbstractNodePtr& node)
{
//LogManager::getSingleton ().logMessage ("CaelumScriptTranslatorManager::getTranslator");
if (node->type == ANT_ATOM) {
//ObjectAbstractNode* atomNode = reinterpret_cast(node.get());
//LogManager::getSingleton ().logMessage ("CaelumScriptTranslatorManager::getTranslator atom node " + atomNode->getValue ());
} else if (node->type == ANT_OBJECT) {
ObjectAbstractNode* objNode = reinterpret_cast(node.get());
//LogManager::getSingleton ().logMessage ("CaelumScriptTranslatorManager::getTranslator object node " + objNode->getValue ());
// Pass down the context.
ScriptTranslatorMap::const_iterator it = mTranslatorMap.find(objNode->cls);
if (it != mTranslatorMap.end()) {
return it->second;
}
}
// Not found in this manager.
return 0;
}
}
#endif // CAELUM_SCRIPT_SUPPORT