mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-12 14:29:42 -05:00
Merge branch 'feature/parallelconnection' into develop
Conflicts: src/interaction/interactionhandler.cpp
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();")
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
+435
-477
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user