📄 rubysceneimporter.cpp
字号:
/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- this file is part of rcssserver3D Fri May 9 2003 Copyright (C) 2002,2003 Koblenz University Copyright (C) 2003 RoboCup Soccer Server 3D Maintenance Group $Id: rubysceneimporter.cpp,v 1.27 2008/05/12 09:39:14 rollmark Exp $ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "rubysceneimporter.h"#include <zeitgeist/logserver/logserver.h>#include <zeitgeist/fileserver/fileserver.h>#include <zeitgeist/scriptserver/scriptserver.h>#include <oxygen/sceneserver/transform.h>#include <oxygen/sceneserver/scenedict.h>#include <boost/scoped_array.hpp>#include <sstream>using namespace zeitgeist;using namespace oxygen;using namespace boost;using namespace std;/** (RubySceneGraph <version major> <version minor>) ( (template varName1 varName2 ...) (define varName value) (node <NodeName> method param param ... method param ... (node <NodeName> method param param ... method param ... ) (node <NodeName> method param param ... method param ... ) method param param ... method param ... )*/#define S_NODE "node"#define S_SELECT "select"#define S_PWD "pwd"#define S_TEMPLATE "template"#define S_DEFINE "define"#define S_ATTACH "attach"#define S_SWITCH "switch"#define S_DELTASCENE "RubyDeltaScene"#define S_SCENEGRAPH "RubySceneGraph"#define S_SETLOCALTRANSFORM "setLocalTransform"#define S_SETSCALE "setScale"#define S_SETMATERIAL "setMaterial"#define S_BASENODE "BaseNode"#define S_SINGLEMATNODE "SingleMatNode"#define S_TRANSFORM "Transform";#define S_FROMSTRING "<from string>"RubySceneImporter::RubySceneImporter() : SceneImporter(){ mVersionMajor = 0; mVersionMinor = 0; mDeltaScene = false; mAutoUnlink = false; mUpdateSceneDict = false; InitTranslationTable();}RubySceneImporter::~RubySceneImporter(){}void RubySceneImporter::SetUnlinkOnCompleteScenes(bool unlink){ mAutoUnlink = unlink;}voidRubySceneImporter::InitTranslationTable(){ mTranslationTable.clear(); mTranslationTable["nd"] = S_NODE; mTranslationTable["sel"] = S_SELECT; mTranslationTable["pwd"] = S_PWD; mTranslationTable["templ"] = S_TEMPLATE; mTranslationTable["def"] = S_DEFINE; mTranslationTable["att"] = S_ATTACH; mTranslationTable["RDS"] = S_DELTASCENE; mTranslationTable["RSG"] = S_SCENEGRAPH; mTranslationTable["SLT"] = S_SETLOCALTRANSFORM; mTranslationTable["sSc"] = S_SETSCALE; mTranslationTable["sMat"] = S_SETMATERIAL; mTranslationTable["BN"] = S_BASENODE; mTranslationTable["SMN"] = S_SINGLEMATNODE; mTranslationTable["TRF"] = S_TRANSFORM;}string RubySceneImporter::Lookup(const std::string& key){ return ((mTranslationTable.find(key) != mTranslationTable.end()) ? mTranslationTable[key] : key);// if (mTranslationTable.find(key) != mTranslationTable.end())// {// return mTranslationTable[key];// } else {// GetLog()->Debug() << "DEBUG: " << key << " not in TranslationTable\n";// return key;// }}voidRubySceneImporter::EnableSceneDictionary(bool enable){ mUpdateSceneDict = enable;}bool RubySceneImporter::ImportScene(const std::string& fileName, shared_ptr<BaseNode> root, shared_ptr<ParameterList> parameter){ // try to open the file shared_ptr<salt::RFile> file = GetFile()->OpenResource(fileName); if (file.get() == 0) { GetLog()->Error() << "(RubySceneImporter) ERROR: cannot open file '" << fileName << "'\n"; return false; } std::string oldFileName = mFileName; mFileName = fileName; // read entire file into a temporary buffer scoped_array<char> buffer(new char[file->Size() + 1]); file->Read(buffer.get(), file->Size()); buffer[file->Size()] = 0; bool ok = ParseScene(buffer.get(), file->Size(), root, parameter); mFileName = oldFileName; return ok;}bool RubySceneImporter::ParseScene(const std::string& scene, shared_ptr<BaseNode> root, shared_ptr<ParameterList> parameter){ mFileName = S_FROMSTRING; return ParseScene(scene.c_str(),static_cast<int>(scene.size()),root,parameter);}bool RubySceneImporter::ParseScene(const char* scene, int size, boost::shared_ptr<oxygen::BaseNode> root, boost::shared_ptr<zeitgeist::ParameterList> parameter){ // parse s-expressions pcont_t* pcont = init_continuation(const_cast<char*>(scene)); sexp_t* sexp = iparse_sexp(const_cast<char*>(scene),size,pcont); // read scene magic and version if ( (sexp == 0) || (! ReadHeader(sexp)) || (mVersionMajor != 0) || (mVersionMinor != 1) ) { destroy_sexp(sexp); destroy_continuation(pcont); return false; } // advance to next sexpression- the scene graph PushParameter(parameter); destroy_sexp(sexp); sexp = iparse_sexp(const_cast<char*>(scene),size,pcont); if (sexp == 0) { GetLog()->Error() << "(RubySceneImporter) ERROR: failed to parse S-Expressions. " << "Last read line was " << pcont->line << "\n"; root->UnlinkChildren(); return false; } if ( (! mDeltaScene) && (mAutoUnlink) ) { root->UnlinkChildren(); } bool ok = mDeltaScene ? ReadDeltaGraph(sexp,root) : ReadGraph(sexp,root); destroy_sexp(sexp); destroy_continuation(pcont); InvokeMethods(); PopParameter(); return ok;}void RubySceneImporter::PushParameter(shared_ptr<ParameterList> parameter){ mParameterStack.push_back(ParamEnv(parameter));}void RubySceneImporter::PopParameter(){ if (mParameterStack.empty()) { GetLog()->Debug() << "(RubySceneImporter) ERROR: PopParameter " << "called on empty stack\n"; return; } mParameterStack.pop_back();}RubySceneImporter::ParamEnv& RubySceneImporter::GetParamEnv(){ if (mParameterStack.empty()) { GetLog()->Debug() << "(RubySceneImporter) ERROR: GetParamEnv " << "called on empty stack\n"; static ParamEnv nullEnv; return nullEnv; } return mParameterStack.back();}bool RubySceneImporter::ReadHeader(sexp_t* sexp){ // (RubySceneGraph <int majorVersion> <int minorVersion>) if ( (sexp == 0) || (sexp->ty != SEXP_LIST) || (sexp->list == 0) ) { return false; } sexp = sexp->list; if (sexp->ty != SEXP_VALUE) { return false; } string val = Lookup(string(sexp->val)); mDeltaScene = false; if (val == S_DELTASCENE) { mDeltaScene = true; } else if (val != S_SCENEGRAPH) { return false; } // try to advance to version number sexp = sexp->next; if ( (sexp == 0) || (sexp->ty != SEXP_VALUE) ) { return false; } string mastr(sexp->val); int major = atoi(mastr.c_str()); if (major < 0) { return false; } sexp = sexp->next; if ( (sexp == 0) || (sexp->ty != SEXP_VALUE) ) { return false; } string mistr(sexp->val); int minor = atoi(mistr.c_str()); if (minor < 0) { return false; } mVersionMajor = major; mVersionMinor = minor; return true;}shared_ptr<Object> RubySceneImporter::CreateInstance(const string& className){ static const string prefixes[] = { "", "oxygen/", "kerosin/" }; const int n = sizeof(prefixes)/sizeof(string); for (int i=0;i<n;++i) { string name = prefixes[i] + className; if (GetCore()->ExistsClass(name)) { return GetCore()->New(name); } } return shared_ptr<Object>();}shared_ptr<BaseNode>RubySceneImporter::CreateNode(sexp_t* sexp){ if (sexp == 0) { return shared_ptr<BaseNode>(); } string className(Lookup(sexp->val)); // create a class instance shared_ptr<Object> obj = CreateInstance(className); if (obj.get() == 0) { GetLog()->Error() << "(RubySceneImporter) ERROR: in file '" << mFileName << "': unknown class '" << className << "'\n"; return shared_ptr<BaseNode>(); } shared_ptr<BaseNode> node = shared_dynamic_cast<BaseNode>(obj); if (node.get() == 0) { GetLog()->Error() << "(RubySceneImporter) ERROR: in file '" << mFileName << className << "': is not derived from BaseNode'\n"; return shared_ptr<BaseNode>(); } if ( (mUpdateSceneDict) && (mSceneDict != 0) ) { mSceneDict->Insert (node, SceneDict::FileRef(mFileName,sexp->line)); } return node;}bool RubySceneImporter::ReplaceVariable(string& param){ // replace a template parameter const ParamEnv& env = GetParamEnv(); param.erase(param.begin(),param.begin()+1); TParameterMap::const_iterator iter = env.parameterMap.find(param); if (iter == env.parameterMap.end()) { GetLog()->Error() << "(RubySceneImporter) ERROR: in file '" << mFileName << "': unknown parameter '" << param << "'\n"; return false; } int idx = (*iter).second; if ( (idx < 0) || (idx >= env.parameter->GetSize()) ) { GetLog()->Error() << "(RubySceneImporter) ERROR: in file '" << mFileName << "': parameter value '" << param << "' not supplied\n"; return false; } string value; ParameterList::TVector::const_iterator pIter = (*env.parameter)[idx]; if (! env.parameter->AdvanceValue(pIter,value)) { GetLog()->Error() << "(RubySceneImporter) ERROR: in file '" << mFileName << "': failed to read parameter value '" << param << "'\n"; return false; } param = value; return true;}bool RubySceneImporter::EvalParameter(sexp_t* sexp, string& value){ const boost::shared_ptr<ScriptServer>& script = GetScript(); if (script.get() == 0) { GetLog()->Error() << "(RubySceneImporter) ERROR: in file '" << mFileName << "': cannot get ScriptServer to eval expression\n"; return false; } if (sexp->ty != SEXP_VALUE) { return false; } string pred = Lookup(sexp->val); //Simply For String Link By Feng Xue //Begin { if (pred == "join") { stringstream ss; sexp = sexp->next; while (sexp != 0) { string atom; if (sexp->ty == SEXP_VALUE) { atom = sexp->val; //todo: use TranslationTable here? if ((atom[0] == '$') && (! ReplaceVariable(atom))) { return false; } } else { if (! EvalParameter(sexp->list, atom)) { return false; } } ss << atom; sexp = sexp->next; } value = ss.str(); return true; } } //End // if (pred == "switch") // { // return ParseSwitch(sexp->next, value); // } if (pred != "eval") { GetLog()->Error() << "(RubySceneImporter) ERROR: in file '" << mFileName << "': unknown expression type '" << pred << "' in parameter list\n"; return false; } string expr; sexp = sexp->next; while (sexp != 0) { string atom; if (sexp->ty == SEXP_VALUE) { atom = sexp->val; //todo: use TranslationTable here? if ( (atom[0] == '$') && (! ReplaceVariable(atom)) ) { return false; } } else { if (! EvalParameter(sexp->list, atom)) { return false; } } expr = expr + atom; expr = expr + " "; sexp = sexp->next; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -