diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index d841acf016..7a504b5679 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -52,7 +52,7 @@ public: static bool findConfiguration(std::string& filename); ConfigurationManager& configurationManager(); - InteractionHandler& interactionHandler(); + interaction::InteractionHandler& interactionHandler(); RenderEngine& renderEngine(); scripting::ScriptEngine& scriptEngine(); @@ -86,7 +86,7 @@ private: static OpenSpaceEngine* _engine; ConfigurationManager _configurationManager; - InteractionHandler _interactionHandler; + interaction::InteractionHandler _interactionHandler; RenderEngine _renderEngine; scripting::ScriptEngine _scriptEngine; ghoul::cmdparser::CommandlineParser _commandlineParser; diff --git a/include/openspace/interaction/controller.h b/include/openspace/interaction/controller.h new file mode 100644 index 0000000000..357d1bfa45 --- /dev/null +++ b/include/openspace/interaction/controller.h @@ -0,0 +1,53 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __CONTROLLER_H__ +#define __CONTROLLER_H__ + +#include + +#include +#include + +namespace openspace { +namespace interaction { + +class InteractionHandler; + +class Controller { +public: + Controller() : + _handler(nullptr) + {} + + void setHandler(InteractionHandler* handler); + +protected: + InteractionHandler* _handler; +}; + +} // namespace interaction +} // namespace openspace + +#endif // __CONTROLLER_H__ \ No newline at end of file diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index 1ccd5174c6..65c6e13ba5 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -22,65 +22,109 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef INTERACTIONHANDLER_H -#define INTERACTIONHANDLER_H +//<<<<<<< HEAD +//#ifndef INTERACTIONHANDLER_H +//#define INTERACTIONHANDLER_H +// +//#include +//#include +//#include +// +//// std includes +//#include +//#include +//#include +//#include +// +//namespace openspace { +// +//// Forward declare to minimize dependencies +//class Camera; +//class SceneGraphNode; +//class ExternalControl; +// +//class InteractionHandler { +//public: +// InteractionHandler(void); +// InteractionHandler(const InteractionHandler& src); +// InteractionHandler& operator=(const InteractionHandler& rhs); +// virtual ~InteractionHandler(); +// +// void enable(); +// void disable(); +// const bool isEnabled() const; +// +// void connectDevices(); +// void addExternalControl(ExternalControl* controller); +// +// void setCamera(Camera *camera = nullptr); +// void setOrigin(SceneGraphNode* node); +// +// Camera* getCamera() const; +// const psc getOrigin() const; +// void lockControls(); +// void unlockControls(); +// +// void setFocusNode(SceneGraphNode *node); +// +// void orbit(const glm::quat &rotation); +// void rotate(const glm::quat &rotation); +// void distance(const PowerScaledScalar &distance, size_t iterations = 0); +//======= +#ifndef __INTERACTIONHANDLER_H__ +#define __INTERACTIONHANDLER_H__ -#include -#include -#include +#include +#include -// std includes -#include #include -#include -#include namespace openspace { -// Forward declare to minimize dependencies class Camera; class SceneGraphNode; -class ExternalControl; + +namespace interaction { class InteractionHandler { public: - InteractionHandler(void); - InteractionHandler(const InteractionHandler& src); - InteractionHandler& operator=(const InteractionHandler& rhs); - virtual ~InteractionHandler(); + InteractionHandler(); - void enable(); - void disable(); - const bool isEnabled() const; + ~InteractionHandler(); - void connectDevices(); - void addExternalControl(ExternalControl* controller); + void setKeyboardController(KeyboardController* controller); + void setMouseController(MouseController* controller); + void addController(Controller* controller); - void setCamera(Camera *camera = nullptr); - void setOrigin(SceneGraphNode* node); - - Camera* getCamera() const; - const psc getOrigin() const; void lockControls(); void unlockControls(); - void setFocusNode(SceneGraphNode *node); - - void orbit(const glm::quat &rotation); - void rotate(const glm::quat &rotation); - void distance(const PowerScaledScalar &distance, size_t iterations = 0); + void update(double deltaTime); - void lookAt(const glm::quat &rotation); - void setRotation(const glm::quat &rotation); - - void update(const double dt); - - double dt(); + void setFocusNode(SceneGraphNode* node); + const SceneGraphNode* const focusNode() const; + void setCamera(Camera* camera); + const Camera* const camera() const; void keyboardCallback(int key, int action); - void mouseButtonCallback(int key, int action); - void mousePositionCallback(int x, int y); - void mouseScrollWheelCallback(int pos); + void mouseButtonCallback(int button, int action); + void mousePositionCallback(int x, int y); + void mouseScrollWheelCallback(int pos); + +//<<<<<<< HEAD + //double dt(); +//======= + double deltaTime() const; + + void orbitDelta(const glm::quat& rotation); + + void rotateDelta(const glm::quat& rotation); + + void distanceDelta(const PowerScaledScalar& distance); + + void lookAt(const glm::quat& rotation); + + void setRotation(const glm::quat& rotation); void resetKeyBindings(); void bindKey(int key, const std::string& lua); @@ -95,30 +139,47 @@ public: static scripting::ScriptEngine::LuaLibrary luaLibrary(); private: - glm::vec3 mapToTrackball(glm::vec2 mousePos); - glm::vec3 mapToCamera(glm::vec3 trackballPos); - void trackballRotate(int x, int y); + friend class Controller; + +//<<<<<<< HEAD +// Camera* _camera; +// bool _enabled; +// SceneGraphNode* _node; +// +// double _dt; +//======= + InteractionHandler(const InteractionHandler&) = delete; + InteractionHandler& operator=(const InteractionHandler&) = delete; + InteractionHandler(InteractionHandler&&) = delete; + InteractionHandler& operator=(InteractionHandler&&) = delete; Camera* _camera; - bool _enabled; - SceneGraphNode* _node; - - double _dt; + SceneGraphNode* _focusNode; - glm::vec3 _lastTrackballPos; - bool _leftMouseButtonDown, _isMouseBeingPressedAndHeld; + double _deltaTime; + std::mutex _mutex; - // used for calling when updating and deallocation - std::vector _controllers; - - // for locking and unlocking - std::mutex _cameraGuard; +//<<<<<<< HEAD +// // used for calling when updating and deallocation +// std::vector _controllers; +// +// // for locking and unlocking +// std::mutex _cameraGuard; bool _validKeyLua; std::multimap _keyLua; + KeyboardController* _keyboardController; + MouseController* _mouseController; + std::vector _controllers; + + + // glm::vec3 mapToTrackball(glm::vec2 mousePos); + // glm::vec3 mapToCamera(glm::vec3 trackballPos); + // void trackballRotate(int x, int y); }; +} // namespace interaction } // namespace openspace -#endif +#endif // __INTERACTIONHANDLER_H__ diff --git a/include/openspace/interaction/keyboardcontroller.h b/include/openspace/interaction/keyboardcontroller.h new file mode 100644 index 0000000000..045fbcc0c1 --- /dev/null +++ b/include/openspace/interaction/keyboardcontroller.h @@ -0,0 +1,56 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __KEYBOARDCONTROLLER_H__ +#define __KEYBOARDCONTROLLER_H__ + +#include + +#include + +namespace openspace { +namespace interaction { + +class KeyboardController : public Controller { +public: + virtual void keyPressed(KeyAction action, Key key, KeyModifier modifier) = 0; +}; + +class KeyboardControllerFixed : public KeyboardController { +public: + void keyPressed(KeyAction action, Key key, KeyModifier modifier); +}; + +class KeyboardControllerLua : public KeyboardController { +public: + void keyPressed(KeyAction action, Key key, KeyModifier modifier); + +protected: + std::string keyToString(Key key, KeyModifier mod) const; +}; + +} // namespace interaction +} // namespace openspace + +#endif // __KEYBOARDCONTROLLER_H__ diff --git a/include/openspace/interaction/keys.h b/include/openspace/interaction/keys.h new file mode 100644 index 0000000000..b380a7b789 --- /dev/null +++ b/include/openspace/interaction/keys.h @@ -0,0 +1,174 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __KEYS_H__ +#define __KEYS_H__ + +#include + +namespace openspace { +namespace interaction { + +enum class KeyAction { + Press = SGCT_PRESS, + Release = SGCT_RELEASE, + Repeat = SGCT_REPEAT +}; + +enum class KeyModifier { + None = 0, + Shift = GLFW_MOD_SHIFT, + Control = GLFW_MOD_CONTROL, + Alt = GLFW_MOD_ALT, + Super = GLFW_MOD_SUPER +}; + +enum class Key { + Unknown = SGCT_KEY_UNKNOWN, + Space = SGCT_KEY_SPACE, + Apostrophe = SGCT_KEY_APOSTROPHE, + Comma = SGCT_KEY_COMMA, + Minus = SGCT_KEY_MINUS, + Period = SGCT_KEY_PERIOD, + Slash = SGCT_KEY_SLASH, + Num0 = SGCT_KEY_0, + Num1 = SGCT_KEY_1, + Num2 = SGCT_KEY_2, + Num3 = SGCT_KEY_3, + Num4 = SGCT_KEY_4, + Num5 = SGCT_KEY_5, + Num6 = SGCT_KEY_6, + Num7 = SGCT_KEY_7, + Num8 = SGCT_KEY_8, + Num9 = SGCT_KEY_9, + SemiColon = SGCT_KEY_SEMICOLON, + Equal = SGCT_KEY_EQUAL, + A = SGCT_KEY_A, + B = SGCT_KEY_B, + C = SGCT_KEY_C, + D = SGCT_KEY_D, + E = SGCT_KEY_E, + F = SGCT_KEY_F, + G = SGCT_KEY_G, + H = SGCT_KEY_H, + I = SGCT_KEY_I, + J = SGCT_KEY_J, + K = SGCT_KEY_K, + L = SGCT_KEY_L, + M = SGCT_KEY_M, + N = SGCT_KEY_N, + O = SGCT_KEY_O, + P = SGCT_KEY_P, + Q = SGCT_KEY_Q, + R = SGCT_KEY_R, + S = SGCT_KEY_S, + T = SGCT_KEY_T, + U = SGCT_KEY_U, + V = SGCT_KEY_V, + W = SGCT_KEY_W, + X = SGCT_KEY_X, + Y = SGCT_KEY_Y, + Z = SGCT_KEY_Z, + LeftBracket = SGCT_KEY_LEFT_BRACKET, + BackSlash = SGCT_KEY_BACKSLASH, + RightBracket = SGCT_KEY_RIGHT_BRACKET, + GraveAccent = SGCT_KEY_GRAVE_ACCENT, + World1 = SGCT_KEY_WORLD_1, + World2 = SGCT_KEY_WORLD_2, + Escape = SGCT_KEY_ESC, + Enter = SGCT_KEY_ENTER, + Tab = SGCT_KEY_TAB, + BackSpace = SGCT_KEY_BACKSPACE, + Insert = SGCT_KEY_INSERT, + Delete = SGCT_KEY_DELETE, + Right = SGCT_KEY_RIGHT, + Left = SGCT_KEY_LEFT, + Down = SGCT_KEY_DOWN, + Up = SGCT_KEY_UP, + PageUp = SGCT_KEY_PAGE_UP, + PageDown = SGCT_KEY_PAGE_DOWN, + Home = SGCT_KEY_HOME, + End = SGCT_KEY_END, + CapsLock = SGCT_KEY_CAPS_LOCK, + ScrollLock = SGCT_KEY_SCROLL_LOCK, + NumLock = SGCT_KEY_NUM_LOCK, + PrintScreen = SGCT_KEY_PRINT_SCREEN, + Pause = SGCT_KEY_PAUSE, + F1 = SGCT_KEY_F1, + F2 = SGCT_KEY_F2, + F3 = SGCT_KEY_F3, + F4 = SGCT_KEY_F4, + F5 = SGCT_KEY_F5, + F6 = SGCT_KEY_F6, + F7 = SGCT_KEY_F7, + F8 = SGCT_KEY_F8, + F9 = SGCT_KEY_F9, + F10 = SGCT_KEY_F10, + F11 = SGCT_KEY_F11, + F12 = SGCT_KEY_F12, + F13 = SGCT_KEY_F13, + F14 = SGCT_KEY_F14, + F15 = SGCT_KEY_F15, + F16 = SGCT_KEY_F16, + F17 = SGCT_KEY_F17, + F18 = SGCT_KEY_F18, + F19 = SGCT_KEY_F19, + F20 = SGCT_KEY_F20, + F21 = SGCT_KEY_F21, + F22 = SGCT_KEY_F22, + F23 = SGCT_KEY_F23, + F24 = SGCT_KEY_F24, + F25 = SGCT_KEY_F25, + Keypad0 = SGCT_KEY_KP_0, + Keypad1 = SGCT_KEY_KP_1, + Keypad2 = SGCT_KEY_KP_2, + Keypad3 = SGCT_KEY_KP_3, + Keypad4 = SGCT_KEY_KP_4, + Keypad5 = SGCT_KEY_KP_5, + Keypad6 = SGCT_KEY_KP_6, + Keypad7 = SGCT_KEY_KP_7, + Keypad8 = SGCT_KEY_KP_8, + Keypad9 = SGCT_KEY_KP_9, + KeypadDecimal = SGCT_KEY_KP_DECIMAL, + KeypadDivide = SGCT_KEY_KP_DIVIDE, + KeypadMultiply = SGCT_KEY_KP_MULTIPLY, + KeypadSubtract = SGCT_KEY_KP_SUBTRACT, + KeypadAdd = SGCT_KEY_KP_ADD, + KeypadEnter = SGCT_KEY_KP_ENTER, + LeftShift = SGCT_KEY_LEFT_SHIFT, + LeftControl = SGCT_KEY_LEFT_CONTROL, + LeftAlt = SGCT_KEY_LEFT_ALT, + LeftSuper = SGCT_KEY_LEFT_SUPER, + RightShift = SGCT_KEY_RIGHT_SHIFT, + RightControl = SGCT_KEY_RIGHT_CONTROL, + RightAlt = SGCT_KEY_RIGHT_ALT, + RightSuper = SGCT_KEY_RIGHT_SUPER, + Menu = SGCT_KEY_MENU, + Last = SGCT_KEY_LAST +}; + +} // namespace interaction +} // namespace openspace + +#endif // __KEYS_H__ diff --git a/include/openspace/interaction/mouse.h b/include/openspace/interaction/mouse.h new file mode 100644 index 0000000000..2a4cca19d6 --- /dev/null +++ b/include/openspace/interaction/mouse.h @@ -0,0 +1,57 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __MOUSE_H__ +#define __MOUSE_H__ + +#include + +namespace openspace { +namespace interaction { + +enum class MouseAction { + Press = SGCT_PRESS, + Release = SGCT_RELEASE, + Repeat = SGCT_REPEAT +}; + +enum class MouseButton { + Left = SGCT_MOUSE_BUTTON_LEFT, + Right = SGCT_MOUSE_BUTTON_RIGHT, + Middle = SGCT_MOUSE_BUTTON_MIDDLE, + Button1 = SGCT_MOUSE_BUTTON_1, + Button2 = SGCT_MOUSE_BUTTON_2, + Button3 = SGCT_MOUSE_BUTTON_3, + Button4 = SGCT_MOUSE_BUTTON_4, + Button5 = SGCT_MOUSE_BUTTON_5, + Button6 = SGCT_MOUSE_BUTTON_6, + Button7 = SGCT_MOUSE_BUTTON_7, + Button8 = SGCT_MOUSE_BUTTON_8, + ButtonLast = SGCT_MOUSE_BUTTON_LAST, +}; + +} // namespace interaction +} // namespace openspace + +#endif // __MOUSE_H__ diff --git a/include/openspace/interaction/mousecontroller.h b/include/openspace/interaction/mousecontroller.h new file mode 100644 index 0000000000..64f085d442 --- /dev/null +++ b/include/openspace/interaction/mousecontroller.h @@ -0,0 +1,73 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __MOUSECONTROLLER_H__ +#define __MOUSECONTROLLER_H__ + +#include + +#include + +#include + +namespace openspace { +namespace interaction { + +class MouseController : public Controller { +public: + MouseController(); + + virtual void button(MouseAction action, MouseButton button) = 0; + virtual void move(float x, float y) = 0; + virtual void scrollWheel(int pos) = 0; + +protected: + glm::vec3 _lastTrackballPos; + bool _isMouseBeingPressedAndHeld; + + glm::vec3 mapToTrackball(glm::vec2 mousePos); + + glm::vec3 mapToCamera(glm::vec3 trackballPos); + + void trackballRotate(int x, int y); +}; + +class TrackballMouseController : public MouseController { +public: + TrackballMouseController(); + + void button(MouseAction action, MouseButton button); + + void move(float x, float y); + + void scrollWheel(int pos); + +protected: + bool _leftMouseButtonDown; +}; + +} // namespace interaction +} // namespace openspace + +#endif // __MOUSECONTROLLER_H__ \ No newline at end of file diff --git a/include/openspace/scripting/scriptengine.h b/include/openspace/scripting/scriptengine.h index 648bc0ca12..5d5a76eead 100644 --- a/include/openspace/scripting/scriptengine.h +++ b/include/openspace/scripting/scriptengine.h @@ -26,6 +26,7 @@ #define __SCRIPTENGINE_H__ #include + #include /** @@ -50,19 +51,24 @@ public: }; ScriptEngine(); - + bool initialize(); void deinitialize(); - bool addLibrary(const LuaLibrary& library); + void initializeLuaState(lua_State* state); + + void addLibrary(const LuaLibrary& library); bool hasLibrary(const std::string& name); bool runScript(const std::string& script); bool runScriptFile(const std::string& filename); + private: + bool registerLuaLibrary(lua_State* state, const LuaLibrary& library); + void addLibraryFunctions(lua_State* state, const LuaLibrary& library, bool replace); + bool isLibraryNameAllowed(const std::string& name); - void addLibraryFunctions(const LuaLibrary& library, bool replace); void addBaseLibrary(); void remapPrintFunction(); diff --git a/scripts/default_keybinding.lua b/scripts/default_keybinding.lua new file mode 100644 index 0000000000..56943efb65 --- /dev/null +++ b/scripts/default_keybinding.lua @@ -0,0 +1,4 @@ +return { + W = function() print("w") end, + S = function() print("s") end +} diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index a6723a4adb..216976614c 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -25,9 +25,11 @@ #include // openspace -#include #include #include +#include +#include +#include #include #include #include @@ -88,7 +90,7 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName) // initialize OpenSpace helpers SpiceManager::initialize(); Time::initialize(); - DeviceIdentifier::init(); + //DeviceIdentifier::init(); FactoryManager::initialize(); ghoul::systemcapabilities::SystemCapabilities::initialize(); } @@ -99,9 +101,13 @@ OpenSpaceEngine::~OpenSpaceEngine() { ghoul::systemcapabilities::SystemCapabilities::deinitialize(); FactoryManager::deinitialize(); - DeviceIdentifier::deinit(); + //DeviceIdentifier::deinit(); Time::deinitialize(); SpiceManager::deinitialize(); + Time::deinitialize(); + //DeviceIdentifier::deinit(); + FileSystem::deinitialize(); + LogManager::deinitialize(); } OpenSpaceEngine& OpenSpaceEngine::ref() { @@ -336,18 +342,17 @@ bool OpenSpaceEngine::initialize() { if (!success) return false; - // Initialize the script engine - _scriptEngine.initialize(); - // Register Lua script functions LDEBUG("Registering Lua libraries"); _scriptEngine.addLibrary(RenderEngine::luaLibrary()); _scriptEngine.addLibrary(SceneGraph::luaLibrary()); _scriptEngine.addLibrary(Time::luaLibrary()); - _scriptEngine.addLibrary(InteractionHandler::luaLibrary()); + _scriptEngine.addLibrary(interaction::InteractionHandler::luaLibrary()); // TODO: Maybe move all scenegraph and renderengine stuff to initializeGL - // Load scenegraph + scriptEngine().initialize(); + + // Load scenegraph SceneGraph* sceneGraph = new SceneGraph; _renderEngine.setSceneGraph(sceneGraph); @@ -362,8 +367,12 @@ bool OpenSpaceEngine::initialize() { sceneGraph->scheduleLoadSceneFile(sceneDescriptionPath); // Initialize OpenSpace input devices - DeviceIdentifier::ref().scanDevices(); - _interactionHandler.connectDevices(); + //DeviceIdentifier::init(); + //DeviceIdentifier::ref().scanDevices(); + + //_interactionHandler.setKeyboardController(new interaction::KeyboardControllerFixed); + _interactionHandler.setKeyboardController(new interaction::KeyboardControllerLua); + _interactionHandler.setMouseController(new interaction::TrackballMouseController); // Run start up scripts runStartupScripts(); @@ -378,7 +387,7 @@ ConfigurationManager& OpenSpaceEngine::configurationManager() { return _configurationManager; } -InteractionHandler& OpenSpaceEngine::interactionHandler() { +interaction::InteractionHandler& OpenSpaceEngine::interactionHandler() { return _interactionHandler; } diff --git a/src/interaction/controller.cpp b/src/interaction/controller.cpp new file mode 100644 index 0000000000..311fdfc6ac --- /dev/null +++ b/src/interaction/controller.cpp @@ -0,0 +1,39 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +namespace openspace { +namespace interaction { + +void Controller::setHandler(InteractionHandler* handler) +{ + _handler = handler; +} + +} // namespace interaction +} // namespace openspace + diff --git a/src/interaction/externalcontrol/externalcontrol.cpp b/src/interaction/externalcontrol/externalcontrol.cpp index ff37ffd055..9060259c7f 100644 --- a/src/interaction/externalcontrol/externalcontrol.cpp +++ b/src/interaction/externalcontrol/externalcontrol.cpp @@ -17,15 +17,15 @@ void ExternalControl::update() { } void ExternalControl::rotate(const glm::quat &rotation) { - OsEng.interactionHandler().rotate(rotation); + //OsEng.interactionHandler().rotate(rotation); } void ExternalControl::orbit(const glm::quat &rotation) { - OsEng.interactionHandler().orbit(rotation); + //OsEng.interactionHandler().orbit(rotation); } void ExternalControl::distance(const PowerScaledScalar &distance) { - OsEng.interactionHandler().distance(distance); + //OsEng.interactionHandler().distance(distance); } diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 401f51545d..a7b10514f6 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -22,30 +22,36 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -// open space includes +//<<<<<<< HEAD +//// open space includes +#include +// +#include +//#include +//#include +//#include +//#include +#include +//#include +//#include +//#include +//#include +// +//// ghoul +#include +// +//// other +//#include +//#include +// +//// std includes +//#include +//#include +// + #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// ghoul -#include - -// other -#include -#include - -// std includes -#include -#include +#include namespace { const std::string _loggerCat = "InteractionHandler"; @@ -225,7 +231,7 @@ int setOrigin(lua_State* L) { return 0; } - OsEng.interactionHandler().setOrigin(node); + OsEng.interactionHandler().setFocusNode(node); return 0; } @@ -291,7 +297,7 @@ int dt(lua_State* L) { if (nArguments != 0) return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments); - lua_pushnumber(L,OsEng.interactionHandler().dt()); + lua_pushnumber(L,OsEng.interactionHandler().deltaTime()); return 1; } @@ -308,156 +314,221 @@ int distance(lua_State* L) { double d1 = luaL_checknumber(L, -2); double d2 = luaL_checknumber(L, -1); PowerScaledScalar dist(d1, d2); - OsEng.interactionHandler().distance(dist); + OsEng.interactionHandler().distanceDelta(dist); return 0; } } // namespace luascriptfunctions -InteractionHandler::InteractionHandler() { - // initiate pointers - _camera = nullptr; - _enabled = true; - _node = nullptr; - _dt = 0.0; - _lastTrackballPos = glm::vec3(0.0, 0.0, 0.5); - _leftMouseButtonDown = false; - _isMouseBeingPressedAndHeld = false; +//InteractionHandler::InteractionHandler() { +// // initiate pointers +// _camera = nullptr; +// _enabled = true; +// _node = nullptr; +// _dt = 0.0; +// _lastTrackballPos = glm::vec3(0.0, 0.0, 0.5); +// _leftMouseButtonDown = false; +// _isMouseBeingPressedAndHeld = false; +//} +// +//InteractionHandler::~InteractionHandler() { +// for (size_t i = 0; i < _controllers.size(); ++i) { +// delete _controllers[i]; +// } +//} +// +////void InteractionHandler::init() { +//// assert( ! this_); +//// this_ = new InteractionHandler(); +////} +//// +////void InteractionHandler::deinit() { +//// assert(this_); +//// delete this_; +//// this_ = nullptr; +////} +//// +////InteractionHandler& InteractionHandler::ref() { +//// assert(this_); +//// return *this_; +////} +// +////bool InteractionHandler::isInitialized() { +//// return this_ != nullptr; +////} +// +//void InteractionHandler::enable() { +// //assert(this_); +// _enabled = true; +//} +// +//void InteractionHandler::disable() { +// //assert(this_); +// _enabled = false; +//} +// +//const bool InteractionHandler::isEnabled() const { +// //assert(this_); +// if (_camera) +// return false; +// return _enabled; +//======= + +//namespace openspace { +namespace interaction { + +InteractionHandler::InteractionHandler() + : _camera(nullptr) + , _focusNode(nullptr) + , _keyboardController(nullptr) + , _mouseController(nullptr) +{ } InteractionHandler::~InteractionHandler() { - for (size_t i = 0; i < _controllers.size(); ++i) { + delete _keyboardController; + delete _mouseController; + for (size_t i = 0; i < _controllers.size(); ++i) delete _controllers[i]; - } } -//void InteractionHandler::init() { -// assert( ! this_); -// this_ = new InteractionHandler(); -//} -// -//void InteractionHandler::deinit() { -// assert(this_); -// delete this_; -// this_ = nullptr; -//} -// -//InteractionHandler& InteractionHandler::ref() { -// assert(this_); -// return *this_; -//} - -//bool InteractionHandler::isInitialized() { -// return this_ != nullptr; -//} - -void InteractionHandler::enable() { - //assert(this_); - _enabled = true; +void InteractionHandler::setKeyboardController(KeyboardController* controller) { + assert(controller); + delete _keyboardController; + _keyboardController = controller; + _keyboardController->setHandler(this); } -void InteractionHandler::disable() { - //assert(this_); - _enabled = false; +void InteractionHandler::setMouseController(MouseController* controller) { + assert(controller); + delete _mouseController; + _mouseController = controller; + _mouseController->setHandler(this); } -const bool InteractionHandler::isEnabled() const { - //assert(this_); - if (_camera) - return false; - return _enabled; -} - -void InteractionHandler::connectDevices() { - //assert(this_); - assert(DeviceIdentifier::ref().isInitialized()); - - // for each device found - for(int i = 0; i < DeviceIdentifier::ref().numberOfDevices(); ++i) { - - // TODO - //if(DeviceIdentifier::ref().type(i) == InputDevice::XBOX) { - - // // found xbox, use xbox python controller - // JoystickExternalControl *joystickexcontrol = new JoystickExternalControl(RELATIVE_PATH"pyinput/Xbox.py"); - // joystickexcontrol->setInputDevice(i); - // addExternalControl(joystickexcontrol); - - //} else if(DeviceIdentifier::ref().type(i) == InputDevice::SPACENAVIGATOR) { - - // // found SpaceNavigator, use SpaceNavigator python controller - // JoystickExternalControl *joystickexcontrol = new JoystickExternalControl(RELATIVE_PATH"pyinput/SpaceNavigator.py"); - // joystickexcontrol->setInputDevice(i); - // addExternalControl(joystickexcontrol); - //} - - } -} - -void InteractionHandler::addExternalControl(ExternalControl* controller) { - //assert(this_); - if (controller != nullptr) { - _controllers.push_back(controller); - } -} - -void InteractionHandler::setCamera(Camera *camera) { - //assert(this_); - _camera = camera; -} - -void InteractionHandler::setOrigin(SceneGraphNode* node) { - if (node) - _node = node; -} - -Camera * InteractionHandler::getCamera() const { - //assert(this_); - if (_enabled) { - return _camera; - } - return nullptr; -} - -const psc InteractionHandler::getOrigin() const { - if (_node) - return _node->worldPosition(); - return psc(); +void InteractionHandler::addController(Controller* controller) { + assert(controller); + _controllers.push_back(controller); + controller->setHandler(this); } void InteractionHandler::lockControls() { - //assert(this_); - _cameraGuard.lock(); + _mutex.lock(); } void InteractionHandler::unlockControls() { - //assert(this_); - _cameraGuard.unlock(); + _mutex.unlock(); } -void InteractionHandler::setFocusNode(SceneGraphNode *node) { - //assert(this_); - _node = node; +//<<<<<<< HEAD +//void InteractionHandler::addExternalControl(ExternalControl* controller) { +// //assert(this_); +// if (controller != nullptr) { +// _controllers.push_back(controller); +// } +//} +// +//void InteractionHandler::setCamera(Camera *camera) { +// //assert(this_); +// _camera = camera; +//} +// +//void InteractionHandler::setOrigin(SceneGraphNode* node) { +// if (node) +// _node = node; +//} +// +//Camera * InteractionHandler::getCamera() const { +// //assert(this_); +// if (_enabled) { +// return _camera; +// } +// return nullptr; +//} +// +//const psc InteractionHandler::getOrigin() const { +// if (_node) +// return _node->worldPosition(); +// return psc(); +//} +// +//void InteractionHandler::lockControls() { +// //assert(this_); +// _cameraGuard.lock(); +//} +// +//void InteractionHandler::unlockControls() { +// //assert(this_); +// _cameraGuard.unlock(); +//} +// +//void InteractionHandler::setFocusNode(SceneGraphNode *node) { +// //assert(this_); +// _node = node; +//} +// +//void InteractionHandler::rotate(const glm::quat &rotation) { +// //assert(this_); +// lockControls(); +// _camera->rotate(rotation); +// unlockControls(); +//======= +void InteractionHandler::update(double deltaTime) { + _deltaTime = deltaTime; } -void InteractionHandler::rotate(const glm::quat &rotation) { - //assert(this_); +void InteractionHandler::setFocusNode(SceneGraphNode* node) { + _focusNode = node; +} + +const SceneGraphNode* const InteractionHandler::focusNode() const { + return _focusNode; +} + +void InteractionHandler::setCamera(Camera* camera) { + assert(camera); + _camera = camera; +} +const Camera* const InteractionHandler::camera() const { + return _camera; +} + +void InteractionHandler::keyboardCallback(int key, int action) { + if (_keyboardController) { + auto start = ghoul::HighResClock::now(); + _keyboardController->keyPressed(KeyAction(action), Key(key), KeyModifier::None); + auto end = ghoul::HighResClock::now(); + LINFO("Keyboard timing: " << std::chrono::duration_cast(end - start).count() << "ns"); + } +} + +void InteractionHandler::mouseButtonCallback(int button, int action) { + if (_mouseController) + _mouseController->button(MouseAction(action), MouseButton(button)); +} + +void InteractionHandler::mousePositionCallback(int x, int y) { + if (_mouseController) + // TODO Remap screen coordinates to [0,1] + _mouseController->move(float(x), float(y)); +} + +void InteractionHandler::mouseScrollWheelCallback(int pos) { + if (_mouseController) + _mouseController->scrollWheel(float(pos)); +} + +void InteractionHandler::orbitDelta(const glm::quat& rotation) +{ lockControls(); - _camera->rotate(rotation); - unlockControls(); -} -void InteractionHandler::orbit(const glm::quat &rotation) { - //assert(this_); - lockControls(); - // the camera position psc relative = _camera->position(); // should be changed to something more dynamic =) psc origin; - if (_node) { - origin = _node->worldPosition(); + if (_focusNode) { + origin = _focusNode->worldPosition(); } psc relative_origin_coordinate = relative - origin; @@ -477,260 +548,283 @@ void InteractionHandler::orbit(const glm::quat &rotation) { unlockControls(); } -void InteractionHandler::distance(const PowerScaledScalar &dist, size_t iterations) { - if (iterations > 5) - return; - //assert(this_); +//<<<<<<< HEAD +//void InteractionHandler::distance(const PowerScaledScalar &dist, size_t iterations) { +// if (iterations > 5) +// return; +// //assert(this_); +// lockControls(); +// +// psc relative = _camera->position(); +// const psc origin = (_node) ? _node->worldPosition() : psc(); +// +// psc relative_origin_coordinate = relative - origin; +// const glm::vec3 dir(relative_origin_coordinate.direction()); +// glm::vec3 newdir = dir * dist[0]; +//======= +void InteractionHandler::rotateDelta(const glm::quat& rotation) +{ lockControls(); - + _camera->rotate(rotation); + unlockControls(); +} + +void InteractionHandler::distanceDelta(const PowerScaledScalar& distance) +{ + lockControls(); + psc relative = _camera->position(); - const psc origin = (_node) ? _node->worldPosition() : psc(); + const psc origin = (_focusNode) ? _focusNode->worldPosition() : psc(); psc relative_origin_coordinate = relative - origin; const glm::vec3 dir(relative_origin_coordinate.direction()); - glm::vec3 newdir = dir * dist[0]; + glm::vec3 newdir = dir * distance[0]; +//>>>>>>> feature/interactionhandler relative_origin_coordinate = newdir; - relative_origin_coordinate[3] = dist[1]; + relative_origin_coordinate[3] = distance[1]; relative = relative + relative_origin_coordinate; relative_origin_coordinate = relative - origin; newdir = relative_origin_coordinate.direction(); // update only if on the same side of the origin - if (glm::angle(newdir, dir) < 90.0f) { +//<<<<<<< HEAD +// if (glm::angle(newdir, dir) < 90.0f) { +// _camera->setPosition(relative); +// unlockControls(); +// +// } +// else { +// unlockControls(); +// PowerScaledScalar d2 = dist; +// d2[0] *= 0.75f; +// d2[1] *= 0.85f; +// distance(d2, iterations + 1); +// } +// +//} +// +//void InteractionHandler::lookAt(const glm::quat &rotation) { +// //assert(this_); +// lockControls(); +//======= + if (glm::angle(newdir, dir) < 90.0f) _camera->setPosition(relative); - unlockControls(); - - } - else { - unlockControls(); - PowerScaledScalar d2 = dist; - d2[0] *= 0.75f; - d2[1] *= 0.85f; - distance(d2, iterations + 1); - } - -} - -void InteractionHandler::lookAt(const glm::quat &rotation) { - //assert(this_); - lockControls(); +//>>>>>>> feature/interactionhandler unlockControls(); } -void InteractionHandler::setRotation(const glm::quat &rotation) { - //assert(this_); - lockControls(); - - unlockControls(); +void InteractionHandler::lookAt(const glm::quat& rotation) +{ } -void InteractionHandler::update(const double dt) { - //assert(this_); - // setting dt_ for use in callbacks - _dt = dt; - if (_enabled && _camera) { - // fetch data from joysticks - DeviceIdentifier::ref().update(); - - // update all controllers - for (size_t i = 0; i < _controllers.size(); ++i) { - _controllers[i]->update(); - } - } -} - -double InteractionHandler::dt() { - //assert(this_); - return _dt; -} - -glm::vec3 InteractionHandler::mapToTrackball(glm::vec2 mousePos) { - const float RADIUS = 0.5; // Sphere radius - glm::vec3 out = glm::vec3(mousePos.x-0.5, -1.0*(mousePos.y-0.5), 0); - - // Mapping according to Holroyds trackball - // Piece-wise sphere + hyperbolic sheet - if (out.x*out.x + out.y*out.y <= RADIUS*RADIUS/2.0) { - //Spherical Region - out.z = RADIUS*RADIUS - (out.x*out.x + out.y*out.y); - out.z = out.z > 0.0f ? sqrtf(out.z) : 0.0f; - } else { //Hyperbolic Region - for smooth z values - out.z = (RADIUS*RADIUS)/(2.0f*sqrt(out.x*out.x + out.y*out.y)); - } - - return glm::normalize(out); -} - -glm::vec3 InteractionHandler::mapToCamera(glm::vec3 trackballPos) { -// return glm::vec3((sgct::Engine::instance()->getActiveViewMatrix() * glm::vec4(trackballPos,0))); - - //Get x,y,z axis vectors of current camera view - glm::vec3 currentViewYaxis = glm::normalize(_camera->lookUpVector()); - psc viewDir = _camera->position() - _node->worldPosition(); - glm::vec3 currentViewZaxis = glm::normalize(viewDir.vec3()); - glm::vec3 currentViewXaxis = glm::normalize(glm::cross(currentViewYaxis, currentViewZaxis)); - - //mapping to camera co-ordinate - currentViewXaxis*=trackballPos.x; - currentViewYaxis*=trackballPos.y; - currentViewZaxis*=trackballPos.z; - return (currentViewXaxis + currentViewYaxis + currentViewZaxis); -} - -void InteractionHandler::trackballRotate(int x, int y) { - // Normalize mouse coordinates to [0,1] - float width = static_cast(sgct::Engine::instance()->getActiveXResolution()); - float height = static_cast(sgct::Engine::instance()->getActiveYResolution()); - glm::vec2 mousePos = glm::vec2((float)x/width, (float)y/height); - - mousePos = glm::clamp(mousePos, -0.5, 1.5); // Ugly fix #1: Camera position becomes NaN on mouse values outside [-0.5, 1.5] - //mousePos[1] = 0.5; // Ugly fix #2: Tempoarily only allow rotation around y - - glm::vec3 curTrackballPos = mapToTrackball(mousePos); -// LDEBUG(mousePos.x << ", " << mousePos.y << " = " << curTrackballPos.x << ", " << curTrackballPos.y << ", " << curTrackballPos.z); - - // Disable movement on the first click for extra smoothness - if (!_isMouseBeingPressedAndHeld) { - _lastTrackballPos = curTrackballPos; - _isMouseBeingPressedAndHeld = true; - } - - if (curTrackballPos != _lastTrackballPos) { - // calculate rotation angle (in radians) - float rotationAngle = glm::angle(curTrackballPos, _lastTrackballPos); - rotationAngle *= static_cast(dt())*100.0f; - - // Map trackballpos to camera -// glm::vec3 trackballMappedToCamera = mapToCamera(_lastTrackballPos - curTrackballPos); -// psc currentCamPos = camera_->getPosition(); -// glm::vec3 nextCamPos = currentCamPos.getVec3f() + trackballMappedToCamera; -// glm::vec3 rotationAxis = glm::cross(currentCamPos.getVec3f(), nextCamPos); - - glm::vec3 rotationAxis = glm::cross(_lastTrackballPos, curTrackballPos); - rotationAxis = glm::normalize(rotationAxis); - glm::quat quaternion = glm::angleAxis(rotationAngle, rotationAxis); - - // Apply quaternion to camera - orbit(quaternion); - - _lastTrackballPos = curTrackballPos; - } -} - -void InteractionHandler::keyboardCallback(int key, int action) { - // TODO package in script - const float speed = 2.75f; - const float dt = static_cast(_dt); - if (action == SGCT_PRESS || action == SGCT_REPEAT) { - - if (key == SGCT_KEY_S) { - glm::vec3 euler(speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == SGCT_KEY_W) { - glm::vec3 euler(-speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == SGCT_KEY_A) { - glm::vec3 euler(0.0, -speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == SGCT_KEY_D) { - glm::vec3 euler(0.0, speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == SGCT_KEY_Z) { - Time::ref().advanceTime(sgct::Engine::instance()->getDt()); - } - if (key == SGCT_KEY_X) { - Time::ref().retreatTime(sgct::Engine::instance()->getDt()); - } - if (key == 262) { - glm::vec3 euler(0.0, speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 263) { - glm::vec3 euler(0.0, -speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 264) { - glm::vec3 euler(speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 265) { - glm::vec3 euler(-speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == SGCT_KEY_KP_SUBTRACT) { - glm::vec2 s = OsEng.renderEngine().camera()->scaling(); - s[1] -= 0.5f; - OsEng.renderEngine().camera()->setScaling(s); - } - if (key == SGCT_KEY_KP_ADD) { - glm::vec2 s = OsEng.renderEngine().camera()->scaling(); - s[1] += 0.5f; - OsEng.renderEngine().camera()->setScaling(s); - } - - // iterate over key bindings - _validKeyLua = true; - auto ret = _keyLua.equal_range(key); - for (auto it = ret.first; it != ret.second; ++it) { - OsEng.scriptEngine().runScript(it->second); - if (!_validKeyLua) { - break; - } - } - } -} - -void InteractionHandler::mouseButtonCallback(int key, int action) { - //if(mouseControl_ != nullptr) { - // mouseControl_->mouseButtonCallback(key,action); - //} - if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_PRESS) - _leftMouseButtonDown = true; - else if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_RELEASE) { - _leftMouseButtonDown = false; - _isMouseBeingPressedAndHeld = false; - } -} - -void InteractionHandler::mousePositionCallback(int x, int y) { - if (_leftMouseButtonDown) - trackballRotate(x,y); - - //if(mouseControl_ != nullptr) { - // mouseControl_->mousePosCallback(x,y); - //} -} - -void InteractionHandler::mouseScrollWheelCallback(int pos) { - //if(mouseControl_ != nullptr) { - // mouseControl_->mouseScrollCallback(pos); - //} - const float speed = 4.75f; - const float dt = static_cast(_dt); - if(pos < 0) { - PowerScaledScalar dist(speed * dt, 0.0f); - distance(dist); - } else if(pos > 0) { - PowerScaledScalar dist(-speed * dt, 0.0f); - distance(dist); - } -} - - +//<<<<<<< HEAD +//void InteractionHandler::update(const double dt) { +// //assert(this_); +// // setting dt_ for use in callbacks +// _dt = dt; +// if (_enabled && _camera) { +// // fetch data from joysticks +// DeviceIdentifier::ref().update(); +// +// // update all controllers +// for (size_t i = 0; i < _controllers.size(); ++i) { +// _controllers[i]->update(); +// } +// } +//} +// +//double InteractionHandler::dt() { +// //assert(this_); +// return _dt; +//} +// +//glm::vec3 InteractionHandler::mapToTrackball(glm::vec2 mousePos) { +// const float RADIUS = 0.5; // Sphere radius +// glm::vec3 out = glm::vec3(mousePos.x-0.5, -1.0*(mousePos.y-0.5), 0); +// +// // Mapping according to Holroyds trackball +// // Piece-wise sphere + hyperbolic sheet +// if (out.x*out.x + out.y*out.y <= RADIUS*RADIUS/2.0) { +// //Spherical Region +// out.z = RADIUS*RADIUS - (out.x*out.x + out.y*out.y); +// out.z = out.z > 0.0f ? sqrtf(out.z) : 0.0f; +// } else { //Hyperbolic Region - for smooth z values +// out.z = (RADIUS*RADIUS)/(2.0f*sqrt(out.x*out.x + out.y*out.y)); +// } +// +// return glm::normalize(out); +//} +// +//glm::vec3 InteractionHandler::mapToCamera(glm::vec3 trackballPos) { +//// return glm::vec3((sgct::Engine::instance()->getActiveViewMatrix() * glm::vec4(trackballPos,0))); +// +// //Get x,y,z axis vectors of current camera view +// glm::vec3 currentViewYaxis = glm::normalize(_camera->lookUpVector()); +// psc viewDir = _camera->position() - _node->worldPosition(); +// glm::vec3 currentViewZaxis = glm::normalize(viewDir.vec3()); +// glm::vec3 currentViewXaxis = glm::normalize(glm::cross(currentViewYaxis, currentViewZaxis)); +// +// //mapping to camera co-ordinate +// currentViewXaxis*=trackballPos.x; +// currentViewYaxis*=trackballPos.y; +// currentViewZaxis*=trackballPos.z; +// return (currentViewXaxis + currentViewYaxis + currentViewZaxis); +//} +// +//void InteractionHandler::trackballRotate(int x, int y) { +// // Normalize mouse coordinates to [0,1] +// float width = static_cast(sgct::Engine::instance()->getActiveXResolution()); +// float height = static_cast(sgct::Engine::instance()->getActiveYResolution()); +// glm::vec2 mousePos = glm::vec2((float)x/width, (float)y/height); +// +// mousePos = glm::clamp(mousePos, -0.5, 1.5); // Ugly fix #1: Camera position becomes NaN on mouse values outside [-0.5, 1.5] +// //mousePos[1] = 0.5; // Ugly fix #2: Tempoarily only allow rotation around y +// +// glm::vec3 curTrackballPos = mapToTrackball(mousePos); +//// LDEBUG(mousePos.x << ", " << mousePos.y << " = " << curTrackballPos.x << ", " << curTrackballPos.y << ", " << curTrackballPos.z); +// +// // Disable movement on the first click for extra smoothness +// if (!_isMouseBeingPressedAndHeld) { +// _lastTrackballPos = curTrackballPos; +// _isMouseBeingPressedAndHeld = true; +// } +// +// if (curTrackballPos != _lastTrackballPos) { +// // calculate rotation angle (in radians) +// float rotationAngle = glm::angle(curTrackballPos, _lastTrackballPos); +// rotationAngle *= static_cast(dt())*100.0f; +// +// // Map trackballpos to camera +//// glm::vec3 trackballMappedToCamera = mapToCamera(_lastTrackballPos - curTrackballPos); +//// psc currentCamPos = camera_->getPosition(); +//// glm::vec3 nextCamPos = currentCamPos.getVec3f() + trackballMappedToCamera; +//// glm::vec3 rotationAxis = glm::cross(currentCamPos.getVec3f(), nextCamPos); +// +// glm::vec3 rotationAxis = glm::cross(_lastTrackballPos, curTrackballPos); +// rotationAxis = glm::normalize(rotationAxis); +// glm::quat quaternion = glm::angleAxis(rotationAngle, rotationAxis); +// +// // Apply quaternion to camera +// orbit(quaternion); +// +// _lastTrackballPos = curTrackballPos; +// } +//} +// +//void InteractionHandler::keyboardCallback(int key, int action) { +// // TODO package in script +// const float speed = 2.75f; +// const float dt = static_cast(_dt); +// if (action == SGCT_PRESS || action == SGCT_REPEAT) { +// +// if (key == SGCT_KEY_S) { +// glm::vec3 euler(speed * dt, 0.0, 0.0); +// glm::quat rot = glm::quat(euler); +// orbit(rot); +// } +// if (key == SGCT_KEY_W) { +// glm::vec3 euler(-speed * dt, 0.0, 0.0); +// glm::quat rot = glm::quat(euler); +// orbit(rot); +// } +// if (key == SGCT_KEY_A) { +// glm::vec3 euler(0.0, -speed * dt, 0.0); +// glm::quat rot = glm::quat(euler); +// orbit(rot); +// } +// if (key == SGCT_KEY_D) { +// glm::vec3 euler(0.0, speed * dt, 0.0); +// glm::quat rot = glm::quat(euler); +// orbit(rot); +// } +// if (key == SGCT_KEY_Z) { +// Time::ref().advanceTime(sgct::Engine::instance()->getDt()); +// } +// if (key == SGCT_KEY_X) { +// Time::ref().retreatTime(sgct::Engine::instance()->getDt()); +// } +// if (key == 262) { +// glm::vec3 euler(0.0, speed * dt, 0.0); +// glm::quat rot = glm::quat(euler); +// rotate(rot); +// } +// if (key == 263) { +// glm::vec3 euler(0.0, -speed * dt, 0.0); +// glm::quat rot = glm::quat(euler); +// rotate(rot); +// } +// if (key == 264) { +// glm::vec3 euler(speed * dt, 0.0, 0.0); +// glm::quat rot = glm::quat(euler); +// rotate(rot); +// } +// if (key == 265) { +// glm::vec3 euler(-speed * dt, 0.0, 0.0); +// glm::quat rot = glm::quat(euler); +// rotate(rot); +// } +// if (key == SGCT_KEY_KP_SUBTRACT) { +// glm::vec2 s = OsEng.renderEngine().camera()->scaling(); +// s[1] -= 0.5f; +// OsEng.renderEngine().camera()->setScaling(s); +// } +// if (key == SGCT_KEY_KP_ADD) { +// glm::vec2 s = OsEng.renderEngine().camera()->scaling(); +// s[1] += 0.5f; +// OsEng.renderEngine().camera()->setScaling(s); +// } +// +// // iterate over key bindings +// _validKeyLua = true; +// auto ret = _keyLua.equal_range(key); +// for (auto it = ret.first; it != ret.second; ++it) { +// OsEng.scriptEngine().runScript(it->second); +// if (!_validKeyLua) { +// break; +// } +// } +// } +//} +// +//void InteractionHandler::mouseButtonCallback(int key, int action) { +// //if(mouseControl_ != nullptr) { +// // mouseControl_->mouseButtonCallback(key,action); +// //} +// if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_PRESS) +// _leftMouseButtonDown = true; +// else if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_RELEASE) { +// _leftMouseButtonDown = false; +// _isMouseBeingPressedAndHeld = false; +// } +//} +// +//void InteractionHandler::mousePositionCallback(int x, int y) { +// if (_leftMouseButtonDown) +// trackballRotate(x,y); +// +// //if(mouseControl_ != nullptr) { +// // mouseControl_->mousePosCallback(x,y); +// //} +//} +// +//void InteractionHandler::mouseScrollWheelCallback(int pos) { +// //if(mouseControl_ != nullptr) { +// // mouseControl_->mouseScrollCallback(pos); +// //} +// const float speed = 4.75f; +// const float dt = static_cast(_dt); +// if(pos < 0) { +// PowerScaledScalar dist(speed * dt, 0.0f); +// distance(dist); +// } else if(pos > 0) { +// PowerScaledScalar dist(-speed * dt, 0.0f); +// distance(dist); +// } +//} +// +// void InteractionHandler::resetKeyBindings() { _keyLua.clear(); _validKeyLua = false; @@ -773,4 +867,472 @@ scripting::ScriptEngine::LuaLibrary InteractionHandler::luaLibrary() { }; } +//======= +void InteractionHandler::setRotation(const glm::quat& rotation) +{ +} + +double InteractionHandler::deltaTime() const { + return _deltaTime; +} + +} // namespace interaction +//>>>>>>> feature/interactionhandler } // namespace openspace + +// +//// open space includes +//#include +//#include +//#include +////#include +////#include +//#include +//#include +//#include +//#include +// +//#include +// +//#include +// +//namespace { +// const std::string _loggerCat = "InteractionHandler"; +//} +// +//namespace openspace { +//namespace interaction { +// +//InteractionHandler::InteractionHandler() +// : _camera(nullptr) +// , _node(nullptr) +// , _dt(0.0) +// , _lastTrackballPos(0.f) +// , _leftMouseButtonDown(false) +// , _isMouseBeingPressedAndHeld(false) +//{ +//} +// +//InteractionHandler::~InteractionHandler() { +// //for (size_t i = 0; i < _controllers.size(); ++i) { +// // delete _controllers[i]; +// //} +//} +// +////void InteractionHandler::init() { +//// assert( ! this_); +//// this_ = new InteractionHandler(); +////} +//// +////void InteractionHandler::deinit() { +//// assert(this_); +//// delete this_; +//// this_ = nullptr; +////} +//// +////InteractionHandler& InteractionHandler::ref() { +//// assert(this_); +//// return *this_; +////} +// +////bool InteractionHandler::isInitialized() { +//// return this_ != nullptr; +////} +// +////void InteractionHandler::connectDevices() { +//// //assert(this_); +//// assert(DeviceIdentifier::ref().isInitialized()); +//// +//// // for each device found +//// for(int i = 0; i < DeviceIdentifier::ref().numberOfDevices(); ++i) { +//// +//// // TODO +//// //if(DeviceIdentifier::ref().type(i) == InputDevice::XBOX) { +//// +//// // // found xbox, use xbox python controller +//// // JoystickExternalControl *joystickexcontrol = new JoystickExternalControl(RELATIVE_PATH"pyinput/Xbox.py"); +//// // joystickexcontrol->setInputDevice(i); +//// // addExternalControl(joystickexcontrol); +//// +//// //} else if(DeviceIdentifier::ref().type(i) == InputDevice::SPACENAVIGATOR) { +//// +//// // // found SpaceNavigator, use SpaceNavigator python controller +//// // JoystickExternalControl *joystickexcontrol = new JoystickExternalControl(RELATIVE_PATH"pyinput/SpaceNavigator.py"); +//// // joystickexcontrol->setInputDevice(i); +//// // addExternalControl(joystickexcontrol); +//// //} +//// +//// } +////} +//// +////void InteractionHandler::addExternalControl(ExternalControl* controller) { +//// //assert(this_); +//// if (controller != nullptr) { +//// _controllers.push_back(controller); +//// } +////} +// +//void InteractionHandler::setCamera(Camera *camera) { +// //assert(this_); +// _camera = camera; +//} +// +//Camera * InteractionHandler::getCamera() const { +// return _camera; +//} +// +//const psc InteractionHandler::getOrigin() const { +// if(_node) +// return _node->worldPosition(); +// return psc(); +//} +// +//void InteractionHandler::lockControls() { +// //assert(this_); +// _cameraGuard.lock(); +//} +// +//void InteractionHandler::unlockControls() { +// //assert(this_); +// _cameraGuard.unlock(); +//} +// +//void InteractionHandler::setFocusNode(SceneGraphNode *node) { +// //assert(this_); +// _node = node; +//} +// +//void InteractionHandler::rotate(const glm::quat &rotation) { +// //assert(this_); +// lockControls(); +// _camera->rotate(rotation); +// unlockControls(); +//} +// +//void InteractionHandler::orbit(const glm::quat &rotation) { +// //assert(this_); +// lockControls(); +// +// // the camera position +// psc relative = _camera->position(); +// +// // should be changed to something more dynamic =) +// psc origin; +// if (_node) { +// origin = _node->worldPosition(); +// } +// +// psc relative_origin_coordinate = relative - origin; +// //glm::mat4 rotation_matrix = glm::mat4_cast(glm::inverse(rotation)); +// //relative_origin_coordinate = relative_origin_coordinate.vec4() * glm::inverse(rotation); +// relative_origin_coordinate = glm::inverse(rotation) * relative_origin_coordinate.vec4(); +// relative = relative_origin_coordinate + origin; +// +// _camera->setPosition(relative); +// //camera_->rotate(rotation); +// //camera_->setRotation(glm::mat4_cast(rotation)); +// +// glm::mat4 la = glm::lookAt(_camera->position().vec3(), origin.vec3(), glm::rotate(rotation, _camera->lookUpVector())); +// _camera->setRotation(la); +// //camera_->setLookUpVector(); +// +// unlockControls(); +//} +// +//void InteractionHandler::distance(const PowerScaledScalar &distance) { +// //assert(this_); +// lockControls(); +// +// psc relative = _camera->position(); +// const psc origin = (_node) ? _node->worldPosition() : psc(); +// +// psc relative_origin_coordinate = relative - origin; +// const glm::vec3 dir(relative_origin_coordinate.direction()); +// glm:: vec3 newdir = dir * distance[0]; +// relative_origin_coordinate = newdir; +// relative_origin_coordinate[3] = distance[1]; +// relative = relative + relative_origin_coordinate; +// +// relative_origin_coordinate = relative - origin; +// newdir = relative_origin_coordinate.direction(); +// +// // update only if on the same side of the origin +// if(glm::angle(newdir, dir) < 90.0f) +// _camera->setPosition(relative); +// +// unlockControls(); +//} +// +//void InteractionHandler::lookAt(const glm::quat &rotation) { +// //assert(this_); +// lockControls(); +// +// unlockControls(); +//} +// +//void InteractionHandler::setRotation(const glm::quat &rotation) { +// //assert(this_); +// lockControls(); +// +// unlockControls(); +//} +// +//void InteractionHandler::update(const double dt) { +// //assert(this_); +// // setting dt_ for use in callbacks +// _dt = dt; +// if (_camera) { +// // fetch data from joysticks +// DeviceIdentifier::ref().update(); +// +// //// update all controllers +// //for (size_t i = 0; i < _controllers.size(); ++i) { +// // _controllers[i]->update(); +// //} +// } +//} +// +//double InteractionHandler::getDt() { +// //assert(this_); +// return _dt; +//} +// +//glm::vec3 InteractionHandler::mapToTrackball(glm::vec2 mousePos) { +// const float RADIUS = 0.5; // Sphere radius +// glm::vec3 out = glm::vec3(mousePos.x-0.5, -1.0*(mousePos.y-0.5), 0); +// +// // Mapping according to Holroyds trackball +// // Piece-wise sphere + hyperbolic sheet +// if (out.x*out.x + out.y*out.y <= RADIUS*RADIUS/2.0) { +// //Spherical Region +// out.z = RADIUS*RADIUS - (out.x*out.x + out.y*out.y); +// out.z = out.z > 0.0 ? sqrtf(out.z) : 0.0; +// } else { //Hyperbolic Region - for smooth z values +// out.z = (RADIUS*RADIUS)/(2.0*sqrt(out.x*out.x + out.y*out.y)); +// } +// +// return glm::normalize(out); +//} +// +//glm::vec3 InteractionHandler::mapToCamera(glm::vec3 trackballPos) { +//// return glm::vec3((sgct::Engine::instance()->getActiveViewMatrix() * glm::vec4(trackballPos,0))); +// +// //Get x,y,z axis vectors of current camera view +// glm::vec3 currentViewYaxis = glm::normalize(_camera->lookUpVector()); +// psc viewDir = _camera->position() - _node->worldPosition(); +// glm::vec3 currentViewZaxis = glm::normalize(viewDir.vec3()); +// glm::vec3 currentViewXaxis = glm::normalize(glm::cross(currentViewYaxis, currentViewZaxis)); +// +// //mapping to camera co-ordinate +// currentViewXaxis*=trackballPos.x; +// currentViewYaxis*=trackballPos.y; +// currentViewZaxis*=trackballPos.z; +// return (currentViewXaxis + currentViewYaxis + currentViewZaxis); +//} +// +//void InteractionHandler::trackballRotate(int x, int y) { +// // Normalize mouse coordinates to [0,1] +// float width = sgct::Engine::instance()->getActiveXResolution(); +// float height = sgct::Engine::instance()->getActiveYResolution(); +// glm::vec2 mousePos = glm::vec2((float)x/width, (float)y/height); +// +// mousePos = glm::clamp(mousePos, -0.5, 1.5); // Ugly fix #1: Camera position becomes NaN on mouse values outside [-0.5, 1.5] +// //mousePos[1] = 0.5; // Ugly fix #2: Tempoarily only allow rotation around y +// +// glm::vec3 curTrackballPos = mapToTrackball(mousePos); +//// LDEBUG(mousePos.x << ", " << mousePos.y << " = " << curTrackballPos.x << ", " << curTrackballPos.y << ", " << curTrackballPos.z); +// +// // Disable movement on the first click for extra smoothness +// if (!_isMouseBeingPressedAndHeld) { +// _lastTrackballPos = curTrackballPos; +// _isMouseBeingPressedAndHeld = true; +// } +// +// if (curTrackballPos != _lastTrackballPos) { +// // calculate rotation angle (in radians) +// float rotationAngle = glm::angle(curTrackballPos, _lastTrackballPos); +// rotationAngle *= getDt()*100.0f; +// +// // Map trackballpos to camera +//// glm::vec3 trackballMappedToCamera = mapToCamera(_lastTrackballPos - curTrackballPos); +//// psc currentCamPos = camera_->getPosition(); +//// glm::vec3 nextCamPos = currentCamPos.getVec3f() + trackballMappedToCamera; +//// glm::vec3 rotationAxis = glm::cross(currentCamPos.getVec3f(), nextCamPos); +// +// glm::vec3 rotationAxis = glm::cross(_lastTrackballPos, curTrackballPos); +// rotationAxis = glm::normalize(rotationAxis); +// glm::quat quaternion = glm::angleAxis(rotationAngle, rotationAxis); +// +// // Apply quaternion to camera +// orbit(quaternion); +// +// _lastTrackballPos = curTrackballPos; +// } +//} +//double acc = 1; +// +//void InteractionHandler::keyboardCallback(int key, int action) { +// // TODO package in script +// const double speed = 2.75; +// const double dt = getDt(); +// if(action == SGCT_PRESS || action == SGCT_REPEAT) { +// if (key == SGCT_KEY_S) { +// glm::vec3 euler(speed * dt, 0.0, 0.0); +// glm::quat rot = glm::quat(euler); +// orbit(rot); +// } +// if (key == SGCT_KEY_W) { +// glm::vec3 euler(-speed * dt, 0.0, 0.0); +// glm::quat rot = glm::quat(euler); +// orbit(rot); +// } +// if (key == SGCT_KEY_A) { +// glm::vec3 euler(0.0, -speed * dt, 0.0); +// glm::quat rot = glm::quat(euler); +// orbit(rot); +// } +// if (key == SGCT_KEY_D) { +// glm::vec3 euler(0.0, speed * dt, 0.0); +// glm::quat rot = glm::quat(euler); +// orbit(rot); +// } +// if (key == SGCT_KEY_Q) { +// Time::ref().advanceTime(dt); +// } +// if (key == 262) { +// glm::vec3 euler(0.0, speed * dt, 0.0); +// glm::quat rot = glm::quat(euler); +// rotate(rot); +// } +// if (key == 263) { +// glm::vec3 euler(0.0, -speed * dt, 0.0); +// glm::quat rot = glm::quat(euler); +// rotate(rot); +// } +// if (key == 264) { +// glm::vec3 euler(speed * dt, 0.0, 0.0); +// glm::quat rot = glm::quat(euler); +// rotate(rot); +// } +// if (key == 265) { +// glm::vec3 euler(-speed * dt, 0.0, 0.0); +// glm::quat rot = glm::quat(euler); +// rotate(rot); +// } +// if (key == SGCT_KEY_R) { +// PowerScaledScalar dist(-speed * dt, 0.0); +// distance(dist); +// } +// if (key == SGCT_KEY_F) { +// PowerScaledScalar dist(speed * dt, 0.0); +// distance(dist); +// } +// if (key == SGCT_KEY_T) { +// PowerScaledScalar dist(-speed * pow(10, 11) * dt, 0.0); +// distance(dist); +// } +// if (key == SGCT_KEY_G) { +// acc += 0.001; +// PowerScaledScalar dist(speed * pow(10, 8 * acc) * dt, 0.0); +// distance(dist); +// } +// if (key == SGCT_KEY_Y) { +// PowerScaledScalar dist(-speed * 100.0 * dt, 6.0); +// distance(dist); +// } +// if (key == SGCT_KEY_H) { +// PowerScaledScalar dist(speed * 100.0 * dt, 6.0); +// distance(dist); +// } +// +// if (key == SGCT_KEY_KP_SUBTRACT) { +// glm::vec2 s = OsEng.renderEngine().camera()->scaling(); +// s[1] -= 0.5; +// OsEng.renderEngine().camera()->setScaling(s); +// } +// if (key == SGCT_KEY_KP_ADD) { +// glm::vec2 s = OsEng.renderEngine().camera()->scaling(); +// s[1] += 0.5; +// OsEng.renderEngine().camera()->setScaling(s); +// } +// } +// /* +// if (key == '1') { +// SceneGraphNode* node = getSceneGraphNode("sun"); +// +// setFocusNode(node); +// getCamera()->setPosition(node->getWorldPosition() + psc(0.0, 0.0, 0.5, 10.0)); +// getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0)); +// } +// +// if (key == '2') { +// SceneGraphNode* node = getSceneGraphNode("earth"); +// +// setFocusNode(node); +// getCamera()->setPosition(node->getWorldPosition() + psc(0.0, 0.0, 1.0, 8.0)); +// getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0)); +// } +// +// +// if (key == '3') { +// SceneGraphNode* node = getSceneGraphNode("moon"); +// +// setFocusNode(node); +// getCamera()->setPosition(node->getWorldPosition() + psc(0.0, 0.0, 0.5, 8.0)); +// getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0)); +// } +//*/ +// // std::pair >::iterator, std::multimap >::iterator> ret; +// if(action == SGCT_PRESS) { +// auto ret = _keyCallbacks.equal_range(key); +// for (auto it=ret.first; it!=ret.second; ++it) +// it->second(); +// } +// +// +//} +// +//void InteractionHandler::mouseButtonCallback(int key, int action) { +// //if(mouseControl_ != nullptr) { +// // mouseControl_->mouseButtonCallback(key,action); +// //} +// if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_PRESS) +// _leftMouseButtonDown = true; +// else if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_RELEASE) { +// _leftMouseButtonDown = false; +// _isMouseBeingPressedAndHeld = false; +// } +//} +// +//void InteractionHandler::mousePositionCallback(int x, int y) { +// if (_leftMouseButtonDown) +// trackballRotate(x,y); +// +// //if(mouseControl_ != nullptr) { +// // mouseControl_->mousePosCallback(x,y); +// //} +//} +// +//void InteractionHandler::mouseScrollWheelCallback(int pos) { +// //if(mouseControl_ != nullptr) { +// // mouseControl_->mouseScrollCallback(pos); +// //} +// const double speed = 4.75; +// const double dt = getDt(); +// if(pos < 0) { +// PowerScaledScalar dist(speed * dt, 0.0); +// distance(dist); +// } else if(pos > 0) { +// PowerScaledScalar dist(-speed * dt, 0.0); +// distance(dist); +// } +//} +// +////void InteractionHandler::addKeyCallback(int key, std::function f) { +//// //std::map > > _keyCallbacks; +//// +//// _keyCallbacks.insert(std::make_pair(key, f)); +////} +// +//} // namespace interaction +//} // namespace openspace diff --git a/src/interaction/keyboardcontroller.cpp b/src/interaction/keyboardcontroller.cpp new file mode 100644 index 0000000000..e3788d7a77 --- /dev/null +++ b/src/interaction/keyboardcontroller.cpp @@ -0,0 +1,322 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +#include +#include +#include +#include + +namespace openspace { +namespace interaction { + +void KeyboardControllerFixed::keyPressed(KeyAction action, Key key, KeyModifier modifier) { + // TODO package in script + const double speed = 2.75; + const double dt = _handler->deltaTime(); + if(action == KeyAction::Press|| action == KeyAction::Repeat) { + if (key == Key::S) { + glm::vec3 euler(speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + _handler->orbitDelta(rot); + } + if (key == Key::W) { + glm::vec3 euler(-speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + _handler->orbitDelta(rot); + } + if (key == Key::A) { + glm::vec3 euler(0.0, -speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + _handler->orbitDelta(rot); + } + if (key == Key::D) { + glm::vec3 euler(0.0, speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + _handler->orbitDelta(rot); + } + if (key == Key::Q) { + Time::ref().advanceTime(dt); + } + if (key == Key::Right) { + glm::vec3 euler(0.0, speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + _handler->rotateDelta(rot); + } + if (key == Key::Left) { + glm::vec3 euler(0.0, -speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + _handler->rotateDelta(rot); + } + if (key == Key::Down) { + glm::vec3 euler(speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + _handler->rotateDelta(rot); + } + if (key == Key::Up) { + glm::vec3 euler(-speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + _handler->rotateDelta(rot); + } + if (key == Key::R) { + PowerScaledScalar dist(-speed * dt, 0.0); + _handler->distanceDelta(dist); + } + if (key == Key::F) { + PowerScaledScalar dist(speed * dt, 0.0); + _handler->distanceDelta(dist); + } + if (key == Key::T) { + PowerScaledScalar dist(-speed * pow(10, 11) * dt, 0.0); + _handler->distanceDelta(dist); + } + //if (key == Keys::G) { + // acc += 0.001; + // PowerScaledScalar dist(speed * pow(10, 8 * acc) * dt, 0.0); + // distanceDelta(dist); + //} + if (key == Key::Y) { + PowerScaledScalar dist(-speed * 100.0 * dt, 6.0); + _handler->distanceDelta(dist); + } + if (key == Key::H) { + PowerScaledScalar dist(speed * 100.0 * dt, 6.0); + _handler->distanceDelta(dist); + } + + if (key == Key::KeypadSubtract) { + glm::vec2 s = OsEng.renderEngine().camera()->scaling(); + s[1] -= 0.5; + OsEng.renderEngine().camera()->setScaling(s); + } + if (key == Key::KeypadAdd) { + glm::vec2 s = OsEng.renderEngine().camera()->scaling(); + s[1] += 0.5; + OsEng.renderEngine().camera()->setScaling(s); + } + } + /* + if (key == '1') { + SceneGraphNode* node = getSceneGraphNode("sun"); + + setFocusNode(node); + getCamera()->setPosition(node->getWorldPosition() + psc(0.0, 0.0, 0.5, 10.0)); + getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0)); + } + + if (key == '2') { + SceneGraphNode* node = getSceneGraphNode("earth"); + + setFocusNode(node); + getCamera()->setPosition(node->getWorldPosition() + psc(0.0, 0.0, 1.0, 8.0)); + getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0)); + } + + + if (key == '3') { + SceneGraphNode* node = getSceneGraphNode("moon"); + + setFocusNode(node); + getCamera()->setPosition(node->getWorldPosition() + psc(0.0, 0.0, 0.5, 8.0)); + getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0)); + } + */ +} + +void KeyboardControllerLua::keyPressed(KeyAction action, Key key, KeyModifier modifier) { + std::string _loggerCat = "KeyboardControllerLua"; + + lua_State* s = luaL_newstate(); + luaL_openlibs(s); + + int status = luaL_loadfile(s, absPath("${SCRIPTS}/default_keybinding.lua").c_str()); + if (status != LUA_OK) { + LERROR("Error loading script: '" << lua_tostring(s, -1) << "'"); + return; + } + + if (lua_pcall(s, 0, LUA_MULTRET, 0)) { + LERROR("Error executing script: " << lua_tostring(s, -1)); + return; + } + + auto start = ghoul::HighResClock::now(); + + lua_getfield(s, -1, keyToString(key, modifier).c_str()); + if (!lua_isnil(s, -1)) + lua_pcall(s, 0, 0, 0); + else + LINFO("Key not found"); + + auto end = ghoul::HighResClock::now(); + LINFO("Keyboard timing: " << std::chrono::duration_cast(end - start).count() << "ns"); + + +} + +std::string KeyboardControllerLua::keyToString(Key key, KeyModifier mod) const { + std::string result = ""; + int intMod = static_cast(mod); + if (intMod & static_cast(KeyModifier::Control)) + result += "CTRL + "; + if (intMod & static_cast(KeyModifier::Super)) + result += "SUPER + "; + if (intMod & static_cast(KeyModifier::Alt)) + result += "ALT + "; + if (intMod & static_cast(KeyModifier::Shift)) + result += "SHIFT + "; + + switch (key) { + case Key::Unknown: result += "Unknown"; break; + case Key::Space: result += "Space"; break; + case Key::Apostrophe: result += "Apostrophe"; break; + case Key::Comma: result += "Comma"; break; + case Key::Minus: result += "Minus"; break; + case Key::Period: result += "Period"; break; + case Key::Slash: result += "Slash"; break; + case Key::Num0: result += "0"; break; + case Key::Num1: result += "1"; break; + case Key::Num2: result += "2"; break; + case Key::Num3: result += "3"; break; + case Key::Num4: result += "4"; break; + case Key::Num5: result += "5"; break; + case Key::Num6: result += "6"; break; + case Key::Num7: result += "7"; break; + case Key::Num8: result += "8"; break; + case Key::Num9: result += "9"; break; + case Key::SemiColon: result += "SemiColon"; break; + case Key::Equal: result += "Equal"; break; + case Key::A: result += "A"; break; + case Key::B: result += "B"; break; + case Key::C: result += "C"; break; + case Key::D: result += "D"; break; + case Key::E: result += "E"; break; + case Key::F: result += "F"; break; + case Key::G: result += "G"; break; + case Key::H: result += "H"; break; + case Key::I: result += "I"; break; + case Key::J: result += "J"; break; + case Key::K: result += "K"; break; + case Key::L: result += "L"; break; + case Key::M: result += "M"; break; + case Key::N: result += "N"; break; + case Key::O: result += "O"; break; + case Key::P: result += "P"; break; + case Key::Q: result += "Q"; break; + case Key::R: result += "R"; break; + case Key::S: result += "S"; break; + case Key::T: result += "T"; break; + case Key::U: result += "U"; break; + case Key::V: result += "V"; break; + case Key::W: result += "W"; break; + case Key::X: result += "X"; break; + case Key::Y: result += "Y"; break; + case Key::Z: result += "Z"; break; + case Key::LeftBracket: result += "LeftBracket"; break; + case Key::BackSlash: result += "BackSlash"; break; + case Key::RightBracket: result += "RightBracket"; break; + case Key::GraveAccent: result += "GraveAccent"; break; + case Key::World1: result += "World1"; break; + case Key::World2: result += "World2"; break; + case Key::Escape: result += "Escape"; break; + case Key::Enter: result += "Enter"; break; + case Key::Tab: result += "Tab"; break; + case Key::BackSpace: result += "BackSpace"; break; + case Key::Insert: result += "Insert"; break; + case Key::Delete: result += "Delete"; break; + case Key::Right: result += "Right"; break; + case Key::Left: result += "Left"; break; + case Key::Down: result += "Down"; break; + case Key::Up: result += "Up"; break; + case Key::PageUp: result += "PageUp"; break; + case Key::PageDown: result += "PageDown"; break; + case Key::Home: result += "Home"; break; + case Key::End: result += "End"; break; + case Key::CapsLock: result += "CapsLock"; break; + case Key::ScrollLock: result += "ScrollLock"; break; + case Key::NumLock: result += "NumLock"; break; + case Key::PrintScreen: result += "PrintScreen"; break; + case Key::Pause: result += "Pause"; break; + case Key::F1: result += "F1"; break; + case Key::F2: result += "F2"; break; + case Key::F3: result += "F3"; break; + case Key::F4: result += "F4"; break; + case Key::F5: result += "F5"; break; + case Key::F6: result += "F6"; break; + case Key::F7: result += "F7"; break; + case Key::F8: result += "F8"; break; + case Key::F9: result += "F9"; break; + case Key::F10: result += "F10"; break; + case Key::F11: result += "F11"; break; + case Key::F12: result += "F12"; break; + case Key::F13: result += "F13"; break; + case Key::F14: result += "F14"; break; + case Key::F15: result += "F15"; break; + case Key::F16: result += "F16"; break; + case Key::F17: result += "F17"; break; + case Key::F18: result += "F18"; break; + case Key::F19: result += "F19"; break; + case Key::F20: result += "F20"; break; + case Key::F21: result += "F21"; break; + case Key::F22: result += "F22"; break; + case Key::F23: result += "F23"; break; + case Key::F24: result += "F24"; break; + case Key::F25: result += "F25"; break; + case Key::Keypad0: result += "Keypad0"; break; + case Key::Keypad1: result += "Keypad1"; break; + case Key::Keypad2: result += "Keypad2"; break; + case Key::Keypad3: result += "Keypad3"; break; + case Key::Keypad4: result += "Keypad4"; break; + case Key::Keypad5: result += "Keypad5"; break; + case Key::Keypad6: result += "Keypad6"; break; + case Key::Keypad7: result += "Keypad7"; break; + case Key::Keypad8: result += "Keypad8"; break; + case Key::Keypad9: result += "Keypad9"; break; + case Key::KeypadDecimal: result += "KeypadDecimal"; break; + case Key::KeypadDivide: result += "KeypadDivide"; break; + case Key::KeypadMultiply: result += "KeypadMultiply"; break; + case Key::KeypadSubtract: result += "KeypadSubtract"; break; + case Key::KeypadAdd: result += "KeypadAdd"; break; + case Key::KeypadEnter: result += "KeypadEnter"; break; + case Key::LeftShift: result += "LeftShift"; break; + case Key::LeftControl: result += "LeftControl"; break; + case Key::LeftAlt: result += "LeftAlt"; break; + case Key::LeftSuper: result += "LeftSuper"; break; + case Key::RightShift: result += "RightShift"; break; + case Key::RightControl: result += "RightControl"; break; + case Key::RightAlt: result += "RightAlt"; break; + case Key::RightSuper: result += "RightSuper"; break; + case Key::Menu: result += "Menu"; break; + default: + assert(false); + } + return std::move(result); +} + +} // namespace interaction +} // namespace openspace \ No newline at end of file diff --git a/src/interaction/mousecontroller.cpp b/src/interaction/mousecontroller.cpp new file mode 100644 index 0000000000..9d089f4d15 --- /dev/null +++ b/src/interaction/mousecontroller.cpp @@ -0,0 +1,145 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +namespace openspace { +namespace interaction { + +MouseController::MouseController() + : _lastTrackballPos(0.f) + , _isMouseBeingPressedAndHeld(false) +{} + +glm::vec3 MouseController::mapToTrackball(glm::vec2 mousePos) { + const float RADIUS = 0.5; // Sphere radius + glm::vec3 out = glm::vec3(mousePos.x - 0.5, -1.0*(mousePos.y - 0.5), 0); + + // Mapping according to Holroyds trackball + // Piece-wise sphere + hyperbolic sheet + if (out.x*out.x + out.y*out.y <= RADIUS*RADIUS / 2.0) { + //Spherical Region + out.z = RADIUS*RADIUS - (out.x*out.x + out.y*out.y); + out.z = out.z > 0.0 ? sqrtf(out.z) : 0.0; + } + else { //Hyperbolic Region - for smooth z values + out.z = (RADIUS*RADIUS) / (2.0*sqrt(out.x*out.x + out.y*out.y)); + } + + return glm::normalize(out); +} + +glm::vec3 MouseController::mapToCamera(glm::vec3 trackballPos) { + // return glm::vec3((sgct::Engine::instance()->getActiveViewMatrix() * glm::vec4(trackballPos,0))); + + //Get x,y,z axis vectors of current camera view + glm::vec3 currentViewYaxis = glm::normalize(_handler->camera()->lookUpVector()); + psc viewDir = _handler->camera()->position() - _handler->focusNode()->worldPosition(); + glm::vec3 currentViewZaxis = glm::normalize(viewDir.vec3()); + glm::vec3 currentViewXaxis = glm::normalize(glm::cross(currentViewYaxis, currentViewZaxis)); + + //mapping to camera co-ordinate + currentViewXaxis *= trackballPos.x; + currentViewYaxis *= trackballPos.y; + currentViewZaxis *= trackballPos.z; + return (currentViewXaxis + currentViewYaxis + currentViewZaxis); +} + +void MouseController::trackballRotate(int x, int y) { + // Normalize mouse coordinates to [0,1] + float width = sgct::Engine::instance()->getActiveXResolution(); + float height = sgct::Engine::instance()->getActiveYResolution(); + glm::vec2 mousePos = glm::vec2((float)x / width, (float)y / height); + + mousePos = glm::clamp(mousePos, -0.5, 1.5); // Ugly fix #1: Camera position becomes NaN on mouse values outside [-0.5, 1.5] + //mousePos[1] = 0.5; // Ugly fix #2: Tempoarily only allow rotation around y + + glm::vec3 curTrackballPos = mapToTrackball(mousePos); + // LDEBUG(mousePos.x << ", " << mousePos.y << " = " << curTrackballPos.x << ", " << curTrackballPos.y << ", " << curTrackballPos.z); + + // Disable movement on the first click for extra smoothness + if (!_isMouseBeingPressedAndHeld) { + _lastTrackballPos = curTrackballPos; + _isMouseBeingPressedAndHeld = true; + } + + if (curTrackballPos != _lastTrackballPos) { + // calculate rotation angle (in radians) + float rotationAngle = glm::angle(curTrackballPos, _lastTrackballPos); + rotationAngle *= _handler->deltaTime() * 100.0f; + + // Map trackballpos to camera + // glm::vec3 trackballMappedToCamera = mapToCamera(_lastTrackballPos - curTrackballPos); + // psc currentCamPos = camera_->getPosition(); + // glm::vec3 nextCamPos = currentCamPos.getVec3f() + trackballMappedToCamera; + // glm::vec3 rotationAxis = glm::cross(currentCamPos.getVec3f(), nextCamPos); + + glm::vec3 rotationAxis = glm::cross(_lastTrackballPos, curTrackballPos); + rotationAxis = glm::normalize(rotationAxis); + glm::quat quaternion = glm::angleAxis(rotationAngle, rotationAxis); + + // Apply quaternion to camera + _handler->orbitDelta(quaternion); + + _lastTrackballPos = curTrackballPos; + } +} + + +TrackballMouseController::TrackballMouseController() + : MouseController() + , _leftMouseButtonDown(false) +{} + +void TrackballMouseController::button(MouseAction action, MouseButton button) { + if (button == MouseButton::Left && action == MouseAction::Press) + _leftMouseButtonDown = true; + else if (button == MouseButton::Left && action == MouseAction::Release) { + _leftMouseButtonDown = false; + _isMouseBeingPressedAndHeld = false; + } +} + +void TrackballMouseController::move(float x, float y) { + if (_leftMouseButtonDown) + trackballRotate(x, y); +} + +void TrackballMouseController::scrollWheel(int pos) { + const double speed = 4.75; + const double dt = _handler->deltaTime(); + if (pos < 0) { + PowerScaledScalar dist(speed * dt, 0.0); + _handler->distanceDelta(dist); + } + else if (pos > 0) { + PowerScaledScalar dist(-speed * dt, 0.0); + _handler->distanceDelta(dist); + } +} + +} // namespace interaction +} // namespace openspace diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 159ba0c133..c8b84941c3 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -332,7 +332,7 @@ void RenderEngine::render() const glm::vec2 scaling = _mainCamera->scaling(); const glm::vec3 viewdirection = _mainCamera->viewDirection(); const psc position = _mainCamera->position(); - const psc origin = OsEng.interactionHandler().getOrigin(); + const psc origin = OsEng.interactionHandler().focusNode()->worldPosition(); const PowerScaledScalar pssl = (position - origin).length(); // GUI PRINT diff --git a/src/scenegraph/scenegraphnode.cpp b/src/scenegraph/scenegraphnode.cpp index b53f88957e..4b4e3c46bd 100644 --- a/src/scenegraph/scenegraphnode.cpp +++ b/src/scenegraph/scenegraphnode.cpp @@ -284,9 +284,6 @@ const std::vector& SceneGraphNode::children() const{ PowerScaledScalar SceneGraphNode::calculateBoundingSphere(){ // set the bounding sphere to 0.0 _boundingSphere = 0.0; - _boundingSphere = 1000.0; - _boundingSphere = 0.0; - if (_children.size() > 0) { // node PowerScaledScalar maxChild; @@ -296,8 +293,9 @@ PowerScaledScalar SceneGraphNode::calculateBoundingSphere(){ for (size_t i = 0; i < _children.size(); ++i) { // when positions is dynamic, change this part to fins the most distant // position - PowerScaledScalar child = _children.at(i)->position().length() - + _children.at(i)->calculateBoundingSphere(); + //PowerScaledScalar child = _children.at(i)->position().length() + // + _children.at(i)->calculateBoundingSphere(); + PowerScaledScalar child = _children.at(i)->calculateBoundingSphere(); if (child > maxChild) { maxChild = child; } @@ -311,7 +309,7 @@ PowerScaledScalar SceneGraphNode::calculateBoundingSphere(){ if(renderableBS > _boundingSphere) _boundingSphere = renderableBS; } - LWARNING(name() << ": " << _boundingSphere); + LINFO("Bounding Sphere of '" << name() << "': " << _boundingSphere); return _boundingSphere; } diff --git a/src/scripting/scriptengine.cpp b/src/scripting/scriptengine.cpp index 49d6420064..c1b3dc4851 100644 --- a/src/scripting/scriptengine.cpp +++ b/src/scripting/scriptengine.cpp @@ -182,23 +182,20 @@ ScriptEngine::ScriptEngine() } bool ScriptEngine::initialize() { + LDEBUG("Adding base functions"); + addBaseLibrary(); + _state = luaL_newstate(); LDEBUG("Creating Lua state"); if (_state == nullptr) { LFATAL("Error creating new Lua state: Memory allocation error"); return false; } + LDEBUG("Open Lua libraries"); luaL_openlibs(_state); - - LDEBUG("Add OpenSpace modules"); - - LDEBUG("Create openspace base library"); - lua_newtable(_state); - lua_setglobal(_state, _openspaceLibraryName.c_str()); - - LDEBUG("Adding base functions"); - addBaseLibrary(); + + initializeLuaState(_state); LDEBUG("Remap print function"); remapPrintFunction(); @@ -211,42 +208,8 @@ void ScriptEngine::deinitialize() { _state = nullptr; } -bool ScriptEngine::addLibrary(const ScriptEngine::LuaLibrary& library) { - assert(_state); - if (library.functions.empty()) { - LERROR("Lua library '" << library.name << "' does not have any functions"); - return false; - } - - //ghoul::lua::logStack(_state); - lua_getglobal(_state, _openspaceLibraryName.c_str()); - //ghoul::lua::logStack(_state); - if (library.name.empty()) { - //ghoul::lua::logStack(_state); - addLibraryFunctions(library, true); - //ghoul::lua::logStack(_state); - lua_pop(_state, 1); - //ghoul::lua::logStack(_state); - } - else { - const bool allowed = isLibraryNameAllowed(library.name); - if (!allowed) - return false; - - //ghoul::lua::logStack(_state); - - lua_pushstring(_state, library.name.c_str()); - //ghoul::lua::logStack(_state); - lua_newtable(_state); - //ghoul::lua::logStack(_state); - addLibraryFunctions(library, false); - lua_settable(_state, _setTableOffset); - //ghoul::lua::logStack(_state); - - _registeredLibraries.insert(library); - } - - return true; +void ScriptEngine::addLibrary(const ScriptEngine::LuaLibrary& library) { + _registeredLibraries.insert(library); } bool ScriptEngine::runScript(const std::string& script) { @@ -350,26 +313,26 @@ bool ScriptEngine::isLibraryNameAllowed(const std::string& name) return result; } -void ScriptEngine::addLibraryFunctions(const LuaLibrary& library, bool replace) -{ +void ScriptEngine::addLibraryFunctions(lua_State* state, const LuaLibrary& library, bool replace) { + assert(state); for (LuaLibrary::Function p : library.functions) { if (!replace) { //ghoul::lua::logStack(_state); - lua_getfield(_state, -1, p.name.c_str()); + lua_getfield(state, -1, p.name.c_str()); //ghoul::lua::logStack(_state); - const bool isNil = lua_isnil(_state, -1); + const bool isNil = lua_isnil(state, -1); if (!isNil) { LERROR("Function name '" << p.name << "' was already assigned"); return; } - lua_pop(_state, 1); + lua_pop(state, 1); } //ghoul::lua::logStack(_state); - lua_pushstring(_state, p.name.c_str()); + lua_pushstring(state, p.name.c_str()); //ghoul::lua::logStack(_state); - lua_pushcfunction(_state, p.function); + lua_pushcfunction(state, p.function); //ghoul::lua::logStack(_state); - lua_settable(_state, _setTableOffset); + lua_settable(state, _setTableOffset); //ghoul::lua::logStack(_state); } } @@ -436,6 +399,54 @@ void ScriptEngine::remapPrintFunction() { // lua_settable(_state, _setTableOffset); //ghoul::lua::logStack(_state); } - + +void ScriptEngine::initializeLuaState(lua_State* state) { + LDEBUG("Create openspace base library"); + lua_newtable(_state); + lua_setglobal(_state, _openspaceLibraryName.c_str()); + + LDEBUG("Add OpenSpace modules"); + for (auto lib : _registeredLibraries) + registerLuaLibrary(state, lib); +} + +bool ScriptEngine::registerLuaLibrary(lua_State* state, const LuaLibrary& library) { + assert(state); + if (library.functions.empty()) { + LERROR("Lua library '" << library.name << "' does not have any functions"); + return false; + } + + //ghoul::lua::logStack(_state); + lua_getglobal(state, _openspaceLibraryName.c_str()); + //ghoul::lua::logStack(_state); + if (library.name.empty()) { + //ghoul::lua::logStack(_state); + addLibraryFunctions(state, library, true); + //ghoul::lua::logStack(_state); + lua_pop(state, 1); + //ghoul::lua::logStack(_state); + } + else { + const bool allowed = isLibraryNameAllowed(library.name); + if (!allowed) + return false; + + //ghoul::lua::logStack(_state); + + lua_pushstring(state, library.name.c_str()); + //ghoul::lua::logStack(_state); + lua_newtable(state); + //ghoul::lua::logStack(_state); + addLibraryFunctions(state, library, false); + lua_settable(state, _setTableOffset); + //ghoul::lua::logStack(_state); + + _registeredLibraries.insert(library); + } + return true; +} + + } // namespace scripting } // namespace openspace