X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FScripting%2FNasalCanvas.cxx;h=204cfa6828398fff179a88bc29275184f7d00ce9;hb=d51499382dc93a8b878e3de795a4471f4ce877ec;hp=2e136ff2d81a98800ab0dfb243fdba9ae89c7498;hpb=724d54b3a3f24107159378cc58c0881fc0a2f3e8;p=flightgear.git diff --git a/src/Scripting/NasalCanvas.cxx b/src/Scripting/NasalCanvas.cxx index 2e136ff2d..204cfa682 100644 --- a/src/Scripting/NasalCanvas.cxx +++ b/src/Scripting/NasalCanvas.cxx @@ -22,19 +22,11 @@ # include "config.h" #endif -#include -#include - #include "NasalCanvas.hxx" #include #include
+#include -//#include -#include -#include -#include -#include -#include #include #include @@ -42,451 +34,26 @@ #include #include +#include #include #include +#include extern naRef propNodeGhostCreate(naContext c, SGPropertyNode* n); -//void initCanvasPython() -//{ -// using namespace boost::python; -// class_("Canvas"); -//} - namespace sc = simgear::canvas; -naRef canvasGetNode(naContext c, sc::Canvas* canvas) +template +naRef elementGetNode(naContext c, Element& element) { - return propNodeGhostCreate(c, canvas->getProps()); + return propNodeGhostCreate(c, element.getProps()); } -namespace nasal -{ - - template - struct class_traits - { - typedef boost::false_type::type is_shared; - typedef T raw_type; - }; - - template - struct class_traits > - { - typedef boost::true_type::type is_shared; - typedef T raw_type; - }; - - template - struct class_traits > - { - typedef boost::true_type::type is_shared; - typedef T raw_type; - }; - - template - struct class_traits > - { - typedef boost::true_type::type is_shared; - typedef T raw_type; - }; - - template - struct SharedPointerPolicy - { - typedef typename class_traits::raw_type raw_type; - - /** - * Create a shared pointer on the heap to handle the reference counting for - * the passed shared pointer while it is used in Nasal space. - */ - static T* createInstance(const T& ptr) - { - return new T(ptr); - } - - static raw_type* getRawPtr(void* ptr) - { - return static_cast(ptr)->get(); - } - }; - - template - struct RawPointerPolicy - { - typedef typename class_traits::raw_type raw_type; - - static T* createInstance() - { - return new T(); - } - - static raw_type* getRawPtr(void* ptr) - { - BOOST_STATIC_ASSERT((boost::is_same::value)); - return static_cast(ptr); - } - }; - - class class_metadata - { - public: - void addNasalBase(const naRef& parent) - { - assert( naIsHash(parent) ); - _parents.push_back(parent); - } - - protected: - const std::string _name; - naGhostType _ghost_type; - std::vector _base_classes; - std::vector _parents; - - explicit class_metadata(const std::string& name): - _name(name) - { - - } - - void addBaseClass(class_metadata* base) - { - assert(base); - std::cout << _name << ": addBase(" << base->_name << ")" << std::endl; - _base_classes.push_back(base); - } - - naRef getParents(naContext c) - { - return nasal::to_nasal(c, _parents); - } - }; - - /** - * Class for exposing C++ objects to Nasal - */ - template - class class_: - public class_metadata, - protected boost::mpl::if_< typename class_traits::is_shared, - SharedPointerPolicy, - RawPointerPolicy >::type - { - private: - typedef typename class_traits::raw_type raw_type; - - public: - - typedef boost::function getter_t; - typedef std::map GetterMap; - - static class_& init(const std::string& name) - { - getSingletonHolder().reset( new class_(name) ); - return *getSingletonPtr(); - } - - static naRef f_create(naContext c, naRef me, int argc, naRef* args) - { - return create(c); - } - - static naRef create( naContext c ) - { - return makeGhost(c, class_::createInstance()); - } - - // TODO use variadic template when supporting C++11 - template - static naRef create( naContext c, const A1& a1 ) - { - return makeGhost(c, class_::createInstance(a1)); - } - - class_& bases(const naRef& parent) - { - addNasalBase(parent); - return *this; - } - - template - typename boost::enable_if - < boost::is_convertible, - class_ - >::type& - bases() - { - Base* base = Base::getSingletonPtr(); - addBaseClass( base ); - - // Replace any getter that is not available in the current class. - // TODO check if this is the correct behavior of function overriding - const typename Base::GetterMap& base_getter = base->getGetter(); - for( typename Base::GetterMap::const_iterator getter = - base_getter.begin(); - getter != base_getter.end(); - ++getter ) - { - if( _getter.find(getter->first) == _getter.end() ) - _getter.insert( *getter ); - } - - return *this; - } - - template - typename boost::enable_if_c - < !boost::is_convertible< Type, class_metadata>::value, - class_ - >::type& - bases() - { - return bases< class_ >(); - } - - template - class_& member( const std::string& field, - Var (raw_type::*getter)() const, - void (raw_type::*setter)(const Var&) = 0 ) - { - naRef (*to_nasal)(naContext, Var) = &nasal::to_nasal; - _getter[field] = boost::bind( to_nasal, - _1, - boost::bind(getter, _2) ); - return *this; - } - - class_& member( const std::string& field, - const getter_t& getter ) - { - _getter[field] = getter; - return *this; - } - - static class_* getSingletonPtr() - { - return getSingletonHolder().get(); - } - - const GetterMap& getGetter() const - { - return _getter; - } - - private: - - typedef std::auto_ptr class_ptr; - GetterMap _getter; - - explicit class_(const std::string& name): - class_metadata( name ) - { - _ghost_type.destroy = &destroyGhost; - _ghost_type.name = _name.c_str(); - _ghost_type.get_member = &getMember; - _ghost_type.set_member = 0; - } - - static class_ptr& getSingletonHolder() - { - static class_ptr instance; - return instance; - } - - static naRef makeGhost(naContext c, void *ptr) - { - std::cout << "makeGhost " << ptr << std::endl; - return naNewGhost2(c, &getSingletonPtr()->_ghost_type, ptr); - } - - static void destroyGhost(void *ptr) - { - std::cout << "destroyGhost " << ptr << std::endl; - delete (T*)ptr; - } - - static const char* getMember(naContext c, void* g, naRef field, naRef* out) - { - const std::string key = naStr_data(field); - if( key == "parents" ) - { - if( getSingletonPtr()->_parents.empty() ) - return 0; - - *out = getSingletonPtr()->getParents(c); - return ""; - } - - typename GetterMap::iterator getter = - getSingletonPtr()->_getter.find(key); - - if( getter == getSingletonPtr()->_getter.end() ) - return 0; - - *out = getter->second(c, class_::getRawPtr(g)); - return ""; - } - }; -} - -struct Base -{ - int getInt() const - { - return 8; - } -}; - -struct Test: - public Base -{ - Test(): x(1) {} - int x; -}; - -typedef nasal::class_ NasalCanvas; - -void initCanvas() -{ - - NasalCanvas::init("Canvas") - .member("_node_ghost", &canvasGetNode) - .member("size_x", &sc::Canvas::getSizeX) - .member("size_y", &sc::Canvas::getSizeY); - nasal::class_::init("canvas.Element"); - nasal::class_::init("canvas.Group") - .bases(); - - nasal::class_::init("BaseClass") - .member("int", &Base::getInt); - nasal::class_::init("TestClass") - .bases(); -} +typedef nasal::Ghost NasalCanvas; +typedef nasal::Ghost NasalElement; +typedef nasal::Ghost NasalGroup; #if 0 -/** - * Class for exposing C++ objects to Nasal - */ -template -class NasalObject -{ - public: - // TODO use variadic template when supporting C++11 - template - static naRef create( naContext c, const A1& a1 ) - { - return makeGhost(c, new T(a1)); - } - - template - static naRef create( naContext c, const A1& a1, - const A2& a2 ) - { - return makeGhost(c, new T(a1, a2)); - } - - template - static naRef create( naContext c, const A1& a1, - const A2& a2, - const A3& a3 ) - { - return makeGhost(c, new T(a1, a2, a3)); - } - - template - static naRef create( naContext c, const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4 ) - { - return makeGhost(c, new T(a1, a2, a3, a4)); - } - - template - static naRef create( naContext c, const A1& a1, - const A2& a2, - const A3& a3, - const A4& a4, - const A5& a5 ) - { - return makeGhost(c, new T(a1, a2, a3, a4, a5)); - } - - // TODO If you need more arguments just do some copy&paste :) - - static Derived& getInstance() - { - static Derived instance; - return instance; - } - - void setParent(const naRef& parent) - { - // TODO check if we need to take care of reference counting/gc - _parents.resize(1); - _parents[0] = parent; - } - - protected: - - // TODO switch to boost::/std::function (with C++11 lambdas this can make - // adding setters easier and shorter) - typedef naRef (Derived::*getter_t)(naContext, const T&); - typedef std::map GetterMap; - - const std::string _ghost_name; - std::vector _parents; - GetterMap _getter; - - NasalObject(const std::string& ghost_name): - _ghost_name( ghost_name ) - { - _ghost_type.destroy = &destroyGhost; - _ghost_type.name = _ghost_name.c_str(); - _ghost_type.get_member = &Derived::getMember; - _ghost_type.set_member = 0; - - _getter["parents"] = &NasalObject::getParents; - } - - naRef getParents(naContext c, const T&) - { - naRef parents = naNewVector(c); - for(size_t i = 0; i < _parents.size(); ++i) - naVec_append(parents, _parents[i]); - return parents; - } - - static naRef makeGhost(naContext c, void *ptr) - { - std::cout << "create " << ptr << std::endl; - return naNewGhost2(c, &(getInstance()._ghost_type), ptr); - } - - static void destroyGhost(void *ptr) - { - std::cout << "destroy " << ptr << std::endl; - delete (T*)ptr; - } - - static const char* getMember(naContext c, void* g, naRef field, naRef* out) - { - typename GetterMap::iterator getter = - getInstance()._getter.find(naStr_data(field)); - - if( getter == getInstance()._getter.end() ) - return 0; - - *out = (getInstance().*getter->second)(c, *static_cast(g)); - return ""; - } - - private: - - naGhostType _ghost_type; - -}; - typedef osg::ref_ptr GUIEventPtr; class NasalCanvasEvent: @@ -494,12 +61,6 @@ class NasalCanvasEvent: { public: - NasalCanvasEvent(): - NasalObject("CanvasEvent") - { - _getter["type"] = &NasalCanvasEvent::getEventType; - } - naRef getEventType(naContext c, const GUIEventPtr& event) { #define RET_EVENT_STR(type, str)\ @@ -525,100 +86,94 @@ class NasalCanvasEvent: } }; #endif -#if 0 -static const char* eventGhostGetMember(naContext c, void* g, naRef field, naRef* out) + +SGPropertyNode& requireArg(naContext c, int argc, naRef* args, int index = 0) { - const char* fieldName = naStr_data(field); - osgGA::GUIEventAdapter* gea = (osgGA::GUIEventAdapter*) g; + if( argc <= index ) + naRuntimeError(c, "missing argument #%d", index); - if (!strcmp(fieldName, "windowX")) *out = naNum(gea->getWindowX()); - else if (!strcmp(fieldName, "windowY")) *out = naNum(gea->getWindowY()); - else if (!strcmp(fieldName, "time")) *out = naNum(gea->getTime()); - else if (!strcmp(fieldName, "button")) *out = naNum(gea->getButton()); - else { - return 0; - } + SGPropertyNode* props = ghostToPropNode(args[index]); + if( !props ) + naRuntimeError(c, "arg #%d: not a SGPropertyNode ghost"); - return ""; + return *props; } -static naRef f_element_addButtonCallback(naContext c, naRef me, int argc, naRef* args) +CanvasMgr& requireCanvasMgr(naContext c) { - simgear::canvas::Element* e = elementGhost(me); - if (!e) { - naRuntimeError(c, "element.addButtonCallback called on non-canvas-element object"); - } - - return naNil(); -} + CanvasMgr* canvas_mgr = + static_cast(globals->get_subsystem("Canvas")); + if( !canvas_mgr ) + naRuntimeError(c, "Failed to get Canvas subsystem"); -static naRef f_element_addDragCallback(naContext c, naRef me, int argc, naRef* args) -{ - simgear::canvas::Element* e = elementGhost(me); - if (!e) { - naRuntimeError(c, "element.addDragCallback called on non-canvas-element object"); - } - - return naNil(); + return *canvas_mgr; } -static naRef f_element_addMoveCallback(naContext c, naRef me, int argc, naRef* args) +/** + * Create new Canvas and get ghost for it. + */ +static naRef f_createCanvas(naContext c, naRef me, int argc, naRef* args) { - simgear::canvas::Element* e = elementGhost(me); - if (!e) { - naRuntimeError(c, "element.addMoveCallback called on non-canvas-element object"); - } - - return naNil(); + return NasalCanvas::create(c, requireCanvasMgr(c).createCanvas()); } -static naRef f_element_addScrollCallback(naContext c, naRef me, int argc, naRef* args) +/** + * Get ghost for existing Canvas. + */ +static naRef f_getCanvas(naContext c, naRef me, int argc, naRef* args) { - simgear::canvas::Element* e = elementGhost(me); - if (!e) { - naRuntimeError(c, "element.addScrollCallback called on non-canvas-element object"); + SGPropertyNode& props = requireArg(c, argc, args); + CanvasMgr& canvas_mgr = requireCanvasMgr(c); + + sc::CanvasPtr canvas; + if( canvas_mgr.getPropertyRoot() == props.getParent() ) + { + // get a canvas specified by its root node + canvas = canvas_mgr.getCanvas( props.getIndex() ); + if( !canvas || canvas->getProps() != &props ) + return naNil(); } - - return naNil(); + else + { + // get a canvas by name + if( props.hasValue("name") ) + canvas = canvas_mgr.getCanvas( props.getStringValue("name") ); + else if( props.hasValue("index") ) + canvas = canvas_mgr.getCanvas( props.getIntValue("index") ); + } + + return NasalCanvas::create(c, canvas); } -#endif -static naRef f_createCanvas(naContext c, naRef me, int argc, naRef* args) +naRef f_canvasCreateGroup( sc::Canvas& canvas, + naContext c, + int argc, + naRef* args ) { - std::cout << "f_createCanvas" << std::endl; - - CanvasMgr* canvas_mgr = - static_cast(globals->get_subsystem("Canvas")); - if( !canvas_mgr ) - return naNil(); + std::string name; + if( argc > 0 ) + name = nasal::from_nasal(c, args[0]); - return NasalCanvas::create(c, canvas_mgr->createCanvas()); + return NasalGroup::create(c, canvas.createGroup(name)); } naRef initNasalCanvas(naRef globals, naContext c, naRef gcSave) { - /*naNewHash(c); - hashset(c, gcSave, "canvasProto", canvasPrototype); - - hashset(c, canvasPrototype, "getElement", naNewFunc(c, naNewCCode(c, f_canvas_getElement)));*/ - // set any event methods - -#if 0 - elementPrototype = naNewHash(c); - hashset(c, gcSave, "elementProto", elementPrototype); - - hashset(c, elementPrototype, "addButtonCallback", naNewFunc(c, naNewCCode(c, f_element_addButtonCallback))); - hashset(c, elementPrototype, "addDragCallback", naNewFunc(c, naNewCCode(c, f_element_addDragCallback))); - hashset(c, elementPrototype, "addMoveCallback", naNewFunc(c, naNewCCode(c, f_element_addMoveCallback))); - hashset(c, elementPrototype, "addScrollCallback", naNewFunc(c, naNewCCode(c, f_element_addScrollCallback))); -#endif + NasalCanvas::init("Canvas") + .member("_node_ghost", &elementGetNode) + .member("size_x", &sc::Canvas::getSizeX) + .member("size_y", &sc::Canvas::getSizeY) + .method_func<&f_canvasCreateGroup>("createGroup"); + NasalElement::init("canvas.Element") + .member("_node_ghost", &elementGetNode); + NasalGroup::init("canvas.Group") + .bases(); + nasal::Hash globals_module(globals, c), canvas_module = globals_module.createHash("canvas"); - canvas_module.set("_new", f_createCanvas); - canvas_module.set("testClass", nasal::class_::f_create); - - initCanvas(); + canvas_module.set("_newCanvasGhost", f_createCanvas); + canvas_module.set("_getCanvasGhost", f_getCanvas); return naNil(); }