From f703882ffa73e70f555caa1867c1650534d5e3dc Mon Sep 17 00:00:00 2001 From: James Turner Date: Thu, 2 Aug 2012 12:18:38 +0100 Subject: [PATCH] Skeleton Nasal-Canvas integration. This code is non-functional, but contains most of the stubs to show what's required to add property get/set access, convert to from ghost & C++ types, and manage ownership. Element derived classes & inheritance (e.g., methods on image/path/map elements) will follow, along with some actual functionality! --- src/Canvas/canvas.hxx | 6 + src/Scripting/CMakeLists.txt | 2 + src/Scripting/NasalCanvas.cxx | 264 ++++++++++++++++++++++++++++++++++ src/Scripting/NasalCanvas.hxx | 35 +++++ src/Scripting/NasalSys.cxx | 3 + 5 files changed, 310 insertions(+) create mode 100644 src/Scripting/NasalCanvas.cxx create mode 100644 src/Scripting/NasalCanvas.hxx diff --git a/src/Canvas/canvas.hxx b/src/Canvas/canvas.hxx index fa75f95d0..29d9ee93e 100644 --- a/src/Canvas/canvas.hxx +++ b/src/Canvas/canvas.hxx @@ -89,6 +89,12 @@ class Canvas: void update(double delta_time_sec); + int getSizeX() const + { return _size_x; } + + int getSizeY() const + { return _size_y; } + void setSizeX(int sx); void setSizeY(int sy); diff --git a/src/Scripting/CMakeLists.txt b/src/Scripting/CMakeLists.txt index d3eab7a70..44c9563b2 100644 --- a/src/Scripting/CMakeLists.txt +++ b/src/Scripting/CMakeLists.txt @@ -4,11 +4,13 @@ set(SOURCES NasalSys.cxx nasal-props.cxx NasalPositioned.cxx + NasalCanvas.cxx ) set(HEADERS NasalSys.hxx NasalPositioned.hxx + NasalCanvas.hxx ) diff --git a/src/Scripting/NasalCanvas.cxx b/src/Scripting/NasalCanvas.cxx new file mode 100644 index 000000000..bbafebd0a --- /dev/null +++ b/src/Scripting/NasalCanvas.cxx @@ -0,0 +1,264 @@ +// NasalCanvas.cxx -- expose Canvas classes to Nasal +// +// Written by James Turner, started 2012. +// +// Copyright (C) 2012 James Turner +// +// 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; either version 2 of the +// License, or (at your option) any later version. +// +// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "NasalCanvas.hxx" + +#include +#include + +#include + +#include + +#include +#include + +static naRef canvasPrototype; +static naRef elementPrototype; +static naRef eventPrototype; + +static void canvasGhostDestroy(void* g); +static void elementGhostDestroy(void* g); +static void eventGhostDestroy(void* g); + +static const char* canvasGhostGetMember(naContext c, void* g, naRef field, naRef* out); +naGhostType CanvasGhostType = { canvasGhostDestroy, "canvas", canvasGhostGetMember, 0 }; + +static const char* elementGhostGetMember(naContext c, void* g, naRef field, naRef* out); +static void elementGhostSetMember(naContext c, void* g, naRef field, naRef value); +naGhostType ElementGhostType = { elementGhostDestroy, "canvas.element", + elementGhostGetMember, elementGhostSetMember }; + +static const char* eventGhostGetMember(naContext c, void* g, naRef field, naRef* out); +naGhostType EventGhostType = { eventGhostDestroy, "ga-event", eventGhostGetMember, 0 }; + +static void hashset(naContext c, naRef hash, const char* key, naRef val) +{ + naRef s = naNewString(c); + naStr_fromdata(s, (char*)key, strlen(key)); + naHash_set(hash, s, val); +} + +static naRef stringToNasal(naContext c, const std::string& s) +{ + return naStr_fromdata(naNewString(c), + const_cast(s.c_str()), + s.length()); +} + +static naRef eventTypeToNasal(naContext c, osgGA::GUIEventAdapter::EventType ty) +{ + switch (ty) { + case osgGA::GUIEventAdapter::PUSH: return stringToNasal(c, "push"); + case osgGA::GUIEventAdapter::RELEASE: return stringToNasal(c, "release"); + case osgGA::GUIEventAdapter::DOUBLECLICK: return stringToNasal(c, "double-click"); + case osgGA::GUIEventAdapter::DRAG: return stringToNasal(c, "drag"); + case osgGA::GUIEventAdapter::MOVE: return stringToNasal(c, "move"); + case osgGA::GUIEventAdapter::SCROLL: return stringToNasal(c, "scroll"); + case osgGA::GUIEventAdapter::KEYUP: return stringToNasal(c, "key-up"); + case osgGA::GUIEventAdapter::KEYDOWN: return stringToNasal(c, "key-down"); + + default: + ; // fall through + } + + return naNil(); +} + +static canvas::Element* elementGhost(naRef r) +{ + if (naGhost_type(r) == &ElementGhostType) + return (canvas::Element*) naGhost_ptr(r); + return 0; +} + +static Canvas* canvasGhost(naRef r) +{ + if (naGhost_type(r) == &CanvasGhostType) + return (Canvas*) naGhost_ptr(r); + return 0; +} + +static void elementGhostDestroy(void* g) +{ +} + +static void canvasGhostDestroy(void* g) +{ +} + +static void eventGhostDestroy(void* g) +{ + osgGA::GUIEventAdapter* gea = static_cast(g); + gea->unref(); +} + +static const char* eventGhostGetMember(naContext c, void* g, naRef field, naRef* out) +{ + const char* fieldName = naStr_data(field); + osgGA::GUIEventAdapter* gea = (osgGA::GUIEventAdapter*) g; + + if (!strcmp(fieldName, "parents")) { + *out = naNewVector(c); + naVec_append(*out, eventPrototype); + } else if (!strcmp(fieldName, "type")) *out = eventTypeToNasal(c, gea->getEventType()); + else 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; + } + + return ""; +} + +static const char* canvasGhostGetMember(naContext c, void* g, naRef field, naRef* out) +{ + const char* fieldName = naStr_data(field); + Canvas* cvs = (Canvas*) g; + + if (!strcmp(fieldName, "parents")) { + *out = naNewVector(c); + naVec_append(*out, canvasPrototype); + } else if (!strcmp(fieldName, "sizeX")) *out = naNum(cvs->getSizeX()); + else if (!strcmp(fieldName, "sizeY")) *out = naNum(cvs->getSizeY()); + else { + return 0; + } + + return ""; +} + +static const char* elementGhostGetMember(naContext c, void* g, naRef field, naRef* out) +{ + const char* fieldName = naStr_data(field); + canvas::Element* e = (canvas::Element*) g; + + if (!strcmp(fieldName, "parents")) { + *out = naNewVector(c); + naVec_append(*out, elementPrototype); + } else { + return 0; + } + + return ""; +} + +static void elementGhostSetMember(naContext c, void* g, naRef field, naRef value) +{ + const char* fieldName = naStr_data(field); + canvas::Element* e = (canvas::Element*) g; +} + + +static naRef f_canvas_getElement(naContext c, naRef me, int argc, naRef* args) +{ + Canvas* cvs = canvasGhost(me); + if (!cvs) { + naRuntimeError(c, "canvas.getElement called on non-canvas object"); + } + + return naNil(); +} + +static naRef f_element_addButtonCallback(naContext c, naRef me, int argc, naRef* args) +{ + canvas::Element* e = elementGhost(me); + if (!e) { + naRuntimeError(c, "element.addButtonCallback called on non-canvas-element object"); + } + + return naNil(); +} + +static naRef f_element_addDragCallback(naContext c, naRef me, int argc, naRef* args) +{ + canvas::Element* e = elementGhost(me); + if (!e) { + naRuntimeError(c, "element.addDragCallback called on non-canvas-element object"); + } + + return naNil(); +} + +static naRef f_element_addMoveCallback(naContext c, naRef me, int argc, naRef* args) +{ + canvas::Element* e = elementGhost(me); + if (!e) { + naRuntimeError(c, "element.addMoveCallback called on non-canvas-element object"); + } + + return naNil(); +} + +static naRef f_element_addScrollCallback(naContext c, naRef me, int argc, naRef* args) +{ + canvas::Element* e = elementGhost(me); + if (!e) { + naRuntimeError(c, "element.addScrollCallback called on non-canvas-element object"); + } + + return naNil(); +} + +static naRef f_canvas(naContext c, naRef me, int argc, naRef* args) +{ + return naNil(); +} + +// Table of extension functions. Terminate with zeros. +static struct { const char* name; naCFunction func; } funcs[] = { + { "canvas", f_canvas }, + { 0, 0 } +}; + +naRef initNasalCanvas(naRef globals, naContext c, naRef gcSave) +{ + canvasPrototype = naNewHash(c); + hashset(c, gcSave, "canvasProto", canvasPrototype); + + hashset(c, canvasPrototype, "getElement", naNewFunc(c, naNewCCode(c, f_canvas_getElement))); + + eventPrototype = naNewHash(c); + hashset(c, gcSave, "eventProto", eventPrototype); + // set any event methods + + 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))); + + for(int i=0; funcs[i].name; i++) { + hashset(c, globals, funcs[i].name, + naNewFunc(c, naNewCCode(c, funcs[i].func))); + } + + return naNil(); +} diff --git a/src/Scripting/NasalCanvas.hxx b/src/Scripting/NasalCanvas.hxx new file mode 100644 index 000000000..c68fc0410 --- /dev/null +++ b/src/Scripting/NasalCanvas.hxx @@ -0,0 +1,35 @@ +// NasalCanvas.hxx -- expose Canvas classes to Nasal +// +// Written by James Turner, started 2012. +// +// Copyright (C) 2012 James Turner +// +// 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; either version 2 of the +// License, or (at your option) any later version. +// +// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +#ifndef SCRIPTING_NASAL_CANVAS_HXX +#define SCRIPTING_NASAL_CANVAS_HXX + +#include + +// forward decls +namespace canvas +{ + class Element; +} + +naRef initNasalCanvas(naRef globals, naContext c, naRef gcSave); + +#endif // of SCRIPTING_NASAL_CANVAS_HXX + diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index b65264a8b..a1de1e794 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -27,6 +27,8 @@ #include "NasalSys.hxx" #include "NasalPositioned.hxx" +#include "NasalCanvas.hxx" + #include
#include
#include
@@ -548,6 +550,7 @@ void FGNasalSys::init() hashset(_globals, "__gcsave", _gcHash); initNasalPositioned(_globals, _context, _gcHash); + initNasalCanvas(_globals, _context, _gcHash); // Now load the various source files in the Nasal directory simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));