21 #include "CaelumPrecompiled.h" 24 #if CAELUM_SCRIPT_SUPPORT 26 #include "CaelumScriptTranslator.h" 27 #include "CaelumSystem.h" 28 #include "CaelumExceptions.h" 34 PropScriptResource::PropScriptResource
36 Ogre::ResourceManager* creator,
const Ogre::String& name, Ogre::ResourceHandle handle,
37 const Ogre::String& group,
bool isManual, Ogre::ManualResourceLoader* loader
39 Ogre::Resource (creator, name, handle, group, isManual, loader)
45 PropScriptResource::~PropScriptResource() {
50 PropScriptResourceManager::PropScriptResourceManager() {
52 mResourceType =
"PropertyScript";
55 PropScriptResource* PropScriptResourceManager::createImpl(
56 const String& name, ResourceHandle handle,
const String& group,
57 bool isManual, ManualResourceLoader* loader,
const NameValuePairList* createParams)
61 return new PropScriptResource (
this, name, handle, group, isManual, loader);
64 TypeDescriptorScriptTranslator::TypeDescriptorScriptTranslator (TypeDescriptor* typeDescriptor):
65 mTypeDescriptor(typeDescriptor)
69 bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
70 ScriptCompiler* compiler,
71 PropertyAbstractNode* prop,
74 if (prop->values.empty ()) {
75 compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
78 if (prop->values.size () > 1) {
79 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
80 prop->name +
" must have at most 1 argument");
83 if (!Ogre::ScriptTranslator::getBoolean(prop->values.front(), &value)) {
84 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
85 prop->values.front()->getValue() +
" is not a valid number");
91 bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
92 ScriptCompiler* compiler,
93 PropertyAbstractNode* prop,
96 if (prop->values.empty ()) {
97 compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
100 if (prop->values.size () > 4) {
101 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
102 prop->name +
" must have at most 4 arguments");
105 if (prop->values.size () < 3) {
106 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
107 prop->name +
" must have at least 3 arguments");
109 if (!getColour(prop->values.begin(), prop->values.end(), &value)) {
110 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
111 prop->name +
" requires a colour argument");
116 bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
117 ScriptCompiler* compiler,
118 PropertyAbstractNode* prop,
121 if (prop->values.empty ()) {
122 compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
125 if (prop->values.size () > 1) {
126 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
127 prop->name +
" must have at most 1 argument");
130 if (!Ogre::ScriptTranslator::getFloat(prop->values.front(), &value)) {
131 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
132 prop->values.front()->getValue() +
" is not a valid number");
138 bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
139 ScriptCompiler* compiler,
140 PropertyAbstractNode* prop,
143 if (prop->values.empty ()) {
144 compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
147 if (prop->values.size () > 1) {
148 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
149 prop->name +
" must have at most 1 argument");
152 if (!Ogre::ScriptTranslator::getInt(prop->values.front(), &value)) {
153 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
154 prop->values.front()->getValue() +
" is not a valid integer");
160 bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
161 ScriptCompiler* compiler,
162 PropertyAbstractNode* prop,
165 if (prop->values.empty ()) {
166 compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
169 if (prop->values.size () > 1) {
170 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
171 prop->name +
" must have at most 1 argument");
175 std::stringstream strStream (std::string(prop->values.front()->getValue()));
177 if (strStream.fail()) {
178 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
179 prop->values.front()->getValue() +
" is not a valid number");
185 bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
186 ScriptCompiler* compiler,
187 PropertyAbstractNode* prop,
190 if (prop->values.size () == 0) {
191 compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
194 if (prop->values.size () > 3) {
195 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
196 prop->name +
" must have at most 3 arguments");
200 float degMinSec[3] = { 0, 0, 0 };
202 for (AbstractNodeList::const_iterator it = prop->values.begin(), endIt = prop->values.end(); it != endIt; ++it, ++k) {
203 if (!Ogre::ScriptTranslator::getFloat(*it, °MinSec[k])) {
204 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
205 (*it)->getValue () +
" is not a valid number");
209 value = Ogre::Degree(degMinSec[0] + degMinSec[1] / 60.0 + degMinSec[2] / 3600);
213 bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
214 ScriptCompiler* compiler,
215 PropertyAbstractNode* prop,
218 if (prop->values.size () == 0) {
219 compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
222 if (prop->values.size () > 1) {
223 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
224 prop->name +
" must have at most 1 arguments");
227 if (!Ogre::ScriptTranslator::getString(prop->values.front(), &value)) {
228 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
229 prop->values.front()->getValue() +
" is not a valid string");
235 bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
236 ScriptCompiler* compiler,
237 PropertyAbstractNode* prop,
238 Ogre::Vector3& value)
240 if (prop->values.size () == 0) {
241 compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
244 if (prop->values.size () > 3) {
245 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
246 prop->name +
" must have at most 3 arguments");
250 if (!Ogre::ScriptTranslator::getFloats(prop->values.begin(), prop->values.end(), floats, 3)) {
251 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
252 "incorrect vector parameters.");
261 bool TypeDescriptorScriptTranslator::getPropValueOrAddError (
262 ScriptCompiler* compiler,
263 PropertyAbstractNode* prop,
264 Ogre::Vector2& value)
266 if (prop->values.size () == 0) {
267 compiler->addError (ScriptCompiler::CE_STRINGEXPECTED, prop->file, prop->line);
270 if (prop->values.size () > 2) {
271 compiler->addError (ScriptCompiler::CE_FEWERPARAMETERSEXPECTED, prop->file, prop->line,
272 prop->name +
" must have at most 3 arguments");
276 if (!Ogre::ScriptTranslator::getFloats(prop->values.begin(), prop->values.end(), floats, 2)) {
277 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, prop->file, prop->line,
278 "incorrect vector parameters.");
287 static bool tryHandlePropertyType (
288 ScriptCompiler* compiler, PropertyAbstractNode* propNode,
289 void* targetObject,
const ValuePropertyDescriptor* propDesc)
291 if (propDesc->getValueTypeId () ==
typeid(T)) {
293 if (TypeDescriptorScriptTranslator::getPropValueOrAddError (compiler, propNode, val)) {
294 propDesc->setValue (targetObject, Ogre::Any(val));
301 void TypeDescriptorScriptTranslator::translateProperty (
302 ScriptCompiler* compiler,
303 PropertyAbstractNode* prop,
305 const TypeDescriptor* typeDescriptor)
307 const ValuePropertyDescriptor* propDesc = typeDescriptor->getPropertyDescriptor (prop->name);
309 compiler->addError (ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
310 "property \"" + prop->name +
"\" not recognized; missing from type descriptor.");
313 if (!propDesc->canSetValue ()) {
314 compiler->addError (ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
315 "property \"" + prop->name +
"\" is read-only and can't be set from a script.");
323 || tryHandlePropertyType<int> (compiler, prop, targetObject, propDesc)
324 || tryHandlePropertyType<float> (compiler, prop, targetObject, propDesc)
325 || tryHandlePropertyType<double> (compiler, prop, targetObject, propDesc)
326 || tryHandlePropertyType<bool> (compiler, prop, targetObject, propDesc)
327 || tryHandlePropertyType<Ogre::Degree> (compiler, prop, targetObject, propDesc)
328 || tryHandlePropertyType<Ogre::String> (compiler, prop, targetObject, propDesc)
329 || tryHandlePropertyType<Ogre::Vector3> (compiler, prop, targetObject, propDesc)
330 || tryHandlePropertyType<Ogre::Vector2> (compiler, prop, targetObject, propDesc)
331 || tryHandlePropertyType<Ogre::ColourValue> (compiler, prop, targetObject, propDesc);
334 compiler->addError (ScriptCompiler::CE_UNEXPECTEDTOKEN, prop->file, prop->line,
335 "property \"" + prop->name +
"\" is found in type descriptor but has " 336 "unsupported type. Mangled typeid is '" + propDesc->getValueTypeId().name() +
"'");
340 void TypeDescriptorScriptTranslator::translate (ScriptCompiler* compiler,
const AbstractNodePtr& node)
345 assert (getTypeDescriptor () &&
"Type descriptor must be set before we can translate.");
348 ObjectAbstractNode *objNode =
reinterpret_cast<ObjectAbstractNode*
>(node.get());
349 assert (!objNode->context.isEmpty ());
350 void* targetObject = any_cast<
void*> (objNode->context);
351 assert (targetObject);
353 for (AbstractNodeList::iterator i = objNode->children.begin(); i != objNode->children.end(); ++i)
355 if ((*i)->type == ANT_PROPERTY)
357 PropertyAbstractNode *prop =
reinterpret_cast<PropertyAbstractNode*
>((*i).get());
359 translateProperty (compiler, prop, targetObject, getTypeDescriptor());
361 else if((*i)->type == ANT_OBJECT)
363 compiler->addError (ScriptCompiler::CE_INVALIDPARAMETERS, (*i)->file, (*i)->line);
370 CaelumSystemScriptTranslator::CaelumSystemScriptTranslator ():
372 mTranslationTarget(0),
373 mTranslationTargetFound(false),
378 void CaelumSystemScriptTranslator::setTranslationTarget (CaelumSystem* target,
const Ogre::String& name)
380 assert (target != 0);
381 this->mTranslationTarget = target;
382 this->mTranslationTargetName = name;
383 this->mTranslationTargetFound =
false;
386 void CaelumSystemScriptTranslator::clearTranslationTarget () {
387 this->mTranslationTarget = 0;
388 this->mTranslationTargetName.clear();
389 this->mTranslationTargetFound =
false;
392 void CaelumSystemScriptTranslator::translate (ScriptCompiler* compiler,
const AbstractNodePtr& node)
396 ObjectAbstractNode *objNode =
reinterpret_cast<ObjectAbstractNode*
>(node.get());
398 CaelumSystem* sys = 0;
401 if (this->getTranslationTarget ()) {
402 sys = this->getTranslationTarget ();
405 if (this->getTranslationTargetName () != objNode->name) {
419 mTranslationTargetFound =
true;
420 }
else if (this->getResourceManager ()) {
424 PropScriptResourceManager* mgr = this->getResourceManager ();
425 #if OGRE_VERSION >= 0x00010900 426 ResourcePtr resource = mgr->createResource (objNode->name, compiler->getResourceGroup());
428 ResourcePtr resource = mgr->create (objNode->name, compiler->getResourceGroup());
430 resource->_notifyOrigin (objNode->file);
434 objNode->context = sys;
436 for (AbstractNodeList::iterator i = objNode->children.begin(); i != objNode->children.end(); ++i)
438 if ((*i)->type == ANT_PROPERTY)
440 PropertyAbstractNode *prop =
reinterpret_cast<PropertyAbstractNode*
>((*i).get());
443 TypeDescriptorScriptTranslator::translateProperty(
445 static_cast<void*>(sys),
446 getTypeDescriptor ());
448 else if((*i)->type == ANT_OBJECT)
450 ObjectAbstractNode *childObjNode =
reinterpret_cast<ObjectAbstractNode*
>((*i).get());
459 #if OGRE_VERSION < 0x010700 460 if (childObjNode->name.empty () ==
false || childObjNode->base.empty () ==
false) {
462 if (childObjNode->name.empty () ==
false || childObjNode->bases.size () != 0) {
465 ScriptCompiler::CE_FEWERPARAMETERSEXPECTED,
466 childObjNode->file, childObjNode->line,
467 "caelum_sky_system components can't have names or bases");
470 const String& className = childObjNode->cls;
473 if (className ==
"sun") {
474 sys->setSun (
new Sun (sys->getSceneMgr (), sys->getCaelumCameraNode ()));
475 childObjNode->context =
static_cast<void*
> (sys->getSun ());
476 }
else if (className ==
"sky_dome") {
477 sys->setSkyDome (
new SkyDome (sys->getSceneMgr (), sys->getCaelumCameraNode ()));
478 childObjNode->context =
static_cast<void*
>(sys->getSkyDome ());
479 }
else if (className ==
"moon") {
480 sys->setMoon (
new Moon (sys->getSceneMgr (), sys->getCaelumCameraNode ()));
481 childObjNode->context =
static_cast<void*
>(sys->getMoon ());
482 }
else if (className ==
"ground_fog") {
483 sys->setGroundFog (
new GroundFog (sys->getSceneMgr (), sys->getCaelumCameraNode ()));
484 childObjNode->context =
static_cast<void*
>(sys->getGroundFog ());
485 }
else if (className ==
"depth_composer") {
486 sys->setDepthComposer (
new DepthComposer (sys->getSceneMgr ()));
487 childObjNode->context =
static_cast<void*
>(sys->getDepthComposer ());
488 }
else if (className ==
"point_starfield") {
489 sys->setPointStarfield (
new PointStarfield (sys->getSceneMgr (), sys->getCaelumCameraNode()));
490 childObjNode->context =
static_cast<void*
>(sys->getPointStarfield ());
491 }
else if (className ==
"precipitation") {
492 sys->setPrecipitationController (
new PrecipitationController (sys->getSceneMgr ()));
493 childObjNode->context =
static_cast<void*
>(sys->getPrecipitationController ());
494 }
else if (className ==
"cloud_system") {
495 sys->setCloudSystem (
new CloudSystem (sys->getSceneMgr (), sys->getCaelumGroundNode ()));
496 childObjNode->context =
static_cast<void*
>(sys->getCloudSystem ());
498 LogManager::getSingleton ().logMessage (
"CaelumSystemScriptTranslator::translate " 499 "unknown child object class '" + className +
"'");
507 ScriptCompiler::CE_UNSUPPORTEDBYRENDERSYSTEM,
508 childObjNode->file, childObjNode->line,
509 "Failed to create component \"" + className +
"\": " + ex.getFullDescription ());
512 processNode (compiler, *i);
519 void CloudSystemScriptTranslator::translate (ScriptCompiler* compiler,
const AbstractNodePtr& node)
523 ObjectAbstractNode *objNode =
reinterpret_cast<ObjectAbstractNode*
>(node.get());
524 assert (!objNode->context.isEmpty ());
525 void* rawTargetObject = any_cast<
void*> (objNode->context);
526 assert (rawTargetObject);
528 CloudSystem* target =
static_cast<CloudSystem*
>(rawTargetObject);
530 for (AbstractNodeList::iterator i = objNode->children.begin(); i != objNode->children.end(); ++i)
532 if ((*i)->type == ANT_PROPERTY)
535 ScriptCompiler::CE_INVALIDPARAMETERS,
536 objNode->file, objNode->line,
537 "cloud_system doesn't have any properties");
539 else if((*i)->type == ANT_OBJECT)
541 ObjectAbstractNode *childObjNode =
reinterpret_cast<ObjectAbstractNode*
>((*i).get());
551 const Ogre::String& className = childObjNode->cls;
553 if (className ==
"cloud_layer") {
555 #if OGRE_VERSION < 0x010700 556 if (childObjNode->base.empty () ==
false) {
558 if (childObjNode->bases.size () != 0) {
561 ScriptCompiler::CE_FEWERPARAMETERSEXPECTED,
562 childObjNode->file, childObjNode->line,
563 "cloud_layer can't have a base");
567 target->createLayerAtHeight (0);
568 FlatCloudLayer* layer = target->getLayer (target->getLayerCount () - 1);
572 childObjNode->context =
static_cast<void*
>(layer);
574 LogManager::getSingleton ().logMessage (
"CloudSystemScriptTranslator::translate " 575 "unknown child object class '" + className +
"'");
577 processNode (compiler, *i);
584 CaelumScriptTranslatorManager::CaelumScriptTranslatorManager
586 CaelumDefaultTypeDescriptorData* typeData
588 mCaelumSystemTranslator(),
589 mCloudSystemTranslator(),
590 mFlatCloudLayerTranslator(typeData->FlatCloudLayerTypeDescriptor),
591 mSunTranslator(typeData->BaseSkyLightTypeDescriptor),
592 mMoonTranslator(typeData->BaseSkyLightTypeDescriptor),
593 mPointStarfieldTranslator(typeData->PointStarfieldTypeDescriptor),
594 mGroundFogTranslator(typeData->GroundFogTypeDescriptor),
595 mDepthComposerTranslator(typeData->DepthComposerTypeDescriptor),
596 mPrecipitationTranslator(typeData->PrecipitationTypeDescriptor),
597 mSkyDomeTranslator(typeData->SkyDomeTypeDescriptor)
599 mCaelumSystemTranslator.setTypeDescriptor(typeData->CaelumSystemTypeDescriptor);
602 mTranslatorMap.insert (std::make_pair (
"caelum_sky_system", &mCaelumSystemTranslator));
603 mTranslatorMap.insert (std::make_pair (
"cloud_system", &mCloudSystemTranslator));
604 mTranslatorMap.insert (std::make_pair (
"cloud_layer", &mFlatCloudLayerTranslator));
605 mTranslatorMap.insert (std::make_pair (
"sun", &mSunTranslator));
606 mTranslatorMap.insert (std::make_pair (
"moon", &mMoonTranslator));
607 mTranslatorMap.insert (std::make_pair (
"point_starfield", &mPointStarfieldTranslator));
608 mTranslatorMap.insert (std::make_pair (
"ground_fog", &mGroundFogTranslator));
609 mTranslatorMap.insert (std::make_pair (
"depth_composer", &mDepthComposerTranslator));
610 mTranslatorMap.insert (std::make_pair (
"precipitation", &mPrecipitationTranslator));
611 mTranslatorMap.insert (std::make_pair (
"sky_dome", &mSkyDomeTranslator));
614 size_t CaelumScriptTranslatorManager::getNumTranslators ()
const {
616 assert(0 &&
"This method should be removed from Ogre::ScriptTranslatorManager");
617 return mTranslatorMap.size ();
620 void CaelumScriptTranslatorManager::_setPropScriptResourceManager (PropScriptResourceManager* mgr)
622 mCaelumSystemTranslator.setResourceManager (mgr);
625 ScriptTranslator* CaelumScriptTranslatorManager::getTranslator (
const AbstractNodePtr& node)
628 if (node->type == ANT_ATOM) {
631 }
else if (node->type == ANT_OBJECT) {
632 ObjectAbstractNode* objNode =
reinterpret_cast<ObjectAbstractNode*
>(node.get());
636 ScriptTranslatorMap::const_iterator it = mTranslatorMap.find(objNode->cls);
637 if (it != mTranslatorMap.end()) {
647 #endif // CAELUM_SCRIPT_SUPPORT
Exception class for unsupported features.