Merge branch 'feature/parallelconnection' into develop

Conflicts:
	src/interaction/interactionhandler.cpp
This commit is contained in:
Emil Axelsson
2016-09-30 11:01:37 +02:00
33 changed files with 1142 additions and 1521 deletions
@@ -51,6 +51,7 @@ class RenderEngine;
class ModuleEngine;
class WindowWrapper;
class SettingsEngine;
class TimeManager;
class SyncEngine;
namespace interaction { class InteractionHandler; }
@@ -90,6 +91,7 @@ public:
WindowWrapper& windowWrapper();
ghoul::fontrendering::FontManager& fontManager();
DownloadManager& downloadManager();
TimeManager& timeManager();
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
gui::GUI& gui();
@@ -151,6 +153,7 @@ private:
std::unique_ptr<LuaConsole> _console;
std::unique_ptr<ModuleEngine> _moduleEngine;
std::unique_ptr<SettingsEngine> _settingsEngine;
std::unique_ptr<TimeManager> _timeManager;
std::unique_ptr<DownloadManager> _downloadManager;
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
std::unique_ptr<gui::GUI> _gui;
@@ -47,113 +47,15 @@ class SceneGraphNode;
namespace interaction {
//#define USE_OLD_INTERACTIONHANDLER
#ifdef USE_OLD_INTERACTIONHANDLER
class InteractionHandler : public properties::PropertyOwner {
public:
InteractionHandler();
~InteractionHandler();
// Mutators
void setKeyboardController(KeyboardController* controller);
void setMouseController(MouseController* controller);
void setFocusNode(SceneGraphNode* node);
void setCamera(Camera* camera);
void setInteractionSensitivity(float sensitivity);
void resetKeyBindings();
void setInvertRoll(bool invert);
void setInvertRotation(bool invert);
void addController(Controller* controller);
void addKeyframe(const network::datamessagestructures::PositionKeyframe &kf);
void clearKeyframes();
void bindKey(Key key, KeyModifier modifier, std::string lua);
void lockControls();
void unlockControls();
void update(double deltaTime);
// Accessors
const SceneGraphNode* const focusNode() const;
const Camera* const camera() const;
double deltaTime() const;
float interactionSensitivity() const;
bool invertRoll() const;
bool invertRotation() const;
/**
* Returns the Lua library that contains all Lua functions available to affect the
* interaction. The functions contained are
* - openspace::luascriptfunctions::setOrigin
* \return The Lua library that contains all Lua functions available to affect the
* interaction
*/
static scripting::LuaLibrary luaLibrary();
// Callback functions
void keyboardCallback(Key key, KeyModifier modifier, KeyAction action);
void mouseButtonCallback(MouseButton button, MouseAction action);
void mousePositionCallback(double x, double y);
void mouseScrollWheelCallback(double pos);
// Interaction functions
void orbitDelta(const glm::quat& rotation);
void orbit(const float &dx, const float &dy, const float &dz, const float &dist);
void rotateDelta(const glm::quat& rotation);
void distanceDelta(const PowerScaledScalar& distance, size_t iterations = 0);
void lookAt(const glm::quat& rotation);
void setRotation(const glm::quat& rotation);
private:
// Remove copy and move constructors
InteractionHandler(const InteractionHandler&) = delete;
InteractionHandler& operator=(const InteractionHandler&) = delete;
InteractionHandler(InteractionHandler&&) = delete;
InteractionHandler& operator=(InteractionHandler&&) = delete;
// Settings
float _controllerSensitivity;
bool _invertRoll;
bool _invertRotation;
// Pointers to entities to affect
Camera* _camera;
SceneGraphNode* _focusNode;
// Cached data
double _deltaTime;
std::mutex _mutex;
//bool _validKeyLua;
std::multimap<KeyWithModifier, std::string > _keyLua;
KeyboardController* _keyboardController;
MouseController* _mouseController;
std::vector<Controller*> _controllers;
properties::StringProperty _origin;
properties::StringProperty _coordinateSystem;
//remote controller
std::vector<network::datamessagestructures::PositionKeyframe> _keyframes;
double _currentKeyframeTime;
std::mutex _keyframeMutex;
};
#else // USE_OLD_INTERACTIONHANDLER
class InteractionHandler : public properties::PropertyOwner
{
public:
InteractionHandler();
~InteractionHandler();
void initialize();
void deinitialize();
// Mutators
void setFocusNode(SceneGraphNode* node);
void setCamera(Camera* camera);
@@ -165,9 +67,10 @@ public:
void resetKeyBindings();
void addKeyframe(const network::datamessagestructures::PositionKeyframe &kf);
void addKeyframe(const network::datamessagestructures::CameraKeyframe &kf);
void clearKeyframes();
void bindKeyLocal(Key key, KeyModifier modifier, std::string lua);
void bindKey(Key key, KeyModifier modifier, std::string lua);
void lockControls();
void unlockControls();
@@ -206,7 +109,7 @@ private:
bool _cameraUpdatedFromScript = false;
std::multimap<KeyWithModifier, std::string > _keyLua;
std::multimap<KeyWithModifier, std::pair<std::string, bool>> _keyLua;
std::unique_ptr<InputState> _inputState;
Camera* _camera;
@@ -228,8 +131,6 @@ private:
properties::FloatProperty _rapidness;
};
#endif // USE_OLD_INTERACTIONHANDLER
} // namespace interaction
} // namespace openspace
@@ -56,15 +56,16 @@ namespace interaction {
void mouseScrollWheelCallback(double mouseScrollDelta);
// Mutators
void addKeyframe(const network::datamessagestructures::PositionKeyframe &kf);
void addKeyframe(const network::datamessagestructures::CameraKeyframe &kf);
void clearKeyframes();
void clearOldKeyframes();
// Accessors
const std::list<std::pair<Key, KeyModifier> >& getPressedKeys() const;
const std::list<MouseButton>& getPressedMouseButtons() const;
glm::dvec2 getMousePosition() const;
double getMouseScrollDelta() const;
std::vector<network::datamessagestructures::PositionKeyframe>& getKeyFrames() const;
const std::vector<network::datamessagestructures::CameraKeyframe>& keyframes() const;
bool isKeyPressed(std::pair<Key, KeyModifier> keyModPair) const;
bool isMouseButtonPressed(MouseButton mouseButton) const;
@@ -76,8 +77,7 @@ namespace interaction {
double _mouseScrollDelta;
// Remote input via keyframes
std::vector<network::datamessagestructures::PositionKeyframe> _keyframes;
std::mutex _keyframeMutex;
std::vector<network::datamessagestructures::CameraKeyframe> _keyframes;
};
@@ -168,6 +168,7 @@ public:
virtual void updateCameraStateFromMouseStates(Camera& camera);
private:
std::vector<network::datamessagestructures::CameraKeyframe> _keyframes;
double _currentKeyframeTime;
};
+7 -1
View File
@@ -26,6 +26,7 @@
#define LUACONSOLE_H
#include <openspace/scripting/scriptengine.h>
#include <openspace/network/parallelconnection.h>
#include <openspace/util/keys.h>
@@ -50,12 +51,16 @@ public:
bool isVisible() const;
void setVisible(bool visible);
void toggleVisibility();
bool isRemoteScripting() const;
void setRemoteScripting(bool remoteScripting);
void toggleMode();
static scripting::LuaLibrary luaLibrary();
private:
void parallelConnectionChanged(const network::Status& status);
void addToCommand(std::string c);
std::string UnicodeToUTF8(unsigned int codepoint);
@@ -73,6 +78,7 @@ private:
} _autoCompleteInfo;
bool _isVisible;
bool _remoteScripting;
};
} // namespace openspace
+42 -34
View File
@@ -33,33 +33,38 @@
#include <glm/gtx/quaternion.hpp>
//openspace includes
#include <openspace/util/powerscaledcoordinate.h>
#include <openspace/util/camera.h>
namespace openspace{
namespace network{
namespace datamessagestructures{
enum type{
PositionData = 0,
namespace datamessagestructures {
enum class Type : uint32_t {
CameraData = 0,
TimeData,
ScriptData
};
struct PositionKeyframe{
glm::quat _viewRotationQuat;
psc _position;
double _timeStamp;
struct CameraKeyframe {
CameraKeyframe() {}
CameraKeyframe(const std::vector<char> &buffer) {
deserialize(buffer);
}
glm::dvec3 _position;
glm::dquat _rotation;
double _timestamp;
void serialize(std::vector<char> &buffer){
//add position
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_position), reinterpret_cast<char*>(&_position) + sizeof(_position));
//add orientation
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_viewRotationQuat), reinterpret_cast<char*>(&_viewRotationQuat) + sizeof(_viewRotationQuat));
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_rotation), reinterpret_cast<char*>(&_rotation) + sizeof(_rotation));
//add timestamp
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_timeStamp), reinterpret_cast<char*>(&_timeStamp) + sizeof(_timeStamp));
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_timestamp), reinterpret_cast<char*>(&_timestamp) + sizeof(_timestamp));
};
void deserialize(const std::vector<char> &buffer){
@@ -72,22 +77,27 @@ namespace openspace{
offset += size;
//orientation
size = sizeof(_viewRotationQuat);
memcpy(&_viewRotationQuat, buffer.data() + offset, size);
size = sizeof(_rotation);
memcpy(&_rotation, buffer.data() + offset, size);
offset += size;
//timestamp
size = sizeof(_timeStamp);
memcpy(&_timeStamp, buffer.data() + offset, size);
size = sizeof(_timestamp);
memcpy(&_timestamp, buffer.data() + offset, size);
};
};
struct TimeKeyframe{
struct TimeKeyframe {
TimeKeyframe() {}
TimeKeyframe(const std::vector<char> &buffer) {
deserialize(buffer);
}
double _time;
double _dt;
bool _paused;
bool _requiresTimeJump;
double _timestamp;
void serialize(std::vector<char> &buffer){
//add current time
@@ -101,6 +111,9 @@ namespace openspace{
//add wether a time jump is necessary (recompute paths etc)
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_requiresTimeJump), reinterpret_cast<char*>(&_requiresTimeJump) + sizeof(_requiresTimeJump));
//add timestamp
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_timestamp), reinterpret_cast<char*>(&_timestamp) + sizeof(_timestamp));
};
void deserialize(const std::vector<char> &buffer){
@@ -125,34 +138,29 @@ namespace openspace{
//is a time jump required?
size = sizeof(_requiresTimeJump);
memcpy(&_requiresTimeJump, buffer.data() + offset, size);
offset += size;
// timestamp
size = sizeof(_timestamp);
memcpy(&_timestamp, buffer.data() + offset, size);
offset += size;
};
};
struct ScriptMessage{
uint16_t _scriptlen;
struct ScriptMessage {
ScriptMessage() {}
ScriptMessage(const std::vector<char> &buffer) {
deserialize(buffer);
}
std::string _script;
void serialize(std::vector<char> &buffer){
//add script length
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_scriptlen), reinterpret_cast<char*>(&_scriptlen) + sizeof(_scriptlen));
//add script
buffer.insert(buffer.end(), _script.begin(), _script.end());
};
void deserialize(const std::vector<char> &buffer){
int offset = 0;
int size = 0;
//size of script
size = sizeof(uint16_t);
memcpy(&_scriptlen, buffer.data() + offset, size);
offset += size;
//actual script
_script.assign(buffer.begin() + offset, buffer.end());
_script.assign(buffer.begin(), buffer.end());
};
};
+91 -88
View File
@@ -33,12 +33,15 @@
//glm includes
#include <glm/gtx/quaternion.hpp>
//ghoul includes
#include <ghoul/designpattern/event.h>
//std includes
#include <string>
#include <vector>
#include <deque>
#include <atomic>
#include <thread>
#include <sstream>
#include <mutex>
#include <map>
#include <condition_variable>
@@ -59,48 +62,64 @@ typedef int _SOCKET;
#include <netdb.h>
#endif
namespace openspace{
namespace openspace {
namespace network{
namespace network {
enum class Status : uint32_t {
Disconnected = 0,
ClientWithoutHost,
ClientWithHost,
Host
};
enum class MessageType : uint32_t {
Authentication = 0,
Data,
ConnectionStatus,
HostshipRequest,
HostshipResignation,
NConnections
};
struct Message {
Message() {};
Message(MessageType t, const std::vector<char>& c)
: type(t)
, content(c)
{};
MessageType type;
std::vector<char> content;
};
struct DataMessage {
DataMessage() {};
DataMessage(network::datamessagestructures::Type t, const std::vector<char>& c)
: type(t)
, content(c)
{};
network::datamessagestructures::Type type;
std::vector<char> content;
};
class ParallelConnection{
public:
ParallelConnection();
~ParallelConnection();
void clientConnect();
void setPort(const std::string &port);
void setAddress(const std::string &address);
void setName(const std::string& name);
bool isHost();
const std::string& hostName();
void requestHostship(const std::string &password);
void resignHostship();
void setPassword(const std::string &password);
void signalDisconnect();
void preSynchronization();
void scriptMessage(const std::string propIdentifier, const std::string propValue);
enum MessageTypes{
Authentication=0,
Initialization,
Data,
Script, //obsolete now
HostInfo,
InitializationRequest,
HostshipRequest,
InitializationCompleted
};
void sendScript(const std::string& script);
/**
* Returns the Lua library that contains all Lua functions available to affect the
* remote OS parallel connection. The functions contained are
@@ -109,97 +128,81 @@ namespace openspace{
* interaction
*/
static scripting::LuaLibrary luaLibrary();
protected:
Status status();
size_t nConnections();
std::shared_ptr<ghoul::Event<>> connectionEvent();
private:
//@TODO change this into the ghoul hasher for client AND server
uint32_t hash(const std::string &val){
uint32_t hashVal = 0, i;
size_t len = val.length();
uint32_t hash(const std::string &val);
void queueOutMessage(const Message& message);
void queueOutDataMessage(const DataMessage& dataMessage);
void queueInMessage(const Message& message);
for (hashVal = i = 0; i < len; ++i){
hashVal += val.c_str()[i];
hashVal += (hashVal << 10);
hashVal ^= (hashVal >> 6);
}
hashVal += (hashVal << 3);
hashVal ^= (hashVal >> 11);
hashVal += (hashVal << 15);
return hashVal;
};
void queueMessage(std::vector<char> message);
void disconnect();
void writeHeader(std::vector<char> &buffer, uint32_t messageType);
void closeSocket();
bool initNetworkAPI();
void establishConnection(addrinfo *info);
void sendAuthentication();
void listenCommunication();
int receiveData(_SOCKET & socket, std::vector<char> &buffer, int length, int flags);
void delegateDecoding(uint32_t type);
void initializationMessageReceived();
void dataMessageReceived();
void hostInfoMessageReceived();
void initializationRequestMessageReceived();
void handleMessage(const Message&);
void dataMessageReceived(const std::vector<char>& messageContent);
void connectionStatusMessageReceived(const std::vector<char>& messageContent);
void nConnectionsMessageReceived(const std::vector<char>& messageContent);
void broadcast();
int headerSize();
void sendCameraKeyframe();
void sendTimeKeyframe();
int receiveData(_SOCKET & socket, std::vector<char> &buffer, int length, int flags);
void sendFunc();
bool parseHints(addrinfo &info);
void threadManagement();
std::string scriptFromPropertyAndValue(const std::string property, const std::string value);
void setStatus(Status status);
void setHostName(const std::string& hostName);
void setNConnections(size_t nConnections);
double calculateBufferedKeyframeTime(double originalTime);
uint32_t _passCode;
std::string _port;
std::string _address;
std::string _name;
_SOCKET _clientSocket;
std::thread *_connectionThread;
std::thread *_broadcastThread;
std::thread *_sendThread;
std::thread *_listenThread;
std::thread *_handlerThread;
std::atomic<bool> _isHost;
std::atomic<bool> _isConnected;
std::atomic<bool> _performDisconnect;
std::atomic<bool> _isRunning;
std::atomic<bool> _tryConnect;
std::atomic<bool> _disconnect;
std::atomic<bool> _initializationTimejumpRequired;
std::atomic<size_t> _nConnections;
std::atomic<Status> _status;
std::string _hostName;
std::condition_variable _disconnectCondition;
std::mutex _disconnectMutex;
std::vector<std::vector<char>> _sendBuffer;
std::mutex _sendBufferMutex;
std::condition_variable _sendCondition;
std::deque<Message> _sendBuffer;
std::mutex _sendBufferMutex;
std::deque<Message> _receiveBuffer;
std::mutex _receiveBufferMutex;
network::datamessagestructures::TimeKeyframe _latestTimeKeyframe;
std::mutex _timeKeyframeMutex;
std::atomic<bool> _latestTimeKeyframeValid;
std::map<std::string, std::string> _currentState;
std::mutex _currentStateMutex;
std::atomic<bool> _timeJumped;
std::mutex _latencyMutex;
std::deque<double> _latencyDiffs;
double _initialTimeDiff;
std::unique_ptr<std::thread> _connectionThread;
std::unique_ptr<std::thread> _broadcastThread;
std::unique_ptr<std::thread> _sendThread;
std::unique_ptr<std::thread> _listenThread;
std::unique_ptr<std::thread> _handlerThread;
std::shared_ptr<ghoul::Event<>> _connectionEvent;
};
} // namespace network
+2 -6
View File
@@ -37,9 +37,8 @@ namespace scripting {
struct LuaLibrary {
/**
* This structure represents a Lua function with its #name, #function pointer
* #argumentText describing the arguments this function takes, the #helpText
* describing the function, and whether it should be shared in a parallel
* connection (#parallelShared)
* #argumentText describing the arguments this function takes, and the the #helpText
* describing the function.
*/
struct Function {
/// The name of the function
@@ -50,9 +49,6 @@ struct LuaLibrary {
std::string argumentText;
/// A help text describing what the function does/
std::string helpText;
/// If <code>true</code>, this function will be shared with other parallel
/// connections
bool parallelShared;
};
/// The name of the library
std::string name;
+8 -7
View File
@@ -50,6 +50,7 @@ namespace scripting {
*/
class ScriptEngine : public Syncable {
public:
using RemoteScripting = ghoul::Boolean;
/**
* Initializes the internal Lua state and registers a common set of library functions
* \throw LuaRuntimeException If the creation of the new Lua state fails
@@ -79,7 +80,7 @@ public:
virtual void decode(SyncBuffer* syncBuffer);
virtual void postsync(bool isMaster);
void queueScript(const std::string &script);
void queueScript(const std::string &script, RemoteScripting remoteScripting);
void setLogFile(const std::string& filename, const std::string& type);
@@ -88,9 +89,9 @@ public:
std::vector<std::string> allLuaFunctions() const;
//parallel functions
bool parseLibraryAndFunctionNames(std::string &library, std::string &function, const std::string &script);
bool shouldScriptBeSent(const std::string &library, const std::string &function);
void cacheScript(const std::string &library, const std::string &function, const std::string &script);
//bool parseLibraryAndFunctionNames(std::string &library, std::string &function, const std::string &script);
//bool shouldScriptBeSent(const std::string &library, const std::string &function);
//void cacheScript(const std::string &library, const std::string &function, const std::string &script);
private:
@@ -107,13 +108,13 @@ private:
//sync variables
std::mutex _mutex;
std::vector<std::string> _queuedScripts;
std::vector<std::pair<std::string, bool>> _queuedScripts;
std::vector<std::string> _receivedScripts;
std::string _currentSyncedScript;
//parallel variables
std::map<std::string, std::map<std::string, std::string>> _cachedScripts;
std::mutex _cachedScriptsMutex;
//std::map<std::string, std::map<std::string, std::string>> _cachedScripts;
//std::mutex _cachedScriptsMutex;
//logging variables
bool _logFileExists = false;
+51
View File
@@ -0,0 +1,51 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 __TIMEMANAGER_H__
#define __TIMEMANAGER_H__
#include <deque>
#include <openspace/network/messagestructures.h>
namespace openspace {
class TimeManager {
public:
void preSynchronization(double dt);
void addKeyframe(const network::datamessagestructures::TimeKeyframe& kf);
void removeKeyframesBefore(double timestamp);
void clearKeyframes();
private:
void consumeKeyframes(double dt);
std::deque<network::datamessagestructures::TimeKeyframe> _keyframes;
static bool compareKeyframeTimes(
const network::datamessagestructures::TimeKeyframe& a,
const network::datamessagestructures::TimeKeyframe& b);
double _latestConsumedTimestamp;
};
}
#endif // __TIMEMANAGER_H__
+9 -5
View File
@@ -155,7 +155,7 @@ void addScreenSpaceRenderable(std::string texturePath) {
std::string luaTable =
"{Type = 'ScreenSpaceImage', TexturePath = '" + absPath(texturePath) + "' }";
std::string script = "openspace.registerScreenSpaceRenderable(" + luaTable + ");";
OsEng.scriptEngine().queueScript(script);
OsEng.scriptEngine().queueScript(script, openspace::scripting::ScriptEngine::RemoteScripting::Yes);
}
} // namespace
@@ -453,22 +453,26 @@ void GUI::render() {
if (toSun) {
OsEng.scriptEngine().queueScript(
"openspace.setPropertyValue('Interaction.coordinateSystem', 'Sun');"
"openspace.setPropertyValue('Interaction.coordinateSystem', 'Sun');",
scripting::ScriptEngine::RemoteScripting::Yes
);
}
if (toPluto) {
OsEng.scriptEngine().queueScript(
"openspace.setPropertyValue('Interaction.coordinateSystem', 'Pluto');"
"openspace.setPropertyValue('Interaction.coordinateSystem', 'Pluto');",
scripting::ScriptEngine::RemoteScripting::Yes
);
}
if (toJupiter) {
OsEng.scriptEngine().queueScript(
"openspace.setPropertyValue('Interaction.coordinateSystem', 'Jupiter');"
"openspace.setPropertyValue('Interaction.coordinateSystem', 'Jupiter');",
scripting::ScriptEngine::RemoteScripting::Yes
);
}
if (to67P) {
OsEng.scriptEngine().queueScript(
"openspace.setPropertyValue('Interaction.coordinateSystem', '67P');"
"openspace.setPropertyValue('Interaction.coordinateSystem', '67P');",
scripting::ScriptEngine::RemoteScripting::Yes
);
}
@@ -65,7 +65,8 @@ void GuiOriginComponent::render() {
if (hasChanged) {
OsEng.scriptEngine().queueScript(
"openspace.setPropertyValue('Interaction.origin', '" +
nodes[currentPosition]->name() + "');"
nodes[currentPosition]->name() + "');",
scripting::ScriptEngine::RemoteScripting::Yes
);
}
}
+2 -1
View File
@@ -38,7 +38,8 @@ void GuiTimeComponent::render() {
bool changed = ImGui::SliderFloat("Delta Time", &deltaTime, -5000.f, 5000.f);
if (changed) {
OsEng.scriptEngine().queueScript(
"openspace.time.setDeltaTime(" + std::to_string(deltaTime) + ")"
"openspace.time.setDeltaTime(" + std::to_string(deltaTime) + ")",
scripting::ScriptEngine::RemoteScripting::Yes
);
}
}
+1 -1
View File
@@ -47,7 +47,7 @@ void renderTooltip(Property* prop) {
void executeScript(const std::string& id, const std::string& value) {
std::string script =
"openspace.setPropertyValueSingle('" + id + "', " + value + ");";
OsEng.scriptEngine().queueScript(script);
OsEng.scriptEngine().queueScript(script, scripting::ScriptEngine::RemoteScripting::Yes);
}
void renderBoolProperty(Property* prop, const std::string& ownerName) {
+6 -3
View File
@@ -24,10 +24,13 @@ openspace.bindKey("q", helper.renderable.toggle('SunMarker'))
openspace.bindKey("e", helper.renderable.toggle('EarthMarker'))
openspace.bindKey("x", helper.renderable.toggle('Constellation Bounds'))
openspace.bindKey("c", "openspace.parallel.setAddress('130.236.142.51');openspace.parallel.setPassword('newhorizons-20150714');openspace.parallel.connect();")
--openspace.bindKey("c", "openspace.parallel.setAddress('130.236.142.51');openspace.parallel.setPassword('newhorizons-20150714');openspace.parallel.connect();")
openspace.bindKey("h", "openspace.iswa.setBaseUrl('https://iswa-demo-server.herokuapp.com/')");
--openspace.bindKey("h", "openspace.iswa.setBaseUrl('https://iswa-demo-server.herokuapp.com/')");
openspace.bindKey("g", "openspace.iswa.setBaseUrl('http://128.183.168.116:3000/')");
openspace.bindKey("l", "openspace.iswa.setBaseUrl('http://localhost:3000/')");
openspace.bindKey("v", "openspace.time.setTime('2015-03-15T02:00:00.00')");
openspace.bindKey("v", "openspace.time.setTime('2015-03-15T02:00:00.00')");
openspace.bindKeyLocal("h", "openspace.parallel.setAddress('127.0.0.1');openspace.parallel.setPort('25001');openspace.parallel.setPassword('test');openspace.parallel.connect();openspace.parallel.requestHostship('test');")
openspace.bindKeyLocal("c", "openspace.parallel.setAddress('127.0.0.1');openspace.parallel.setPort('25001');openspace.parallel.setPassword('test');openspace.parallel.connect();")
+3 -1
View File
@@ -17,6 +17,7 @@ openspace.bindKey("s", "openspace.setPropertyValue('Interaction.origin', 'Rosett
-- openspace.bindKey("F5", "openspace.setPropertyValue('Interaction.coordinateSystem', 'Sun'); openspace.printInfo('Changing Viewpoint to Sun');");
openspace.bindKey("F6", "openspace.setPropertyValue('Interaction.coordinateSystem', '67P'); openspace.printInfo('Changing Viewpoint to 67P');");
openspace.bindKey("F7", "openspace.time.setTime('2014-08-15T03:05:18.101')");
openspace.bindKey("F8", "openspace.setPropertyValue('67P.renderable.ProjectionComponent.clearAllProjections', true);");
openspace.bindKey("i", helper.renderable.toggle('ImagePlaneRosetta'))
@@ -24,4 +25,5 @@ openspace.bindKey("q", helper.renderable.toggle('SunMarker'))
openspace.bindKey("e", helper.renderable.toggle('JupiterTrail') .. helper.renderable.toggle('SaturnTrail') .. helper.renderable.toggle('UranusTrail') .. helper.renderable.toggle('NeptuneTrail'))
openspace.bindKey("f", helper.renderable.toggle('PhilaeTrail'))
openspace.bindKey("c", "openspace.parallel.setAddress('130.236.142.51');openspace.parallel.setPassword('newhorizons-20150714');openspace.parallel.connect();")
openspace.bindKeyLocal("h", "openspace.parallel.setAddress('127.0.0.1');openspace.parallel.setPort('25001');openspace.parallel.setPassword('test');openspace.parallel.connect();openspace.parallel.requestHostship('test');")
openspace.bindKeyLocal("c", "openspace.parallel.setAddress('127.0.0.1');openspace.parallel.setPort('25001');openspace.parallel.setPassword('test');openspace.parallel.connect();")
+10 -10
View File
@@ -12,24 +12,24 @@ helper.scheduledScript.reversible = {}
-- Function that sets the most common key bindings that are common to most (all?)
-- scenes
helper.setCommonKeys = function()
openspace.bindKey("F1", "openspace.gui.toggle()")
openspace.bindKey("F2", "openspace.setPerformanceMeasurement(true)")
openspace.bindKey("F3", "openspace.setPerformanceMeasurement(false)")
openspace.bindKeyLocal("F1", "openspace.gui.toggle()")
openspace.bindKeyLocal("F2", "openspace.setPerformanceMeasurement(true)")
openspace.bindKeyLocal("F3", "openspace.setPerformanceMeasurement(false)")
openspace.bindKey("t", "openspace.toggleFrametimeType(1)")
openspace.bindKey("Shift+t", "openspace.toggleFrametimeType(0)")
openspace.bindKeyLocal("t", "openspace.toggleFrametimeType(1)")
openspace.bindKeyLocal("Shift+t", "openspace.toggleFrametimeType(0)")
openspace.bindKey("ESC", "openspace.toggleShutdown()")
openspace.bindKeyLocal("ESC", "openspace.toggleShutdown()")
openspace.bindKey("PRINT_SCREEN", "openspace.takeScreenshot()")
openspace.bindKeyLocal("PRINT_SCREEN", "openspace.takeScreenshot()")
openspace.bindKey("SPACE", "openspace.time.togglePause()")
openspace.bindKey("COMMA", "openspace.setRenderer('Framebuffer');")
openspace.bindKey("PERIOD", "openspace.setRenderer('ABuffer');")
openspace.bindKey("f", helper.property.invert('Interaction.rotationalFriction'))
openspace.bindKey("Shift+f", helper.property.invert('Interaction.zoomFriction'))
openspace.bindKeyLocal("f", helper.property.invert('Interaction.rotationalFriction'))
openspace.bindKeyLocal("Shift+f", helper.property.invert('Interaction.zoomFriction'))
openspace.bindKey("w", "openspace.toggleFade(3)")
end
@@ -102,4 +102,4 @@ helper.scheduledScript.setEnabled = function(time, renderable, enabled)
Backward = ""
}
}
end
end
+2
View File
@@ -113,6 +113,7 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/util/syncdata.cpp
${OPENSPACE_BASE_DIR}/src/util/histogram.cpp
${OPENSPACE_BASE_DIR}/src/util/time.cpp
${OPENSPACE_BASE_DIR}/src/util/timemanager.cpp
${OPENSPACE_BASE_DIR}/src/util/time_lua.inl
${OPENSPACE_BASE_DIR}/src/util/timerange.cpp
${OPENSPACE_BASE_DIR}/src/util/transformationmanager.cpp
@@ -210,6 +211,7 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/util/syncbuffer.h
${OPENSPACE_BASE_DIR}/include/openspace/util/syncdata.h
${OPENSPACE_BASE_DIR}/include/openspace/util/time.h
${OPENSPACE_BASE_DIR}/include/openspace/util/timemanager.h
${OPENSPACE_BASE_DIR}/include/openspace/util/updatestructures.h
${OPENSPACE_BASE_DIR}/include/openspace/util/transformationmanager.h
${OPENSPACE_BASE_DIR}/include/openspace/util/histogram.h
+22 -11
View File
@@ -50,6 +50,7 @@
#include <openspace/scene/scene.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/time.h>
#include <openspace/util/timemanager.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/syncbuffer.h>
#include <openspace/util/transformationmanager.h>
@@ -140,6 +141,7 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
, _console(new LuaConsole)
, _moduleEngine(new ModuleEngine)
, _settingsEngine(new SettingsEngine)
, _timeManager(new TimeManager)
, _downloadManager(nullptr)
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
, _gui(new gui::GUI)
@@ -154,6 +156,7 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName,
, _shutdownWait(0.f)
, _isFirstRenderingFirstFrame(true)
{
_interactionHandler->setPropertyOwner(_globalPropertyNamespace.get());
_globalPropertyNamespace->addPropertySubOwner(_interactionHandler.get());
_globalPropertyNamespace->addPropertySubOwner(_settingsEngine.get());
@@ -179,6 +182,7 @@ OpenSpaceEngine::~OpenSpaceEngine() {
#ifdef OPENSPACE_MODULE_ONSCREENGUI_ENABLED
_gui->deinitializeGL();
#endif
_interactionHandler->deinitialize();
_renderEngine->deinitialize();
_globalPropertyNamespace = nullptr;
@@ -437,6 +441,9 @@ bool OpenSpaceEngine::initialize() {
_settingsEngine->initialize();
_settingsEngine->setModules(_moduleEngine->modules());
// Initialize the InteractionHandler
_interactionHandler->initialize();
// Load a light and a monospaced font
loadFonts();
@@ -628,6 +635,7 @@ void OpenSpaceEngine::runScripts(const ghoul::Dictionary& scripts) {
//@JK
//temporary solution to ensure that startup scripts may be syncrhonized over parallel connection
/*
std::ifstream scriptFile;
scriptFile.open(absoluteScriptPath.c_str());
std::string line;
@@ -641,7 +649,7 @@ void OpenSpaceEngine::runScripts(const ghoul::Dictionary& scripts) {
_engine->scriptEngine().cacheScript(lib, func, line);
}
}
}
}*/
}
}
@@ -836,14 +844,13 @@ void OpenSpaceEngine::preSynchronization() {
_syncEngine->presync(_isMaster);
if (_isMaster) {
double dt = _windowWrapper->averageDeltaTime();
Time::ref().advanceTime(dt);
_timeManager->preSynchronization(dt);
auto scheduledScripts = _scriptScheduler->progressTo(Time::ref().j2000Seconds());
while(scheduledScripts.size()){
auto scheduledScript = scheduledScripts.front();
LINFO(scheduledScript);
_scriptEngine->queueScript(scheduledScript);
_scriptEngine->queueScript(scheduledScript, ScriptEngine::RemoteScripting::Yes);
scheduledScripts.pop();
}
@@ -967,14 +974,13 @@ void OpenSpaceEngine::keyboardCallback(Key key, KeyModifier mod, KeyAction actio
return;
}
#endif
if (key == _console->commandInputButton() && (action == KeyAction::Press || action == KeyAction::Repeat))
_console->toggleVisibility();
if (!_console->isVisible()) {
if (key == _console->commandInputButton()) {
if (action == KeyAction::Press) {
_console->toggleMode();
}
} else if (!_console->isVisible()) {
_interactionHandler->keyboardCallback(key, mod, action);
}
else {
} else {
_console->keyboardCallback(key, mod, action);
}
}
@@ -1173,5 +1179,10 @@ DownloadManager& OpenSpaceEngine::downloadManager() {
return *_downloadManager;
}
TimeManager& OpenSpaceEngine::timeManager() {
ghoul_assert(_timeManager, "Download Manager must not be nullptr");
return *_timeManager;
}
} // namespace openspace
+58 -592
View File
@@ -64,574 +64,6 @@ namespace {
namespace openspace {
namespace interaction {
#ifdef USE_OLD_INTERACTIONHANDLER
InteractionHandler::InteractionHandler()
: properties::PropertyOwner()
, _camera(nullptr)
, _focusNode(nullptr)
, _deltaTime(0.0)
//, _validKeyLua(false)
, _controllerSensitivity(1.f)
, _invertRoll(true)
, _invertRotation(false)
, _keyboardController(nullptr)
, _mouseController(nullptr)
, _origin("origin", "Origin", "")
, _coordinateSystem("coordinateSystem", "Coordinate System", "")
, _currentKeyframeTime(-1.0)
{
setName("Interaction");
_origin.onChange([this](){
SceneGraphNode* node = sceneGraphNode(_origin.value());
if (!node) {
LWARNING("Could not find a node in scenegraph called '" << _origin.value() <<"'");
return;
}
setFocusNode(node);
});
addProperty(_origin);
_coordinateSystem.onChange([this](){
OsEng.renderEngine().changeViewPoint(_coordinateSystem.value());
});
addProperty(_coordinateSystem);
}
InteractionHandler::~InteractionHandler() {
delete _keyboardController;
delete _mouseController;
for (size_t i = 0; i < _controllers.size(); ++i)
delete _controllers[i];
}
void InteractionHandler::setKeyboardController(KeyboardController* controller) {
assert(controller);
delete _keyboardController;
_keyboardController = controller;
_keyboardController->setHandler(this);
}
void InteractionHandler::setMouseController(MouseController* controller) {
assert(controller);
delete _mouseController;
_mouseController = controller;
_mouseController->setHandler(this);
}
void InteractionHandler::addController(Controller* controller) {
assert(controller);
_controllers.push_back(controller);
controller->setHandler(this);
}
void InteractionHandler::lockControls() {
_mutex.lock();
}
void InteractionHandler::unlockControls() {
_mutex.unlock();
}
void InteractionHandler::update(double deltaTime) {
_deltaTime = deltaTime;
_mouseController->update(deltaTime);
bool hasKeys = false;
psc pos;
glm::quat q;
_keyframeMutex.lock();
if (_keyframes.size() > 4){ //wait until enough samples are buffered
hasKeys = true;
openspace::network::datamessagestructures::PositionKeyframe p0, p1, p2, p3;
p0 = _keyframes[0];
p1 = _keyframes[1];
p2 = _keyframes[2];
p3 = _keyframes[3];
//interval check
if (_currentKeyframeTime < p1._timeStamp){
_currentKeyframeTime = p1._timeStamp;
}
double t0 = p1._timeStamp;
double t1 = p2._timeStamp;
double fact = (_currentKeyframeTime - t0) / (t1 - t0);
//glm::dvec4 v = positionInterpCR.interpolate(fact, _keyframes[0]._position.dvec4(), _keyframes[1]._position.dvec4(), _keyframes[2]._position.dvec4(), _keyframes[3]._position.dvec4());
glm::dvec4 v = ghoul::interpolateLinear(fact, p1._position.dvec4(), p2._position.dvec4());
pos = psc(v.x, v.y, v.z, v.w);
q = ghoul::interpolateLinear(fact, p1._viewRotationQuat, p2._viewRotationQuat);
//we're done with this sample interval
if (_currentKeyframeTime >= p2._timeStamp){
_keyframes.erase(_keyframes.begin());
_currentKeyframeTime = p1._timeStamp;
}
_currentKeyframeTime += deltaTime;
}
_keyframeMutex.unlock();
if (hasKeys) {
_camera->setPosition(pos);
_camera->setRotation(q);
}
}
void InteractionHandler::setFocusNode(SceneGraphNode* node) {
if (_focusNode == node){
return;
}
_focusNode = node;
//orient the camera to the new node
psc focusPos = node->worldPosition();
psc camToFocus = focusPos - _camera->position();
glm::vec3 viewDir = glm::normalize(camToFocus.vec3());
glm::vec3 cameraView = glm::normalize(_camera->viewDirectionWorldSpace());
//set new focus position
_camera->setFocusPosition(node->worldPosition());
float dot = glm::dot(viewDir, cameraView);
//static const float Epsilon = 0.001f;
if (dot < 1.f && dot > -1.f) {
//if (glm::length(viewDir - cameraView) < 0.001) {
//if (viewDir != cameraView) {
glm::vec3 rotAxis = glm::normalize(glm::cross(viewDir, cameraView));
float angle = glm::angle(viewDir, cameraView);
glm::quat q = glm::angleAxis(angle, rotAxis);
//rotate view to target new focus
_camera->rotate(q);
}
}
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<std::chrono::nanoseconds>(end - start).count() << "ns");
// }
//}
void InteractionHandler::mouseButtonCallback(MouseButton button, MouseAction action) {
if (_mouseController)
_mouseController->button(button, action);
}
void InteractionHandler::mousePositionCallback(double x, double y) {
if (_mouseController)
// TODO Remap screen coordinates to [0,1]
_mouseController->move(static_cast<float>(x), static_cast<float>(y));
}
void InteractionHandler::mouseScrollWheelCallback(double pos) {
if (_mouseController)
_mouseController->scrollWheel(static_cast<int>(pos));
}
void InteractionHandler::orbit(const float &dx, const float &dy, const float &dz, const float &dist){
lockControls();
glm::vec3 cameraUp = glm::normalize((glm::inverse(_camera->viewRotationMatrix()) * glm::vec4(_camera->lookUpVectorCameraSpace(), 0))).xyz();
glm::vec3 cameraRight = glm::cross(glm::vec3(_camera->viewDirectionWorldSpace()), cameraUp);
glm::mat4 transform;
transform = glm::rotate(glm::radians(dx * 100.f), cameraUp) * transform;
transform = glm::rotate(glm::radians(dy * 100.f), cameraRight) * transform;
transform = glm::rotate(glm::radians(dz * 100.f), glm::vec3(_camera->viewDirectionWorldSpace())) * transform;
//get "old" focus position
psc camPos = _camera->position();
psc focusPos = _camera->focusPosition();
float distToFocusNodeCenter = (focusPos - camPos).length().lengthf();
float focusNodeBounds = _focusNode ? _focusNode->boundingSphere().lengthf() : 0.f;
float speedFactor = distToFocusNodeCenter - 0.098*focusNodeBounds;
float rotationSpeed = glm::min(0.00001f * speedFactor, 100.0f);
float zoomSpeed = glm::min(0.0000001f * speedFactor, 1.0f);
float rollSpeed = 100.0f;
glm::mat4 transform;
transform = glm::rotate(glm::radians(dx * rotationSpeed), cameraUp) * transform;
transform = glm::rotate(glm::radians(dy * rotationSpeed), cameraRight) * transform;
transform = glm::rotate(glm::radians(dz * rollSpeed), _camera->viewDirection()) * transform;
//// get camera position
//psc relative = _camera->position();
// get camera position (UNSYNCHRONIZED)
psc relative = _camera->unsynchedPosition();
//get relative vector
psc relative_focus_coordinate = relative - focusPos;
//rotate relative vector
relative_focus_coordinate = glm::inverse(transform) * relative_focus_coordinate.vec4();
//get new new position of focus node
psc origin;
if (_focusNode) {
origin = _focusNode->worldPosition();
}
//new camera position
relative = origin + relative_focus_coordinate;
psc target = relative + relative_focus_coordinate * dist * zoomSpeed;
//don't fly into objects
if ((target - origin).length() < focusNodeBounds){
//target = relative;
}
unlockControls();
_camera->setFocusPosition(origin);
_camera->setPosition(target);
_camera->rotate(glm::quat_cast(transform));
}
//void InteractionHandler::distance(const float &d){
//
// lockControls();
//
// psc relative = _camera->position();
// const psc origin = (_focusNode) ? _focusNode->worldPosition() : psc();
// psc relative_origin_coordinate = relative - origin;
// // addition 100% of bounds (fix later to something node specific?)
// float bounds = 2.f * (_focusNode ? _focusNode->boundingSphere().lengthf() : 0.f);
//
// psc target = relative + relative_origin_coordinate * d;// *fmaxf(bounds, (1.f - d));
// //don't fly into objects
// if ((target - origin).length() < bounds){
// target = relative;
// }
// _camera->setPosition(target);
//
// unlockControls();
//}
void InteractionHandler::orbitDelta(const glm::quat& rotation)
{
lockControls();
// the camera position
psc relative = _camera->position();
// should be changed to something more dynamic =)
psc origin;
if (_focusNode) {
origin = _focusNode->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;
glm::mat4 la = glm::lookAt(_camera->position().vec3(), origin.vec3(), glm::rotate(rotation, glm::vec3(_camera->lookUpVectorCameraSpace())));
unlockControls();
_camera->setPosition(relative);
//camera_->rotate(rotation);
//camera_->setRotation(glm::mat4_cast(rotation));
_camera->setRotation(glm::quat_cast(la));
//camera_->setLookUpVector();
}
//<<<<<<< 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)
{
_camera->rotate(rotation);
}
void InteractionHandler::distanceDelta(const PowerScaledScalar& distance, size_t iterations)
{
if (iterations > 5)
return;
//assert(this_);
lockControls();
psc relative = _camera->position();
const psc origin = (_focusNode) ? _focusNode->worldPosition() : psc();
unlockControls();
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;
if (relative_origin_coordinate.vec4().x == 0.f && relative_origin_coordinate.vec4().y == 0.f && relative_origin_coordinate.vec4().z == 0.f)
// TODO: this shouldn't be allowed to happen; a mechanism to prevent the camera to coincide with the origin is necessary (ab)
return;
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);
}
else {
PowerScaledScalar d2 = distance;
d2[0] *= 0.75f;
d2[1] *= 0.85f;
distanceDelta(d2, iterations + 1);
}
}
void InteractionHandler::lookAt(const glm::quat& rotation)
{
}
void InteractionHandler::keyboardCallback(Key key, KeyModifier modifier, KeyAction action) {
// TODO package in script
const float speed = _controllerSensitivity;
const float dt = static_cast<float>(_deltaTime);
if (action == KeyAction::Press || action == KeyAction::Repeat) {
if ((key == Key::Right) && (modifier == KeyModifier::NoModifier)) {
glm::vec3 euler(0.0, speed * dt*0.4, 0.0);
glm::quat rot = glm::quat(euler);
rotateDelta(rot);
}
if ((key == Key::Left) && (modifier == KeyModifier::NoModifier)) {
glm::vec3 euler(0.0, -speed * dt*0.4, 0.0);
glm::quat rot = glm::quat(euler);
rotateDelta(rot);
}
if ((key == Key::Down) && (modifier == KeyModifier::NoModifier)) {
glm::vec3 euler(speed * dt*0.4, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
rotateDelta(rot);
}
if ((key == Key::Up) && (modifier == KeyModifier::NoModifier)) {
glm::vec3 euler(-speed * dt*0.4, 0.0, 0.0);
glm::quat rot = glm::quat(euler);
rotateDelta(rot);
}
if ((key == Key::KeypadSubtract) && (modifier == KeyModifier::NoModifier)) {
glm::vec2 s = OsEng.renderEngine().camera()->scaling();
s[1] -= 0.5f;
OsEng.renderEngine().camera()->setScaling(s);
}
if ((key == Key::KeypadAdd) && (modifier == KeyModifier::NoModifier)) {
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, modifier });
for (auto it = ret.first; it != ret.second; ++it) {
//OsEng.scriptEngine()->runScript(it->second);
OsEng.scriptEngine().queueScript(it->second);
//if (!_validKeyLua) {
// break;
//}
}
}
}
void InteractionHandler::resetKeyBindings() {
_keyLua.clear();
//_validKeyLua = false;
}
void InteractionHandler::bindKey(Key key, KeyModifier modifier, std::string lua) {
_keyLua.insert({
{key, modifier},
lua
});
}
scripting::LuaLibrary InteractionHandler::luaLibrary() {
return {
"",
{
{
"clearKeys",
&luascriptfunctions::clearKeys,
"",
"Clear all key bindings"
},
{
"bindKey",
&luascriptfunctions::bindKey,
"string, string",
"Binds a key by name to a lua string command"
},
{
"dt",
&luascriptfunctions::dt,
"",
"Get current frame time"
},
{
"distance",
&luascriptfunctions::distance,
"number",
"Change distance to origin",
true
},
{
"setInteractionSensitivity",
&luascriptfunctions::setInteractionSensitivity,
"number",
"Sets the global interaction sensitivity"
},
{
"interactionSensitivity",
&luascriptfunctions::interactionSensitivity,
"",
"Gets the current global interaction sensitivity"
},
{
"setInvertRoll",
&luascriptfunctions::setInvertRoll,
"bool",
"Sets the setting if roll movements are inverted"
},
{
"invertRoll",
&luascriptfunctions::invertRoll,
"",
"Returns the status of roll movement inversion"
},
{
"setInvertRotation",
&luascriptfunctions::setInvertRotation,
"bool",
"Sets the setting if rotation movements are inverted"
},
{
"invertRotation",
&luascriptfunctions::invertRotation,
"",
"Returns the status of rotation movement inversion"
}
}
};
}
void InteractionHandler::setRotation(const glm::quat& rotation)
{
_camera->setRotation(rotation);
}
double InteractionHandler::deltaTime() const {
return _deltaTime;
}
void InteractionHandler::setInteractionSensitivity(float sensitivity) {
_controllerSensitivity = sensitivity;
}
float InteractionHandler::interactionSensitivity() const {
return _controllerSensitivity;
}
void InteractionHandler::setInvertRoll(bool invert) {
_invertRoll = invert;
}
bool InteractionHandler::invertRoll() const {
return _invertRoll;
}
void InteractionHandler::setInvertRotation(bool invert) {
_invertRotation = invert;
}
bool InteractionHandler::invertRotation() const {
return _invertRotation;
}
void InteractionHandler::addKeyframe(const network::datamessagestructures::PositionKeyframe &kf){
_keyframeMutex.lock();
//save a maximum of 10 samples (1 seconds of buffer)
if (_keyframes.size() >= 10){
_keyframes.erase(_keyframes.begin());
}
_keyframes.push_back(kf);
_keyframeMutex.unlock();
}
void InteractionHandler::clearKeyframes(){
_keyframeMutex.lock();
_keyframes.clear();
_keyframeMutex.unlock();
}
#else // USE_OLD_INTERACTIONHANDLER
// InteractionHandler
InteractionHandler::InteractionHandler()
: _origin("origin", "Origin", "")
@@ -672,6 +104,11 @@ InteractionHandler::InteractionHandler()
"GlobeBrowsing",
std::make_shared<GlobeBrowsingInteractionMode>(_mouseStates)
));
_interactionModes.insert(
std::pair<std::string, std::shared_ptr<InteractionMode>>(
"Keyframe",
std::make_shared<KeyframeInteractionMode>()
));
// Set the interactionMode
_currentInteractionMode = _interactionModes["Orbital"];
@@ -708,6 +145,25 @@ InteractionHandler::~InteractionHandler() {
}
void InteractionHandler::initialize() {
OsEng.parallelConnection().connectionEvent()->subscribe("interactionHandler", "statusChanged", [this]() {
if (OsEng.parallelConnection().status() == network::Status::ClientWithHost) {
setInteractionMode("Keyframe");
} else {
auto keyframeModeIter = _interactionModes.find("Keyframe");
if (keyframeModeIter != _interactionModes.end()) {
if (_currentInteractionMode == keyframeModeIter->second) {
setInteractionMode("Orbital");
}
}
}
});
}
void InteractionHandler::deinitialize() {
OsEng.parallelConnection().connectionEvent()->unsubscribe("interactionHandler");
}
void InteractionHandler::setFocusNode(SceneGraphNode* node) {
_currentInteractionMode->setFocusNode(node);
}
@@ -831,8 +287,10 @@ void InteractionHandler::keyboardCallback(Key key, KeyModifier modifier, KeyActi
// iterate over key bindings
auto ret = _keyLua.equal_range({ key, modifier });
for (auto it = ret.first; it != ret.second; ++it) {
//OsEng.scriptEngine()->runScript(it->second);
OsEng.scriptEngine().queueScript(it->second);
OsEng.scriptEngine().queueScript(it->second.first,
it->second.second ?
scripting::ScriptEngine::RemoteScripting::Yes :
scripting::ScriptEngine::RemoteScripting::No);
}
}
}
@@ -936,12 +394,20 @@ void InteractionHandler::resetKeyBindings() {
_keyLua.clear();
}
void InteractionHandler::bindKeyLocal(Key key, KeyModifier modifier, std::string lua) {
_keyLua.insert({
{ key, modifier },
std::make_pair(lua, false)
});
}
void InteractionHandler::bindKey(Key key, KeyModifier modifier, std::string lua) {
_keyLua.insert({
{ key, modifier },
lua
std::make_pair(lua, true)
});
}
void InteractionHandler::writeKeyboardDocumentation(const std::string& type, const std::string& file)
{
@@ -951,8 +417,14 @@ void InteractionHandler::writeKeyboardDocumentation(const std::string& type, con
f.open(absPath(file));
for (const auto& p : _keyLua) {
std::string remoteScriptingInfo;
bool remoteScripting = p.second.second;
if (!remoteScripting) {
remoteScriptingInfo = " (LOCAL)";
}
f << std::to_string(p.first) << ": " <<
p.second << std::endl;
p.second.first << remoteScriptingInfo << std::endl;
}
}
else if (type == "html") {
@@ -996,7 +468,8 @@ void InteractionHandler::writeKeyboardDocumentation(const std::string& type, con
first = false;
json << "{";
json << "\"key\": \"" << std::to_string(p.first) << "\",";
json << "\"script\": \"" << p.second << "\"";
json << "\"script\": \"" << p.second.first << "\"";
json << "\"remoteScripting\": \"" << (p.second.second ? "true" : "false") << "\"";
json << "}";
}
json << "]";
@@ -1038,11 +511,13 @@ void InteractionHandler::writeKeyboardDocumentation(const std::string& type, con
f << html.str();
/*
for (const auto& p : _keyLua) {
html << "\t\t<tr>\n"
<< "\t\t\t<td>" << std::to_string(p.first) << "</td>\n"
<< "\t\t\t<td>" << p.second << "</td>\n"
<< "\t\t\t<td>" << p.second.first << "</td>\n"
<< "\t\t\t<td>" << (p.second.second ? "Yes" : "No") << "</td>\n"
<< "\t\t</tr>\n";
}*/
}
@@ -1068,7 +543,14 @@ scripting::LuaLibrary InteractionHandler::luaLibrary() {
"bindKey",
&luascriptfunctions::bindKey,
"string, string",
"Binds a key by name to a lua string command"
"Binds a key by name to a lua string command to execute both locally "
"and to broadcast to clients if this is the host of a parallel session"
},
{
"bindKeyLocal",
&luascriptfunctions::bindKeyLocal,
"string, string",
"Binds a key by name to a lua string command to execute only locally"
},
{
"setInteractionMode",
@@ -1098,7 +580,7 @@ scripting::LuaLibrary InteractionHandler::luaLibrary() {
};
}
void InteractionHandler::addKeyframe(const network::datamessagestructures::PositionKeyframe &kf) {
void InteractionHandler::addKeyframe(const network::datamessagestructures::CameraKeyframe &kf) {
_inputState->addKeyframe(kf);
}
@@ -1106,21 +588,5 @@ void InteractionHandler::clearKeyframes() {
_inputState->clearKeyframes();
}
//void InteractionHandler::serialize(SyncBuffer* syncBuffer) {
// for (auto var : _interactionModes)
// {
// var.second->serialize(syncBuffer);
// }
//}
//
//void InteractionHandler::deserialize(SyncBuffer* syncBuffer) {
// for (auto var : _interactionModes)
// {
// var.second->deserialize(syncBuffer);
// }
//}
#endif // USE_OLD_INTERACTIONHANDLER
} // namespace interaction
} // namespace openspace
+39 -114
View File
@@ -60,7 +60,9 @@ int setOrigin(lua_State* L) {
/**
* \ingroup LuaScripts
* bindKey():
* Binds a key to Lua command
* Binds a key to Lua command to both execute locally
* and broadcast to all clients if this node is hosting
* a parallel connection.
*/
int bindKey(lua_State* L) {
using ghoul::lua::luaTypeToString;
@@ -93,6 +95,42 @@ int bindKey(lua_State* L) {
return 0;
}
/**
* \ingroup LuaScripts
* bindKey():
* Binds a key to Lua command to execute only locally
*/
int bindKeyLocal(lua_State* L) {
using ghoul::lua::luaTypeToString;
int nArguments = lua_gettop(L);
if (nArguments != 2)
return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments);
std::string key = luaL_checkstring(L, -2);
std::string command = luaL_checkstring(L, -1);
if (command.empty())
return luaL_error(L, "Command string is empty");
openspace::KeyWithModifier iKey = openspace::stringToKey(key);
if (iKey.key == openspace::Key::Unknown) {
LERRORC("lua.bindKey", "Could not find key '" << key << "'");
return 0;
}
OsEng.interactionHandler().bindKeyLocal(
iKey.key,
iKey.modifier,
command
);
return 0;
}
/**
* \ingroup LuaScripts
* clearKeys():
@@ -176,120 +214,7 @@ int resetCameraDirection(lua_State* L) {
OsEng.interactionHandler().resetCameraDirection();
}
#ifdef USE_OLD_INTERACTIONHANDLER
/**
* \ingroup LuaScripts
* dt(bool):
* Get current frame time
*/
int dt(lua_State* L) {
/*
int nArguments = lua_gettop(L);
if (nArguments != 0)
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
lua_pushnumber(L,OsEng.interactionHandler().deltaTime());
*/return 1;
}
/**
* \ingroup LuaScripts
* distance(double, double):
* Change distance to origin
*/
int distance(lua_State* L) {
/*
int nArguments = lua_gettop(L);
if (nArguments != 2)
return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments);
double d1 = luaL_checknumber(L, -2);
double d2 = luaL_checknumber(L, -1);
PowerScaledScalar dist(static_cast<float>(d1), static_cast<float>(d2));
OsEng.interactionHandler().distanceDelta(dist);
*/
return 0;
}
/**
* \ingroup LuaScripts
* setInteractionSensitivity(double):
* Changes the global interaction sensitivity to the passed value
*/
int setInteractionSensitivity(lua_State* L) {
int nArguments = lua_gettop(L);
if (nArguments != 1)
return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments);
float sensitivity = static_cast<float>(luaL_checknumber(L, -1));
//OsEng.interactionHandler().setInteractionSensitivity(sensitivity);
return 0;
}
/**
* \ingroup LuaScripts
* interactionSensitivity():
* Returns the current, global interaction sensitivity
*/
int interactionSensitivity(lua_State* L) {
//float sensitivity = OsEng.interactionHandler().interactionSensitivity();
//lua_pushnumber(L, sensitivity);
return 1;
}
/**
* \ingroup LuaScripts
* setInvertRoll(bool):
* Determines if the roll movement is inverted
*/
int setInvertRoll(lua_State* L) {
int nArguments = lua_gettop(L);
if (nArguments != 1)
return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments);
bool invert = lua_toboolean(L, -1) == 1;
//OsEng.interactionHandler().setInvertRoll(invert);
return 0;
}
/**
* \ingroup LuaScripts
* invertRoll():
* Returns the current setting for inversion of roll movement
*/
int invertRoll(lua_State* L) {
//bool invert = OsEng.interactionHandler().invertRoll();
//lua_pushboolean(L, invert);
return 1;
}
/**
* \ingroup LuaScripts
* setInvertRotation(bool):
* Determines if the rotation movement is inverted
*/
int setInvertRotation(lua_State* L) {
int nArguments = lua_gettop(L);
if (nArguments != 1)
return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments);
bool invert = lua_toboolean(L, -1) == 1;
//OsEng.interactionHandler().setInvertRotation(invert);
return 0;
}
/**
* \ingroup LuaScripts
* invertRotation():
* Returns the current setting for inversion of rotation movement
*/
int invertRotation(lua_State* L) {
//bool invert = OsEng.interactionHandler().invertRotation();
//lua_pushboolean(L, invert);
return 1;
}
#endif USE_OLD_INTERACTIONHANDLER
} // namespace luascriptfunctions
} // namespace openspace
+54 -10
View File
@@ -57,22 +57,39 @@ namespace interaction {
}
void InputState::addKeyframe(const network::datamessagestructures::PositionKeyframe &kf) {
_keyframeMutex.lock();
const std::vector<network::datamessagestructures::CameraKeyframe>& InputState::keyframes() const {
return _keyframes;
}
void InputState::addKeyframe(const network::datamessagestructures::CameraKeyframe &kf) {
clearOldKeyframes();
auto compareTimestamps = [](const network::datamessagestructures::CameraKeyframe a,
network::datamessagestructures::CameraKeyframe b) {
return a._timestamp < b._timestamp;
};
// Remove keyframes after the inserted keyframe.
_keyframes.erase(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, compareTimestamps), _keyframes.end());
//save a maximum of 10 samples (1 seconds of buffer)
if (_keyframes.size() >= 10) {
_keyframes.erase(_keyframes.begin());
}
_keyframes.push_back(kf);
}
_keyframeMutex.unlock();
void InputState::clearOldKeyframes() {
double now = OsEng.runTime();
auto isLater = [now](const network::datamessagestructures::CameraKeyframe kf) {
return kf._timestamp > now;
};
// Remote keyframes with earlier timestamps than the current time.
auto nextKeyframe = std::find_if(_keyframes.begin(), _keyframes.end(), isLater);
if (nextKeyframe != _keyframes.begin()) {
_keyframes.erase(_keyframes.begin(), nextKeyframe - 1);
}
}
void InputState::clearKeyframes() {
_keyframeMutex.lock();
_keyframes.clear();
_keyframeMutex.unlock();
}
void InputState::keyboardCallback(Key key, KeyModifier modifier, KeyAction action) {
@@ -175,11 +192,38 @@ KeyframeInteractionMode::~KeyframeInteractionMode() {
}
void KeyframeInteractionMode::updateMouseStatesFromInput(const InputState& inputState, double deltaTime) {
_keyframes = inputState.keyframes();
}
void KeyframeInteractionMode::updateCameraStateFromMouseStates(Camera& camera) {
if (_keyframes.size() == 0) {
return;
}
double now = OsEng.runTime();
auto isLater = [now](const network::datamessagestructures::CameraKeyframe kf) {
return kf._timestamp > now;
};
auto nextKeyframe = std::find_if(_keyframes.begin(), _keyframes.end(), isLater);
if (nextKeyframe == _keyframes.end()) {
return;
}
if (nextKeyframe == _keyframes.begin()) {
camera.setPositionVec3(_keyframes[0]._position);
camera.setRotation(_keyframes[0]._rotation);
return;
}
auto prevKeyframe = nextKeyframe - 1;
double prevTime = prevKeyframe->_timestamp;
double nextTime = nextKeyframe->_timestamp;
double t = (now - prevTime) / (nextTime - prevTime);
camera.setPositionVec3(prevKeyframe->_position * (1 - t) + nextKeyframe->_position * t);
camera.setRotation(glm::slerp(prevKeyframe->_rotation, nextKeyframe->_rotation, t));
}
// OrbitalInteractionMode
+44 -4
View File
@@ -58,6 +58,7 @@ LuaConsole::LuaConsole()
, _filename("")
, _autoCompleteInfo({NoAutoComplete, false, ""})
, _isVisible(false)
, _remoteScripting(true)
{
// _commands.push_back("");
// _activeCommand = _commands.size() - 1;
@@ -89,6 +90,13 @@ void LuaConsole::initialize() {
}
_commands.push_back("");
_activeCommand = _commands.size() - 1;
OsEng.parallelConnection().connectionEvent()->subscribe("luaConsole",
"statusChanged", [this]() {
network::Status status = OsEng.parallelConnection().status();
parallelConnectionChanged(status);
});
}
void LuaConsole::deinitialize() {
@@ -102,6 +110,8 @@ void LuaConsole::deinitialize() {
file.write(s.c_str(), length);
}
}
OsEng.parallelConnection().connectionEvent()->unsubscribe("luaConsole");
}
void LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction action) {
@@ -169,7 +179,8 @@ void LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction actio
else {
std::string cmd = _commands.at(_activeCommand);
if (cmd != "") {
OsEng.scriptEngine().queueScript(cmd);
OsEng.scriptEngine().queueScript(cmd,
_remoteScripting ? scripting::ScriptEngine::RemoteScripting::Yes : scripting::ScriptEngine::RemoteScripting::No);
// Only add the current command to the history if it hasn't been
// executed before. We don't want two of the same commands in a row
@@ -310,13 +321,28 @@ void LuaConsole::render() {
startY = startY - font_size * 15.0f * 2.0f;
const glm::vec4 red(1, 0, 0, 1);
const glm::vec4 lightBlue(0.4, 0.4, 1, 1);
const glm::vec4 green(0, 1, 0, 1);
const glm::vec4 white(1, 1, 1, 1);
std::shared_ptr<ghoul::fontrendering::Font> font = OsEng.fontManager().font("Mono", font_size);
using ghoul::fontrendering::RenderFont;
RenderFont(*font, glm::vec2(15.f, startY), red, "$");
if (_remoteScripting) {
int nClients = OsEng.parallelConnection().nConnections() - 1;
if (nClients == 1) {
RenderFont(*font, glm::vec2(15.f, startY + 20.0f), red, "Broadcasting script to 1 client");
} else {
RenderFont(*font, glm::vec2(15.f, startY + 20.0f), red, ("Broadcasting script to " + std::to_string(nClients) + " clients").c_str());
}
RenderFont(*font, glm::vec2(15.f, startY), red, "$");
}
else {
if (OsEng.parallelConnection().isHost()) {
RenderFont(*font, glm::vec2(15.f, startY + 20.0f), lightBlue, "Local script execution");
}
RenderFont(*font, glm::vec2(15.f, startY), lightBlue, "$");
}
RenderFont(*font, glm::vec2(15.f + font_size, startY), white, "%s", _commands.at(_activeCommand).c_str());
size_t n = std::count(_commands.at(_activeCommand).begin(), _commands.at(_activeCommand).begin() + _inputPosition, '\n');
@@ -391,10 +417,24 @@ void LuaConsole::setVisible(bool visible) {
_isVisible = visible;
}
void LuaConsole::toggleVisibility() {
_isVisible = !_isVisible;
void LuaConsole::toggleMode() {
if (_isVisible) {
if (_remoteScripting) {
_remoteScripting = false;
} else {
_isVisible = false;
}
} else {
_remoteScripting = OsEng.parallelConnection().isHost();
_isVisible = true;
}
}
void LuaConsole::parallelConnectionChanged(const network::Status& status) {
_remoteScripting = status == network::Status::Host;
}
scripting::LuaLibrary LuaConsole::luaLibrary() {
return {
"console",
+1 -1
View File
@@ -64,7 +64,7 @@ int toggle(lua_State* L) {
if (nArguments != 0)
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
OsEng.console().toggleVisibility();
OsEng.console().toggleMode();
return 0;
}
+1 -1
View File
@@ -67,7 +67,7 @@ bool NetworkEngine::handleMessage(const std::string& message) {
{
std::string script = message.substr(1);
//LINFO("Received Lua Script: '" << script << "'");
OsEng.scriptEngine().queueScript(script);
OsEng.scriptEngine().queueScript(script, scripting::ScriptEngine::RemoteScripting::No);
return true;
}
case MessageTypeExternalControlConnected:
File diff suppressed because it is too large Load Diff
+11
View File
@@ -184,6 +184,17 @@ int requestHostship(lua_State* L) {
return 0;
}
int resignHostship(lua_State* L) {
int nArguments = lua_gettop(L);
if (nArguments != 0)
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
if (OsEng.isMaster()) {
OsEng.parallelConnection().resignHostship();
}
return 0;
}
} // namespace luascriptfunctions
} // namespace openspace
+42 -6
View File
@@ -753,23 +753,20 @@ scripting::LuaLibrary RenderEngine::luaLibrary() {
"toggleFade",
&luascriptfunctions::toggleFade,
"number",
"Toggles fading in or out",
true
"Toggles fading in or out"
},
{
"fadeIn",
&luascriptfunctions::fadeIn,
"number",
"",
true
""
},
//also temporary @JK
{
"fadeOut",
&luascriptfunctions::fadeOut,
"number",
"",
true
""
},
{
"registerScreenSpaceRenderable",
@@ -1329,6 +1326,45 @@ void RenderEngine::renderInformation() {
break;
}
network::Status status = OsEng.parallelConnection().status();
size_t nConnections = OsEng.parallelConnection().nConnections();
const std::string& hostName = OsEng.parallelConnection().hostName();
std::string connectionInfo = "";
int nClients = nConnections;
if (status == network::Status::Host) {
nClients--;
if (nClients == 1) {
connectionInfo = "Hosting session with 1 client";
} else {
connectionInfo = "Hosting session with " + std::to_string(nClients) + " clients";
}
} else if (status == network::Status::ClientWithHost) {
nClients--;
connectionInfo = "Session hosted by '" + hostName + "'";
} else if (status == network::Status::ClientWithoutHost) {
connectionInfo = "Host is disconnected";
}
if (status == network::Status::ClientWithHost || status == network::Status::ClientWithoutHost) {
connectionInfo += "\n";
if (nClients > 2) {
connectionInfo += "You and " + std::to_string(nClients - 1) + " more clients are tuned in";
} else if (nClients == 2) {
connectionInfo += "You and " + std::to_string(nClients - 1) + " more client are tuned in";
} else if (nClients == 1) {
connectionInfo += "You are the only client";
}
}
if (connectionInfo != "") {
RenderFontCr(*_fontInfo,
penPosition,
connectionInfo.c_str()
);
}
#ifdef OPENSPACE_MODULE_NEWHORIZONS_ENABLED
//<<<<<<< HEAD
bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons");
+1 -1
View File
@@ -159,7 +159,7 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary
_delete.onChange([this](){
std::string script =
"openspace.unregisterScreenSpaceRenderable('" + name() + "');";
OsEng.scriptEngine().queueScript(script);
OsEng.scriptEngine().queueScript(script, scripting::ScriptEngine::RemoteScripting::Yes);
});
}
-1
View File
@@ -669,7 +669,6 @@ scripting::LuaLibrary Scene::luaLibrary() {
"Sets a property identified by the URI in "
"the first argument. The second argument can be any type, but it has to "
"match the type that the property expects.",
true
},
{
"getPropertyValue",
+3 -3
View File
@@ -52,10 +52,10 @@ void applyRegularExpression(lua_State* L, std::regex regex, std::vector<properti
//ensure properties are synced over parallel connection
std::string value;
prop->getStringValue(value);
OsEng.parallelConnection().scriptMessage(
/* OsEng.parallelConnection().scriptMessage(
prop->fullyQualifiedIdentifier(),
value
);
);*/
}
}
@@ -101,7 +101,7 @@ int property_setValueSingle(lua_State* L) {
//ensure properties are synced over parallel connection
std::string value;
prop->getStringValue(value);
OsEng.parallelConnection().scriptMessage(prop->fullyQualifiedIdentifier(), value);
//OsEng.parallelConnection().scriptMessage(prop->fullyQualifiedIdentifier(), value);
}
return 0;
+24 -25
View File
@@ -166,16 +166,7 @@ bool ScriptEngine::runScript(const std::string& script) {
LERRORC(e.component, e.message);
return false;
}
// if we're currently hosting the parallel session, find out if script should be synchronized.
if (OsEng.parallelConnection().isHost()) {
std::string lib, func;
if (parseLibraryAndFunctionNames(lib, func, script) && shouldScriptBeSent(lib, func)){
// OsEng.parallelConnection()->sendScript(script);
// cacheScript(lib, func, script);
}
}
return true;
}
@@ -204,7 +195,7 @@ bool ScriptEngine::runScriptFile(const std::string& filename) {
return true;
}
bool ScriptEngine::shouldScriptBeSent(const std::string& library, const std::string& function) {
/*bool ScriptEngine::shouldScriptBeSent(const std::string& library, const std::string& function) {
std::set<LuaLibrary>::const_iterator libit;
for (libit = _registeredLibraries.cbegin();
libit != _registeredLibraries.cend();
@@ -229,9 +220,9 @@ bool ScriptEngine::shouldScriptBeSent(const std::string& library, const std::str
}
return false;
}
}*/
void ScriptEngine::cacheScript(const std::string &library, const std::string &function, const std::string &script){
/*void ScriptEngine::cacheScript(const std::string &library, const std::string &function, const std::string &script){
_cachedScriptsMutex.lock();
_cachedScripts[library][function] = script;
_cachedScriptsMutex.unlock();
@@ -256,8 +247,9 @@ std::vector<std::string> ScriptEngine::cachedScripts(){
_cachedScriptsMutex.unlock();
return retVal;
}
}*/
/*
bool ScriptEngine::parseLibraryAndFunctionNames(std::string &library, std::string &function, const std::string &script){
//"deconstruct the script to find library and function name
@@ -299,7 +291,7 @@ bool ScriptEngine::parseLibraryAndFunctionNames(std::string &library, std::strin
//if we found a function all is good
return !function.empty();
}
*/
bool ScriptEngine::isLibraryNameAllowed(lua_State* state, const std::string& name) {
bool result = false;
lua_getglobal(state, _openspaceLibraryName.c_str());
@@ -793,20 +785,27 @@ bool ScriptEngine::writeLog(const std::string& script) {
}
void ScriptEngine::presync(bool isMaster) {
if (isMaster) {
_mutex.lock();
if (!isMaster) return;
if (!_queuedScripts.empty()) {
_currentSyncedScript = _queuedScripts.back();
_queuedScripts.pop_back();
_mutex.lock();
//Not really a received script but the master also needs to run the script...
_receivedScripts.push_back(_currentSyncedScript);
if (!_queuedScripts.empty()) {
_currentSyncedScript = _queuedScripts.back().first;
bool remoteScripting = _queuedScripts.back().second;
//Not really a received script but the master also needs to run the script...
_receivedScripts.push_back(_currentSyncedScript);
_queuedScripts.pop_back();
if (OsEng.parallelConnection().isHost() && remoteScripting) {
OsEng.parallelConnection().sendScript(_currentSyncedScript);
}
_mutex.unlock();
}
_mutex.unlock();
}
void ScriptEngine::encode(SyncBuffer* syncBuffer) {
@@ -843,13 +842,13 @@ void ScriptEngine::postsync(bool isMaster) {
}
}
void ScriptEngine::queueScript(const std::string &script){
void ScriptEngine::queueScript(const std::string &script, ScriptEngine::RemoteScripting remoteScripting){
if (script.empty())
return;
_mutex.lock();
_queuedScripts.insert(_queuedScripts.begin(), script);
_queuedScripts.insert(_queuedScripts.begin(), std::make_pair(script, remoteScripting));
_mutex.unlock();
}
+4 -8
View File
@@ -179,8 +179,7 @@ scripting::LuaLibrary Time::luaLibrary() {
&luascriptfunctions::time_setDeltaTime,
"number",
"Sets the amount of simulation time that happens "
"in one second of real time",
true
"in one second of real time"
},
{
"deltaTime",
@@ -193,16 +192,14 @@ scripting::LuaLibrary Time::luaLibrary() {
"setPause",
&luascriptfunctions::time_setPause,
"bool",
"Pauses the simulation time or restores the delta time",
true
"Pauses the simulation time or restores the delta time"
},
{
"togglePause",
&luascriptfunctions::time_togglePause,
"",
"Toggles the pause function, i.e. temporarily setting the delta time to 0"
" and restoring it afterwards",
true
" and restoring it afterwards"
},
{
"setTime",
@@ -211,8 +208,7 @@ scripting::LuaLibrary Time::luaLibrary() {
"Sets the current simulation time to the "
"specified value. If the parameter is a number, the value is the number "
"of seconds past the J2000 epoch. If it is a string, it has to be a "
"valid ISO 8601 date string (YYYY-MM-DDTHH:MN:SS)",
true
"valid ISO 8601 date string (YYYY-MM-DDTHH:MN:SS)"
},
{
"currentTime",
+153
View File
@@ -0,0 +1,153 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* 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 <openspace/util/timemanager.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/util/time.h>
namespace {
double SecondsOffTolerance = 0.1;
}
namespace openspace {
using network::datamessagestructures::TimeKeyframe;
void TimeManager::preSynchronization(double dt) {
double now = OsEng.runTime();
removeKeyframesBefore(_latestConsumedTimestamp);
if (_keyframes.size() == 0) {
Time::ref().advanceTime(dt);
} else {
consumeKeyframes(dt);
}
}
void TimeManager::consumeKeyframes(double dt) {
double now = OsEng.runTime();
TimeKeyframe kf;
kf._timestamp = now;
auto firstFutureKeyframe = std::lower_bound(_keyframes.begin(), _keyframes.end(), kf, &TimeManager::compareKeyframeTimes);
bool consumingTimeJump = std::find_if(_keyframes.begin(), firstFutureKeyframe, [] (const TimeKeyframe& f) {
return f._requiresTimeJump;
}) != firstFutureKeyframe;
Time& time = Time::ref();
if (firstFutureKeyframe == _keyframes.end()) {
// All keyframes are in the past.
// Consume the latest one.
TimeKeyframe& current = _keyframes.back();
time.setTime(current._time, consumingTimeJump);
time.setDeltaTime(current._dt);
time.setPause(current._paused);
_latestConsumedTimestamp = current._timestamp;
}
else {
TimeKeyframe& next = *firstFutureKeyframe;
if (firstFutureKeyframe != _keyframes.begin()) {
TimeKeyframe& latest = *(firstFutureKeyframe - 1);
// In case of unconsumed passed keyframes, let the last one
// determine whether the time should be paused or not.
// If there was a time jump or time is paused, apply it directly.
// Then consume the last keyframe.
time.setPause(latest._paused);
time.setTimeJumped(consumingTimeJump);
time.setDeltaTime(latest._dt);
if (consumingTimeJump || latest._paused) {
time.setTime(latest._time, consumingTimeJump);
}
_latestConsumedTimestamp = latest._timestamp;
}
// Do not interpolate with time jumping keyframes.
// Instead, wait until their timestamp and apply them directly.
if (next._requiresTimeJump) {
Time::ref().advanceTime(dt);
return;
}
if (time.paused()) {
return;
}
double predictedTime = time.j2000Seconds() + time.deltaTime() * (next._timestamp - now);
bool withinTolerance = std::abs(predictedTime - next._time) < std::abs(next._dt * SecondsOffTolerance);
if (next._dt == time.deltaTime() && withinTolerance) {
Time::ref().advanceTime(dt);
return;
}
double t0 = now - dt;
double t1 = now;
double t2 = next._timestamp;
double parameter = (t1 - t0) / (t2 - t0);
double y0 = time.j2000Seconds();
double yPrime0 = time.deltaTime();
double y2 = next._time;
double yPrime2 = next._dt;
double y1 = (1 - parameter) * y0 + parameter * y2;
double y1Prime = (y1 - y0) / dt;
time.setDeltaTime(y1Prime);
time.setTime(y1, false);
}
}
void TimeManager::addKeyframe(const TimeKeyframe& kf) {
if (kf._timestamp < OsEng.runTime()) {
return;
}
auto iter = std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &TimeManager::compareKeyframeTimes);
_keyframes.insert(iter, kf);
}
void TimeManager::removeKeyframesBefore(double timestamp) {
network::datamessagestructures::TimeKeyframe kf;
kf._timestamp = timestamp;
auto iter = std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &TimeManager::compareKeyframeTimes);
_keyframes.erase(_keyframes.begin(), iter);
}
void TimeManager::clearKeyframes() {
_keyframes.clear();
}
bool TimeManager::compareKeyframeTimes(const TimeKeyframe& a, const TimeKeyframe& b)
{
return a._timestamp < b._timestamp;
}
}