mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-03-08 22:38:42 -05:00
Event System (#1741)
* Add implementation of the EventEngine to handle global event chains * Add properties to SceneGraphNodes to determine two distance radii for camera-based events
This commit is contained in:
@@ -43,6 +43,9 @@ set(OPENSPACE_SOURCE
|
||||
${OPENSPACE_BASE_DIR}/src/engine/openspaceengine_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/engine/syncengine.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/engine/virtualpropertymanager.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/events/event.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/events/eventengine.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/events/eventengine_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/interaction/actionmanager.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/interaction/actionmanager_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/interaction/camerainteractionstates.cpp
|
||||
@@ -176,6 +179,7 @@ set(OPENSPACE_SOURCE
|
||||
${OPENSPACE_BASE_DIR}/src/util/spicemanager_lua.inl
|
||||
${OPENSPACE_BASE_DIR}/src/util/syncbuffer.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/synchronizationwatcher.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/tstring.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/histogram.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/task.cpp
|
||||
${OPENSPACE_BASE_DIR}/src/util/taskloader.cpp
|
||||
@@ -223,6 +227,9 @@ set(OPENSPACE_HEADER
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/syncengine.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/virtualpropertymanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/engine/windowdelegate.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/events/event.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/events/eventengine.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/events/eventengine.inl
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/interaction/action.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/interaction/actionmanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/interaction/delayedvariable.h
|
||||
@@ -381,6 +388,7 @@ set(OPENSPACE_HEADER
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/timemanager.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/timerange.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/touch.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/tstring.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/universalhelpers.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/updatestructures.h
|
||||
${OPENSPACE_BASE_DIR}/include/openspace/util/versionchecker.h
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <openspace/engine/logfactory.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <openspace/interaction/actionmanager.h>
|
||||
#include <openspace/interaction/keybindingmanager.h>
|
||||
#include <openspace/interaction/sessionrecording.h>
|
||||
@@ -77,13 +78,14 @@ void registerCoreClasses(documentation::DocumentationEngine& engine) {
|
||||
// documentation version.
|
||||
void registerCoreClasses(scripting::ScriptEngine& engine) {
|
||||
engine.addLibrary(Dashboard::luaLibrary());
|
||||
engine.addLibrary(EventEngine::luaLibrary());
|
||||
engine.addLibrary(MissionManager::luaLibrary());
|
||||
engine.addLibrary(ModuleEngine::luaLibrary());
|
||||
engine.addLibrary(OpenSpaceEngine::luaLibrary());
|
||||
engine.addLibrary(ParallelPeer::luaLibrary());
|
||||
engine.addLibrary(Profile::luaLibrary());
|
||||
engine.addLibrary(RenderEngine::luaLibrary());
|
||||
engine.addLibrary(SpiceManager::luaLibrary());
|
||||
engine.addLibrary(Profile::luaLibrary());
|
||||
engine.addLibrary(Scene::luaLibrary());
|
||||
engine.addLibrary(Time::luaLibrary());
|
||||
engine.addLibrary(interaction::ActionManager::luaLibrary());
|
||||
|
||||
@@ -295,6 +295,11 @@ namespace {
|
||||
// 'false'
|
||||
std::optional<bool> logEachOpenGLCall;
|
||||
|
||||
// Determines whether events are printed as debug messages to the console each
|
||||
// frame. If this value is set it determines the default value of the property of
|
||||
// the OpenSpaceEngine with the same name
|
||||
std::optional<bool> printEvents;
|
||||
|
||||
// This value determines whether the initialization of the scene graph should
|
||||
// occur multithreaded, that is, whether multiple scene graph nodes should
|
||||
// initialize in parallel. The only use for this value is to disable it for
|
||||
@@ -391,6 +396,7 @@ void parseLuaState(Configuration& configuration) {
|
||||
p.useMultithreadedInitialization.value_or(c.useMultithreadedInitialization);
|
||||
c.isCheckingOpenGLState = p.checkOpenGLState.value_or(c.isCheckingOpenGLState);
|
||||
c.isLoggingOpenGLCalls = p.logEachOpenGLCall.value_or(c.isLoggingOpenGLCalls);
|
||||
c.isPrintingEvents = p.printEvents.value_or(c.isPrintingEvents);
|
||||
c.shutdownCountdown = p.shutdownCountdown.value_or(c.shutdownCountdown);
|
||||
c.shouldUseScreenshotDate = p.screenshotUseDate.value_or(c.shouldUseScreenshotDate);
|
||||
if (p.onScreenTextScaling.has_value()) {
|
||||
|
||||
@@ -24,14 +24,15 @@
|
||||
|
||||
#include <openspace/engine/globals.h>
|
||||
|
||||
#include <openspace/engine/downloadmanager.h>
|
||||
#include <openspace/engine/configuration.h>
|
||||
#include <openspace/engine/downloadmanager.h>
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/syncengine.h>
|
||||
#include <openspace/engine/virtualpropertymanager.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <openspace/interaction/actionmanager.h>
|
||||
#include <openspace/interaction/interactionmonitor.h>
|
||||
#include <openspace/interaction/keybindingmanager.h>
|
||||
@@ -71,12 +72,13 @@ namespace {
|
||||
// in some random global randoms
|
||||
#ifdef WIN32
|
||||
constexpr const int TotalSize =
|
||||
sizeof(MemoryManager) +
|
||||
sizeof(EventEngine) +
|
||||
sizeof(ghoul::fontrendering::FontManager) +
|
||||
sizeof(Dashboard) +
|
||||
sizeof(DeferredcasterManager) +
|
||||
sizeof(DownloadManager) +
|
||||
sizeof(LuaConsole) +
|
||||
sizeof(MemoryManager) +
|
||||
sizeof(MissionManager) +
|
||||
sizeof(ModuleEngine) +
|
||||
sizeof(OpenSpaceEngine) +
|
||||
@@ -119,6 +121,22 @@ void create() {
|
||||
std::byte* currentPos = DataStorage.data();
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef WIN32
|
||||
memoryManager = new (currentPos) MemoryManager;
|
||||
ghoul_assert(memoryManager, "No memoryManager");
|
||||
currentPos += sizeof(MemoryManager);
|
||||
#else // ^^^ WIN32 / !WIN32 vvv
|
||||
memoryManager = new MemoryManager;
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef WIN32
|
||||
eventEngine = new (currentPos) EventEngine;
|
||||
ghoul_assert(eventEngine, "No eventEngine");
|
||||
currentPos += sizeof(EventEngine);
|
||||
#else // ^^^ WIN32 / !WIN32 vvv
|
||||
downloadManager = new EventEngine;
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef WIN32
|
||||
fontManager = new (currentPos) ghoul::fontrendering::FontManager({ 1536, 1536, 1 });
|
||||
ghoul_assert(fontManager, "No fontManager");
|
||||
@@ -159,14 +177,6 @@ void create() {
|
||||
luaConsole = new LuaConsole;
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef WIN32
|
||||
memoryManager = new (currentPos) MemoryManager;
|
||||
ghoul_assert(memoryManager, "No memoryManager");
|
||||
currentPos += sizeof(MemoryManager);
|
||||
#else // ^^^ WIN32 / !WIN32 vvv
|
||||
memoryManager = new MemoryManager;
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef WIN32
|
||||
missionManager = new (currentPos) MissionManager;
|
||||
ghoul_assert(missionManager, "No missionManager");
|
||||
@@ -573,13 +583,6 @@ void destroy() {
|
||||
delete missionManager;
|
||||
#endif // WIN32
|
||||
|
||||
LDEBUGC("Globals", "Destroying 'MemoryManager'");
|
||||
#ifdef WIN32
|
||||
memoryManager->~MemoryManager();
|
||||
#else // ^^^ WIN32 / !WIN32 vvv
|
||||
delete memoryManager;
|
||||
#endif // WIN32
|
||||
|
||||
LDEBUGC("Globals", "Destroying 'LuaConsole'");
|
||||
#ifdef WIN32
|
||||
luaConsole->~LuaConsole();
|
||||
@@ -615,6 +618,20 @@ void destroy() {
|
||||
delete fontManager;
|
||||
#endif // WIN32
|
||||
|
||||
LDEBUGC("Globals", "Destroying 'EventEngine'");
|
||||
#ifdef WIN32
|
||||
eventEngine->~EventEngine();
|
||||
#else // ^^^ WIN32 / !WIN32 vvv
|
||||
delete eventEngine;
|
||||
#endif // WIN32
|
||||
|
||||
LDEBUGC("Globals", "Destroying 'MemoryManager'");
|
||||
#ifdef WIN32
|
||||
memoryManager->~MemoryManager();
|
||||
#else // ^^^ WIN32 / !WIN32 vvv
|
||||
delete memoryManager;
|
||||
#endif // WIN32
|
||||
|
||||
callback::destroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
#include <openspace/engine/syncengine.h>
|
||||
#include <openspace/engine/virtualpropertymanager.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/events/event.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <openspace/interaction/actionmanager.h>
|
||||
#include <openspace/interaction/interactionmonitor.h>
|
||||
#include <openspace/interaction/keybindingmanager.h>
|
||||
@@ -53,6 +55,7 @@
|
||||
#include <openspace/scene/assetloader.h>
|
||||
#include <openspace/scene/profile.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scene/rotation.h>
|
||||
#include <openspace/scene/scale.h>
|
||||
#include <openspace/scene/timeframe.h>
|
||||
@@ -101,13 +104,22 @@ namespace {
|
||||
template <class... Ts> overloaded(Ts...)->overloaded<Ts...>;
|
||||
|
||||
constexpr const char* _loggerCat = "OpenSpaceEngine";
|
||||
|
||||
openspace::properties::Property::PropertyInfo PrintEventsInfo = {
|
||||
"PrintEvents",
|
||||
"Print Events",
|
||||
"If this is enabled, all events that are propagated through the system are "
|
||||
"printed to the log."
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class Scene;
|
||||
|
||||
OpenSpaceEngine::OpenSpaceEngine() {
|
||||
OpenSpaceEngine::OpenSpaceEngine()
|
||||
: _printEvents(PrintEventsInfo, false)
|
||||
{
|
||||
FactoryManager::initialize();
|
||||
FactoryManager::ref().addFactory(
|
||||
std::make_unique<ghoul::TemplateFactory<Renderable>>(),
|
||||
@@ -186,6 +198,8 @@ void OpenSpaceEngine::initialize() {
|
||||
|
||||
global::initialize();
|
||||
|
||||
_printEvents = global::configuration->isPrintingEvents;
|
||||
|
||||
const std::string versionCheckUrl = global::configuration->versionCheckUrl;
|
||||
if (!versionCheckUrl.empty()) {
|
||||
global::versionChecker->requestLatestVersion(versionCheckUrl);
|
||||
@@ -895,13 +909,16 @@ void OpenSpaceEngine::deinitialize() {
|
||||
TransformationManager::deinitialize();
|
||||
SpiceManager::deinitialize();
|
||||
|
||||
if (_printEvents) {
|
||||
events::Event* e = global::eventEngine->firstEvent();
|
||||
events::logAllEvents(e);
|
||||
}
|
||||
|
||||
ghoul::fontrendering::FontRenderer::deinitialize();
|
||||
|
||||
ghoul::logging::LogManager::deinitialize();
|
||||
|
||||
LTRACE("deinitialize(end)");
|
||||
|
||||
|
||||
LTRACE("OpenSpaceEngine::deinitialize(end)");
|
||||
}
|
||||
|
||||
@@ -1101,6 +1118,7 @@ void OpenSpaceEngine::preSynchronization() {
|
||||
resetPropertyChangeFlagsOfSubowners(global::rootPropertyOwner);
|
||||
_hasScheduledAssetLoading = false;
|
||||
_scheduledAssetPathToLoad.clear();
|
||||
global::eventEngine->publishEvent<events::EventProfileLoadingFinished>();
|
||||
}
|
||||
else if (_isRenderingFirstFrame) {
|
||||
global::profile->ignoreUpdates = true;
|
||||
@@ -1186,6 +1204,9 @@ void OpenSpaceEngine::postSynchronizationPreDraw() {
|
||||
|
||||
if (_shutdown.inShutdown) {
|
||||
if (_shutdown.timer <= 0.f) {
|
||||
global::eventEngine->publishEvent<events::EventApplicationShutdown>(
|
||||
events::EventApplicationShutdown::State::Finished
|
||||
);
|
||||
global::windowDelegate->terminate();
|
||||
return;
|
||||
}
|
||||
@@ -1311,6 +1332,23 @@ void OpenSpaceEngine::postDraw() {
|
||||
_isRenderingFirstFrame = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle events
|
||||
//
|
||||
const events::Event* e = global::eventEngine->firstEvent();
|
||||
if (_printEvents) {
|
||||
events::logAllEvents(e);
|
||||
}
|
||||
global::eventEngine->triggerActions();
|
||||
while (e) {
|
||||
// @TODO (abock, 2021-08-25) Need to send all events to a topic to be sent out to
|
||||
// others
|
||||
|
||||
e = e->next;
|
||||
}
|
||||
|
||||
|
||||
global::eventEngine->postFrameCleanup();
|
||||
global::memoryManager->PersistentMemory.housekeeping();
|
||||
|
||||
LTRACE("OpenSpaceEngine::postDraw(end)");
|
||||
@@ -1544,11 +1582,17 @@ void OpenSpaceEngine::toggleShutdownMode() {
|
||||
if (_shutdown.inShutdown) {
|
||||
// If we are already in shutdown mode, we want to disable it
|
||||
_shutdown.inShutdown = false;
|
||||
global::eventEngine->publishEvent<events::EventApplicationShutdown>(
|
||||
events::EventApplicationShutdown::State::Aborted
|
||||
);
|
||||
}
|
||||
else {
|
||||
// Else, we have to enable it
|
||||
_shutdown.timer = _shutdown.waitTime;
|
||||
_shutdown.inShutdown = true;
|
||||
global::eventEngine->publishEvent<events::EventApplicationShutdown>(
|
||||
events::EventApplicationShutdown::State::Started
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
595
src/events/event.cpp
Normal file
595
src/events/event.cpp
Normal file
@@ -0,0 +1,595 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2021 *
|
||||
* *
|
||||
* 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/events/event.h>
|
||||
|
||||
#include <openspace/properties/property.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
#include <openspace/scene/profile.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/util/tstring.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <functional>
|
||||
|
||||
namespace {
|
||||
constexpr const char _loggerCat[] = "EventInfo";
|
||||
} // namespace
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace openspace::events {
|
||||
|
||||
void log(int i, const EventSceneGraphNodeAdded& e) {
|
||||
ghoul_assert(e.type == EventSceneGraphNodeAdded::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] SceneGraphNodeAdded: {}", i, e.node));
|
||||
}
|
||||
|
||||
void log(int i, const EventSceneGraphNodeRemoved& e) {
|
||||
ghoul_assert(e.type == EventSceneGraphNodeRemoved::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] SceneGraphNodeRemoved: {}", i, e.node));
|
||||
}
|
||||
|
||||
void log(int i, const EventParallelConnection& e) {
|
||||
ghoul_assert(e.type == EventParallelConnection::Type, "Wrong type");
|
||||
std::string_view state = [](EventParallelConnection::State s) {
|
||||
switch (s) {
|
||||
case EventParallelConnection::State::Established: return "Established";
|
||||
case EventParallelConnection::State::Lost: return "Lost";
|
||||
case EventParallelConnection::State::HostshipGained: return "HostshipGained";
|
||||
case EventParallelConnection::State::HostshipLost: return "HostshipLost";
|
||||
default: throw ghoul::MissingCaseException();
|
||||
}
|
||||
}(e.state);
|
||||
LINFO(fmt::format("[{}] ParallelConnection ({})", i, state));
|
||||
}
|
||||
|
||||
void log(int i, [[ maybe_unused ]] const EventProfileLoadingFinished& e) {
|
||||
ghoul_assert(e.type == EventProfileLoadingFinished::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] ProfileLoadingFinished", i));
|
||||
}
|
||||
|
||||
void log(int i, const EventApplicationShutdown& e) {
|
||||
ghoul_assert(e.type == EventApplicationShutdown::Type, "Wrong type");
|
||||
std::string t = [](EventApplicationShutdown::State state) {
|
||||
switch (state) {
|
||||
case EventApplicationShutdown::State::Started: return "started";
|
||||
case EventApplicationShutdown::State::Aborted: return "aborted";
|
||||
case EventApplicationShutdown::State::Finished: return "finished";
|
||||
default: throw ghoul::MissingCaseException();
|
||||
}
|
||||
}(e.state);
|
||||
LINFO(fmt::format("[{}] ApplicationShutdown", i));
|
||||
}
|
||||
|
||||
void log(int i, const EventScreenSpaceRenderableAdded& e) {
|
||||
ghoul_assert(e.type == EventScreenSpaceRenderableAdded::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] ScreenSpaceRenderableAdded: {}", i, e.renderable));
|
||||
}
|
||||
|
||||
void log(int i, const EventScreenSpaceRenderableRemoved& e) {
|
||||
ghoul_assert(e.type == EventScreenSpaceRenderableRemoved::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] ScreenSpaceRenderableRemoved: {}", i, e.renderable));
|
||||
}
|
||||
|
||||
void log(int i, const EventCameraFocusTransition& e) {
|
||||
ghoul_assert(e.type == EventCameraFocusTransition::Type, "Wrong type");
|
||||
std::string_view t = [](EventCameraFocusTransition::Transition transition) {
|
||||
switch (transition) {
|
||||
case EventCameraFocusTransition::Transition::Approaching:
|
||||
return "Approaching";
|
||||
case EventCameraFocusTransition::Transition::Reaching:
|
||||
return "Reaching";
|
||||
case EventCameraFocusTransition::Transition::Receding:
|
||||
return "Receding";
|
||||
case EventCameraFocusTransition::Transition::Exiting:
|
||||
return "Exiting";
|
||||
default: throw ghoul::MissingCaseException();
|
||||
}
|
||||
}(e.transition);
|
||||
|
||||
LINFO(fmt::format(
|
||||
"[{}] CameraTransition: {}, {} ({})",
|
||||
i, reinterpret_cast<const void*>(e.camera), e.node, t
|
||||
));
|
||||
}
|
||||
|
||||
void log(int i, const EventTimeOfInterestReached& e) {
|
||||
ghoul_assert(e.type == EventTimeOfInterestReached::Type, "Wrong type");
|
||||
LINFO(fmt::format(
|
||||
"[{}] TimeOfInterestReached: {}, {}",
|
||||
i, e.time->UTC(), reinterpret_cast<const void*>(e.camera)
|
||||
));
|
||||
}
|
||||
|
||||
void log(int i, [[ maybe_unused ]] const EventMissionEventReached& e) {
|
||||
ghoul_assert(e.type == EventMissionEventReached::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] MissionEventReached", i));
|
||||
}
|
||||
|
||||
void log(int i, const EventPlanetEclipsed& e) {
|
||||
ghoul_assert(e.type == EventPlanetEclipsed::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] PlanetEclipsed: {} -> {}", i, e.eclipsee, e.eclipser));
|
||||
}
|
||||
|
||||
void log(int i, [[ maybe_unused ]] const EventInterpolationFinished& e) {
|
||||
ghoul_assert(e.type == EventInterpolationFinished::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] InterpolationFinished", i));
|
||||
}
|
||||
|
||||
void log(int i, const EventFocusNodeChanged& e) {
|
||||
ghoul_assert(e.type == EventFocusNodeChanged::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] FocusNodeChanged: {} -> {}", i, e.oldNode, e.newNode));
|
||||
}
|
||||
|
||||
void log(int i, const EventLayerAdded& e) {
|
||||
ghoul_assert(e.type == EventLayerAdded::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] LayerAdded: {}", i, e.layer));
|
||||
}
|
||||
|
||||
void log(int i, const EventLayerRemoved& e) {
|
||||
ghoul_assert(e.type == EventLayerRemoved::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] LayerRemoved: {}", i, e.layer));
|
||||
}
|
||||
|
||||
void log(int i, const EventSessionRecordingPlayback& e) {
|
||||
ghoul_assert(e.type == EventSessionRecordingPlayback::Type, "Wrong type");
|
||||
|
||||
std::string_view state = [](EventSessionRecordingPlayback::State s) {
|
||||
switch (s) {
|
||||
case EventSessionRecordingPlayback::State::Started: return "Started";
|
||||
case EventSessionRecordingPlayback::State::Paused: return "Paused";
|
||||
case EventSessionRecordingPlayback::State::Resumed: return "Resumed";
|
||||
case EventSessionRecordingPlayback::State::Finished: return "Finished";
|
||||
default: throw ghoul::MissingCaseException();
|
||||
}
|
||||
}(e.state);
|
||||
|
||||
LINFO(fmt::format("[{}] SessionRecordingPlayback: {}", i, state));
|
||||
}
|
||||
|
||||
void log(int i, const CustomEvent& e) {
|
||||
ghoul_assert(e.type == CustomEvent::Type, "Wrong type");
|
||||
LINFO(fmt::format("[{}] CustomEvent: {} ({})", i, e.subtype, e.payload));
|
||||
}
|
||||
|
||||
std::string_view toString(Event::Type type) {
|
||||
switch (type) {
|
||||
case Event::Type::SceneGraphNodeAdded: return "SceneGraphNodeAdded";
|
||||
case Event::Type::SceneGraphNodeRemoved: return "SceneGraphNodeRemoved";
|
||||
case Event::Type::ParallelConnection: return "ParallelConnection";
|
||||
case Event::Type::ProfileLoadingFinished: return "ProfileLoadingFinished";
|
||||
case Event::Type::ApplicationShutdown: return "ApplicationShutdown";
|
||||
case Event::Type::ScreenSpaceRenderableAdded: return "ScreenSpaceRenderableAdded";
|
||||
case Event::Type::ScreenSpaceRenderableRemoved:
|
||||
return "ScreenSpaceRenderableRemoved";
|
||||
case Event::Type::CameraFocusTransition: return "CameraFocusTransition";
|
||||
case Event::Type::TimeOfInterestReached: return "TimeOfInterestReached";
|
||||
case Event::Type::MissionEventReached: return "MissionEventReached";
|
||||
case Event::Type::PlanetEclipsed: return "PlanetEclipsed";
|
||||
case Event::Type::InterpolationFinished: return "InterpolationFinished";
|
||||
case Event::Type::FocusNodeChanged: return "FocusNodeChanged";
|
||||
case Event::Type::LayerAdded: return "LayerAdded";
|
||||
case Event::Type::LayerRemoved: return "LayerRemoved";
|
||||
case Event::Type::SessionRecordingPlayback: return "SessionRecordingPlayback";
|
||||
case Event::Type::Custom: return "Custom";
|
||||
default:
|
||||
throw ghoul::MissingCaseException();
|
||||
}
|
||||
}
|
||||
|
||||
Event::Type fromString(std::string_view str) {
|
||||
if (str == "SceneGraphNodeAdded") {
|
||||
return Event::Type::SceneGraphNodeAdded;
|
||||
}
|
||||
else if (str == "SceneGraphNodeRemoved") {
|
||||
return Event::Type::SceneGraphNodeRemoved;
|
||||
}
|
||||
else if (str == "ParallelConnection") {
|
||||
return Event::Type::ParallelConnection;
|
||||
}
|
||||
else if (str == "ProfileLoadingFinished") {
|
||||
return Event::Type::ProfileLoadingFinished;
|
||||
}
|
||||
else if (str == "ApplicationShutdown") {
|
||||
return Event::Type::ApplicationShutdown;
|
||||
}
|
||||
else if (str == "ScreenSpaceRenderableAdded") {
|
||||
return Event::Type::ScreenSpaceRenderableAdded;
|
||||
}
|
||||
else if (str == "ScreenSpaceRenderableRemoved") {
|
||||
return Event::Type::ScreenSpaceRenderableRemoved;
|
||||
}
|
||||
else if (str == "CameraFocusTransition") {
|
||||
return Event::Type::CameraFocusTransition;
|
||||
}
|
||||
else if (str == "TimeOfInterestReached") {
|
||||
return Event::Type::TimeOfInterestReached;
|
||||
}
|
||||
else if (str == "MissionEventReached") {
|
||||
return Event::Type::MissionEventReached;
|
||||
}
|
||||
else if (str == "PlanetEclipsed") {
|
||||
return Event::Type::PlanetEclipsed;
|
||||
}
|
||||
else if (str == "InterpolationFinished") {
|
||||
return Event::Type::InterpolationFinished;
|
||||
}
|
||||
else if (str == "FocusNodeChanged") {
|
||||
return Event::Type::FocusNodeChanged;
|
||||
}
|
||||
else if (str == "LayerAdded") {
|
||||
return Event::Type::LayerAdded;
|
||||
}
|
||||
else if (str == "LayerRemoved") {
|
||||
return Event::Type::LayerRemoved;
|
||||
}
|
||||
else if (str == "SessionRecordingPlayback") {
|
||||
return Event::Type::SessionRecordingPlayback;
|
||||
}
|
||||
else if (str == "Custom") {
|
||||
return Event::Type::Custom;
|
||||
}
|
||||
|
||||
throw ghoul::RuntimeError(fmt::format("Unknown event type '{}'", str));
|
||||
}
|
||||
|
||||
ghoul::Dictionary toParameter(const Event& e) {
|
||||
ghoul::Dictionary d;
|
||||
switch (e.type) {
|
||||
case Event::Type::SceneGraphNodeAdded:
|
||||
d.setValue(
|
||||
"Node",
|
||||
std::string(static_cast<const EventSceneGraphNodeAdded&>(e).node)
|
||||
);
|
||||
break;
|
||||
case Event::Type::SceneGraphNodeRemoved:
|
||||
d.setValue(
|
||||
"Node",
|
||||
std::string(static_cast<const EventSceneGraphNodeRemoved&>(e).node)
|
||||
);
|
||||
break;
|
||||
case Event::Type::ParallelConnection:
|
||||
switch (static_cast<const EventParallelConnection&>(e).state) {
|
||||
case EventParallelConnection::State::Established:
|
||||
d.setValue("State", "Established"s);
|
||||
break;
|
||||
case EventParallelConnection::State::Lost:
|
||||
d.setValue("State", "Lost"s);
|
||||
break;
|
||||
case EventParallelConnection::State::HostshipGained:
|
||||
d.setValue("State", "HostshipGained"s);
|
||||
break;
|
||||
case EventParallelConnection::State::HostshipLost:
|
||||
d.setValue("State", "HostshipLost"s);
|
||||
break;
|
||||
default:
|
||||
throw ghoul::MissingCaseException();
|
||||
}
|
||||
break;
|
||||
case Event::Type::ApplicationShutdown:
|
||||
switch (static_cast<const EventApplicationShutdown&>(e).state) {
|
||||
case EventApplicationShutdown::State::Started:
|
||||
d.setValue("State", "Started"s);
|
||||
break;
|
||||
case EventApplicationShutdown::State::Aborted:
|
||||
d.setValue("State", "Aborted"s);
|
||||
break;
|
||||
case EventApplicationShutdown::State::Finished:
|
||||
d.setValue("State", "Finished"s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Event::Type::ScreenSpaceRenderableAdded:
|
||||
d.setValue(
|
||||
"Renderable",
|
||||
std::string(
|
||||
static_cast<const EventScreenSpaceRenderableAdded&>(e).renderable
|
||||
)
|
||||
);
|
||||
break;
|
||||
case Event::Type::ScreenSpaceRenderableRemoved:
|
||||
d.setValue(
|
||||
"Renderable",
|
||||
std::string(
|
||||
static_cast<const EventScreenSpaceRenderableRemoved&>(e).renderable
|
||||
)
|
||||
);
|
||||
break;
|
||||
case Event::Type::CameraFocusTransition:
|
||||
d.setValue(
|
||||
"Node",
|
||||
std::string(static_cast<const EventCameraFocusTransition&>(e).node)
|
||||
);
|
||||
switch (static_cast<const EventCameraFocusTransition&>(e).transition) {
|
||||
case EventCameraFocusTransition::Transition::Approaching:
|
||||
d.setValue("Transition", "Approaching"s);
|
||||
break;
|
||||
case EventCameraFocusTransition::Transition::Reaching:
|
||||
d.setValue("Transition", "Reaching"s);
|
||||
break;
|
||||
case EventCameraFocusTransition::Transition::Receding:
|
||||
d.setValue("Transition", "Receding"s);
|
||||
break;
|
||||
case EventCameraFocusTransition::Transition::Exiting:
|
||||
d.setValue("Transition", "Exiting"s);
|
||||
break;
|
||||
default:
|
||||
throw ghoul::MissingCaseException();
|
||||
}
|
||||
break;
|
||||
case Event::Type::PlanetEclipsed:
|
||||
d.setValue(
|
||||
"Eclipsee",
|
||||
std::string(static_cast<const EventPlanetEclipsed&>(e).eclipsee)
|
||||
);
|
||||
d.setValue(
|
||||
"Eclipser",
|
||||
std::string(static_cast<const EventPlanetEclipsed&>(e).eclipser)
|
||||
);
|
||||
break;
|
||||
case Event::Type::InterpolationFinished:
|
||||
d.setValue(
|
||||
"Property",
|
||||
std::string(static_cast<const EventInterpolationFinished&>(e).property)
|
||||
);
|
||||
break;
|
||||
case Event::Type::FocusNodeChanged:
|
||||
d.setValue(
|
||||
"OldNode",
|
||||
std::string(static_cast<const EventFocusNodeChanged&>(e).oldNode)
|
||||
);
|
||||
d.setValue(
|
||||
"NewNode",
|
||||
std::string(static_cast<const EventFocusNodeChanged&>(e).newNode)
|
||||
);
|
||||
break;
|
||||
case Event::Type::LayerAdded:
|
||||
d.setValue(
|
||||
"Globe",
|
||||
std::string(static_cast<const EventLayerAdded&>(e).node)
|
||||
);
|
||||
d.setValue(
|
||||
"Group",
|
||||
std::string(static_cast<const EventLayerAdded&>(e).layerGroup)
|
||||
);
|
||||
d.setValue(
|
||||
"Layer",
|
||||
std::string(static_cast<const EventLayerAdded&>(e).layer)
|
||||
);
|
||||
break;
|
||||
case Event::Type::LayerRemoved:
|
||||
d.setValue(
|
||||
"Globe",
|
||||
std::string(static_cast<const EventLayerRemoved&>(e).node)
|
||||
);
|
||||
d.setValue(
|
||||
"Group",
|
||||
std::string(static_cast<const EventLayerRemoved&>(e).layerGroup)
|
||||
);
|
||||
d.setValue(
|
||||
"Layer",
|
||||
std::string(static_cast<const EventLayerRemoved&>(e).layer)
|
||||
);
|
||||
break;
|
||||
case Event::Type::SessionRecordingPlayback:
|
||||
switch (static_cast<const EventSessionRecordingPlayback&>(e).state) {
|
||||
case EventSessionRecordingPlayback::State::Started:
|
||||
d.setValue("State", "Started"s);
|
||||
break;
|
||||
case EventSessionRecordingPlayback::State::Paused:
|
||||
d.setValue("State", "Paused"s);
|
||||
break;
|
||||
case EventSessionRecordingPlayback::State::Resumed:
|
||||
d.setValue("State", "Resumed"s);
|
||||
break;
|
||||
case EventSessionRecordingPlayback::State::Finished:
|
||||
d.setValue("State", "Finished"s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Event::Type::Custom:
|
||||
d.setValue(
|
||||
"Subtype", std::string(static_cast<const CustomEvent&>(e).subtype)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
void logAllEvents(const Event* e) {
|
||||
int i = 0;
|
||||
while (e) {
|
||||
switch (e->type) {
|
||||
case Event::Type::SceneGraphNodeAdded:
|
||||
log(i, *static_cast<const EventSceneGraphNodeAdded*>(e));
|
||||
break;
|
||||
case Event::Type::SceneGraphNodeRemoved:
|
||||
log(i, *static_cast<const EventSceneGraphNodeRemoved*>(e));
|
||||
break;
|
||||
case Event::Type::ParallelConnection:
|
||||
log(i, *static_cast<const EventParallelConnection*>(e));
|
||||
break;
|
||||
case Event::Type::ProfileLoadingFinished:
|
||||
log(i, *static_cast<const EventProfileLoadingFinished*>(e));
|
||||
break;
|
||||
case Event::Type::ApplicationShutdown:
|
||||
log(i, *static_cast<const EventApplicationShutdown*>(e));
|
||||
break;
|
||||
case Event::Type::ScreenSpaceRenderableAdded:
|
||||
log(i, *static_cast<const EventScreenSpaceRenderableAdded*>(e));
|
||||
break;
|
||||
case Event::Type::ScreenSpaceRenderableRemoved:
|
||||
log(i, *static_cast<const EventScreenSpaceRenderableRemoved*>(e));
|
||||
break;
|
||||
case Event::Type::CameraFocusTransition:
|
||||
log(i, *static_cast<const EventCameraFocusTransition*>(e));
|
||||
break;
|
||||
case Event::Type::TimeOfInterestReached:
|
||||
log(i, *static_cast<const EventTimeOfInterestReached*>(e));
|
||||
break;
|
||||
case Event::Type::MissionEventReached:
|
||||
log(i, *static_cast<const EventMissionEventReached*>(e));
|
||||
break;
|
||||
case Event::Type::PlanetEclipsed:
|
||||
log(i, *static_cast<const EventPlanetEclipsed*>(e));
|
||||
break;
|
||||
case Event::Type::InterpolationFinished:
|
||||
log(i, *static_cast<const EventInterpolationFinished*>(e));
|
||||
break;
|
||||
case Event::Type::FocusNodeChanged:
|
||||
log(i, *static_cast<const EventFocusNodeChanged*>(e));
|
||||
break;
|
||||
case Event::Type::LayerAdded:
|
||||
log(i, *static_cast<const EventLayerAdded*>(e));
|
||||
break;
|
||||
case Event::Type::LayerRemoved:
|
||||
log(i, *static_cast<const EventLayerRemoved*>(e));
|
||||
break;
|
||||
case Event::Type::SessionRecordingPlayback:
|
||||
log(i, *static_cast<const EventSessionRecordingPlayback*>(e));
|
||||
break;
|
||||
case Event::Type::Custom:
|
||||
log(i, *static_cast<const CustomEvent*>(e));
|
||||
break;
|
||||
default:
|
||||
LINFO(fmt::format("[{}]: Unknown {}", typeid(e).name()));
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
|
||||
EventSceneGraphNodeAdded::EventSceneGraphNodeAdded(const SceneGraphNode* node_)
|
||||
: Event(Type)
|
||||
, node(temporaryString(node_->identifier()))
|
||||
{}
|
||||
|
||||
EventSceneGraphNodeRemoved::EventSceneGraphNodeRemoved(const SceneGraphNode* node_)
|
||||
: Event(Type)
|
||||
, node(temporaryString(node_->identifier()))
|
||||
{}
|
||||
|
||||
EventParallelConnection::EventParallelConnection(State state_)
|
||||
: Event(Type)
|
||||
, state(state_)
|
||||
{}
|
||||
|
||||
EventProfileLoadingFinished::EventProfileLoadingFinished()
|
||||
: Event(Type)
|
||||
{}
|
||||
|
||||
EventApplicationShutdown::EventApplicationShutdown(State state_)
|
||||
: Event(Type)
|
||||
, state(state_)
|
||||
{}
|
||||
|
||||
EventScreenSpaceRenderableAdded::EventScreenSpaceRenderableAdded(
|
||||
const ScreenSpaceRenderable* renderable_)
|
||||
: Event(Type)
|
||||
, renderable(temporaryString(renderable_->identifier()))
|
||||
{}
|
||||
|
||||
EventScreenSpaceRenderableRemoved::EventScreenSpaceRenderableRemoved(
|
||||
const ScreenSpaceRenderable* renderable_)
|
||||
: Event(Type)
|
||||
, renderable(temporaryString(renderable_->identifier()))
|
||||
{}
|
||||
|
||||
EventCameraFocusTransition::EventCameraFocusTransition(const Camera* camera_,
|
||||
const SceneGraphNode* node_,
|
||||
Transition transition_)
|
||||
: Event(Type)
|
||||
, camera(camera_)
|
||||
, node(temporaryString(node_->identifier()))
|
||||
, transition(transition_)
|
||||
{}
|
||||
|
||||
EventTimeOfInterestReached::EventTimeOfInterestReached(const Time* time_,
|
||||
const Camera* camera_)
|
||||
: Event(Type)
|
||||
, time(time_)
|
||||
, camera(camera_)
|
||||
{}
|
||||
|
||||
EventMissionEventReached::EventMissionEventReached()
|
||||
: Event(Type)
|
||||
{}
|
||||
|
||||
EventPlanetEclipsed::EventPlanetEclipsed(const SceneGraphNode* eclipsee_,
|
||||
const SceneGraphNode* eclipser_)
|
||||
: Event(Type)
|
||||
, eclipsee(temporaryString(eclipsee_->identifier()))
|
||||
, eclipser(temporaryString(eclipser_->identifier()))
|
||||
{}
|
||||
|
||||
EventInterpolationFinished::EventInterpolationFinished(
|
||||
const properties::Property* property_)
|
||||
: Event(Type)
|
||||
, property(temporaryString(property_->fullyQualifiedIdentifier()))
|
||||
{}
|
||||
|
||||
EventFocusNodeChanged::EventFocusNodeChanged(const SceneGraphNode* oldNode_,
|
||||
const SceneGraphNode* newNode_)
|
||||
: Event(Type)
|
||||
, oldNode(oldNode_ ? temporaryString(oldNode_->identifier()) : "")
|
||||
, newNode(temporaryString(newNode_->identifier()))
|
||||
{
|
||||
ghoul_assert(newNode_, "There must be a new node");
|
||||
}
|
||||
|
||||
EventLayerAdded::EventLayerAdded(std::string_view node_, std::string_view layerGroup_,
|
||||
std::string_view layer_)
|
||||
: Event(Type)
|
||||
, node(temporaryString(node_))
|
||||
, layerGroup(temporaryString(layerGroup_))
|
||||
, layer(temporaryString(layer_))
|
||||
{}
|
||||
|
||||
EventLayerRemoved::EventLayerRemoved(std::string_view node_, std::string_view layerGroup_,
|
||||
std::string_view layer_)
|
||||
: Event(Type)
|
||||
, node(temporaryString(node_))
|
||||
, layerGroup(temporaryString(layerGroup_))
|
||||
, layer(temporaryString(layer_))
|
||||
{}
|
||||
|
||||
EventSessionRecordingPlayback::EventSessionRecordingPlayback(State state_)
|
||||
: Event(Type)
|
||||
, state(state_)
|
||||
{}
|
||||
|
||||
CustomEvent::CustomEvent(std::string_view subtype_, const void* payload_)
|
||||
: Event(Type)
|
||||
, subtype(subtype_)
|
||||
, payload(payload_)
|
||||
{}
|
||||
|
||||
} // namespace openspace::events
|
||||
133
src/events/eventengine.cpp
Normal file
133
src/events/eventengine.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2021 *
|
||||
* *
|
||||
* 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/events/eventengine.h>
|
||||
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/interaction/actionmanager.h>
|
||||
|
||||
#include "eventengine_lua.inl"
|
||||
|
||||
namespace openspace {
|
||||
|
||||
#ifdef _DEBUG
|
||||
uint64_t EventEngine::nEvents = 0;
|
||||
#endif // _DEBUG
|
||||
|
||||
events::Event* EventEngine::firstEvent() const {
|
||||
return _firstEvent;
|
||||
}
|
||||
|
||||
void EventEngine::postFrameCleanup() {
|
||||
_memory.reset();
|
||||
_firstEvent = nullptr;
|
||||
_lastEvent = nullptr;
|
||||
#ifdef _DEBUG
|
||||
nEvents = 0;
|
||||
#endif // _DEBUG
|
||||
}
|
||||
|
||||
void EventEngine::registerEventAction(events::Event::Type type,
|
||||
std::string identifier,
|
||||
std::optional<ghoul::Dictionary> filter)
|
||||
{
|
||||
ActionInfo ai;
|
||||
ai.action = std::move(identifier);
|
||||
ai.filter = std::move(filter);
|
||||
const auto it = _eventActions.find(type);
|
||||
if (it != _eventActions.end()) {
|
||||
it->second.push_back(ai);
|
||||
}
|
||||
else {
|
||||
_eventActions[type] = { std::move(ai) };
|
||||
}
|
||||
}
|
||||
|
||||
void EventEngine::unregisterEventAction(events::Event::Type type,
|
||||
const std::string& identifier,
|
||||
std::optional<ghoul::Dictionary> filter)
|
||||
{
|
||||
const auto it = _eventActions.find(type);
|
||||
if (it != _eventActions.end()) {
|
||||
const auto jt = std::find_if(
|
||||
it->second.begin(), it->second.end(),
|
||||
[identifier, filter](const ActionInfo& ai) {
|
||||
const bool a = ai.action == identifier;
|
||||
const bool f = !filter.has_value() || *filter == ai.filter;
|
||||
return a && f;
|
||||
}
|
||||
);
|
||||
if (jt != it->second.end()) {
|
||||
it->second.erase(jt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventEngine::triggerActions() const {
|
||||
if (_eventActions.empty()) {
|
||||
// Nothing to do here
|
||||
return;
|
||||
}
|
||||
|
||||
const events::Event* e = _firstEvent;
|
||||
while (e) {
|
||||
const auto it = _eventActions.find(e->type);
|
||||
if (it != _eventActions.end()) {
|
||||
ghoul::Dictionary params = toParameter(*e);
|
||||
for (const ActionInfo& ai : it->second) {
|
||||
if (!ai.filter.has_value() || params.isSubset(*ai.filter)) {
|
||||
global::actionManager->triggerAction(ai.action, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e = e->next;
|
||||
}
|
||||
}
|
||||
|
||||
scripting::LuaLibrary EventEngine::luaLibrary() {
|
||||
scripting::LuaLibrary res;
|
||||
res.name = "event";
|
||||
res.functions.push_back({
|
||||
"registerEventAction",
|
||||
&luascriptfunctions::registerEventAction,
|
||||
{},
|
||||
"string, string [, table]",
|
||||
"Registers an action (second parameter) to be executed whenever an event (first "
|
||||
"parameter) is encountered. If the optional third parameter is provided, it "
|
||||
"describes a filter that the event is being checked against and only if it "
|
||||
"passes the filter, the action is triggered"
|
||||
});
|
||||
res.functions.push_back({
|
||||
"unregisterEventAction",
|
||||
&luascriptfunctions::unregisterEventAction,
|
||||
{},
|
||||
"string, string [, table]",
|
||||
"Unregisters a specific combination of event (first parameter), action (second "
|
||||
"parameter), and potentially a filter (optional third argument)"
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
49
src/events/eventengine_lua.inl
Normal file
49
src/events/eventengine_lua.inl
Normal file
@@ -0,0 +1,49 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2021 *
|
||||
* *
|
||||
* 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. *
|
||||
****************************************************************************************/
|
||||
|
||||
namespace openspace::luascriptfunctions {
|
||||
|
||||
int registerEventAction(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::registerEventAction");
|
||||
auto [event, action, filter] =
|
||||
ghoul::lua::values<std::string, std::string, std::optional<ghoul::Dictionary>>(L);
|
||||
|
||||
events::Event::Type type = events::fromString(event);
|
||||
|
||||
global::eventEngine->registerEventAction(type, std::move(action), std::move(filter));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unregisterEventAction(lua_State* L) {
|
||||
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::unregisterEventAction");
|
||||
auto [event, action, filter] =
|
||||
ghoul::lua::values<std::string, std::string, std::optional<ghoul::Dictionary>>(L);
|
||||
|
||||
events::Event::Type type = events::fromString(event);
|
||||
|
||||
global::eventEngine->unregisterEventAction(type, action, filter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace openspace::luascriptfunctions
|
||||
@@ -86,7 +86,14 @@ void ActionManager::triggerAction(const std::string& identifier,
|
||||
const ghoul::Dictionary& arguments) const
|
||||
{
|
||||
ghoul_assert(!identifier.empty(), "Identifier must not be empty");
|
||||
ghoul_assert(hasAction(identifier), "Action was not found in the list");
|
||||
|
||||
if (!hasAction(identifier)) {
|
||||
LWARNINGC(
|
||||
"ActionManager",
|
||||
fmt::format("Action '{}' not found in the list", identifier)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const Action& a = action(identifier);
|
||||
if (arguments.isEmpty()) {
|
||||
@@ -97,7 +104,7 @@ void ActionManager::triggerAction(const std::string& identifier,
|
||||
}
|
||||
else {
|
||||
global::scriptEngine->queueScript(
|
||||
fmt::format("local args = {}\n{}", ghoul::formatLua(arguments), a.command),
|
||||
fmt::format("args = {}\n{}", ghoul::formatLua(arguments), a.command),
|
||||
scripting::ScriptEngine::RemoteScripting(a.synchronization)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <openspace/camera/camera.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <openspace/interaction/tasks/convertrecfileversiontask.h>
|
||||
#include <openspace/interaction/tasks/convertrecformattask.h>
|
||||
#include <openspace/navigation/keyframenavigator.h>
|
||||
@@ -461,6 +462,9 @@ bool SessionRecording::startPlayback(std::string& filename,
|
||||
(_playbackForceSimTimeAtStart ? 1 : 0)
|
||||
));
|
||||
|
||||
global::eventEngine->publishEvent<events::EventSessionRecordingPlayback>(
|
||||
events::EventSessionRecordingPlayback::State::Started
|
||||
);
|
||||
initializePlayback_triggerStart();
|
||||
|
||||
global::navigationHandler->orbitalNavigator().updateOnCameraInteraction();
|
||||
@@ -527,12 +531,18 @@ void SessionRecording::setPlaybackPause(bool pause) {
|
||||
global::timeManager->setPause(true);
|
||||
}
|
||||
_state = SessionState::PlaybackPaused;
|
||||
global::eventEngine->publishEvent<events::EventSessionRecordingPlayback>(
|
||||
events::EventSessionRecordingPlayback::State::Paused
|
||||
);
|
||||
}
|
||||
else if (!pause && _state == SessionState::PlaybackPaused) {
|
||||
if (!_playbackPausedWithinDeltaTimePause) {
|
||||
global::timeManager->setPause(false);
|
||||
}
|
||||
_state = SessionState::Playback;
|
||||
global::eventEngine->publishEvent<events::EventSessionRecordingPlayback>(
|
||||
events::EventSessionRecordingPlayback::State::Resumed
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,7 +585,7 @@ void SessionRecording::signalPlaybackFinishedForComponent(RecordedType type) {
|
||||
|
||||
if (!_playbackActive_camera && !_playbackActive_time && !_playbackActive_script) {
|
||||
if (_playbackLoopMode) {
|
||||
//Loop back to the beginning to replay
|
||||
// Loop back to the beginning to replay
|
||||
_saveRenderingDuringPlayback = false;
|
||||
initializePlayback_time(global::windowDelegate->applicationTime());
|
||||
initializePlayback_modeFlags();
|
||||
@@ -586,6 +596,9 @@ void SessionRecording::signalPlaybackFinishedForComponent(RecordedType type) {
|
||||
_state = SessionState::Idle;
|
||||
_cleanupNeeded = true;
|
||||
LINFO("Playback session finished");
|
||||
global::eventEngine->publishEvent<events::EventSessionRecordingPlayback>(
|
||||
events::EventSessionRecordingPlayback::State::Finished
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -606,6 +619,9 @@ void SessionRecording::stopPlayback() {
|
||||
_state = SessionState::Idle;
|
||||
_cleanupNeeded = true;
|
||||
LINFO("Session playback stopped");
|
||||
global::eventEngine->publishEvent<events::EventSessionRecordingPlayback>(
|
||||
events::EventSessionRecordingPlayback::State::Finished
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#include <openspace/camera/camera.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/events/event.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <openspace/interaction/actionmanager.h>
|
||||
#include <openspace/navigation/navigationstate.h>
|
||||
#include <openspace/network/parallelpeer.h>
|
||||
#include <openspace/scene/profile.h>
|
||||
@@ -175,6 +178,7 @@ void NavigationHandler::updateCamera(double deltaTime) {
|
||||
}
|
||||
else if (_pathNavigator.isPlayingPath()) {
|
||||
_pathNavigator.updateCamera(deltaTime);
|
||||
updateCameraTransitions();
|
||||
}
|
||||
else {
|
||||
if (_disableJoystickInputs) {
|
||||
@@ -186,6 +190,7 @@ void NavigationHandler::updateCamera(double deltaTime) {
|
||||
}
|
||||
_orbitalNavigator.updateStatesFromInput(_inputState, deltaTime);
|
||||
_orbitalNavigator.updateCameraStateFromStates(deltaTime);
|
||||
updateCameraTransitions();
|
||||
}
|
||||
|
||||
_orbitalNavigator.updateCameraScalingFromAnchor(deltaTime);
|
||||
@@ -208,6 +213,118 @@ void NavigationHandler::applyNavigationState(const NavigationState& ns) {
|
||||
_orbitalNavigator.clearPreviousState();
|
||||
}
|
||||
|
||||
void NavigationHandler::updateCameraTransitions() {
|
||||
// This function is concerned with managing transitions of the camera between
|
||||
// different distances of interest relative to the focus node. For each transition two
|
||||
// scenarios are handled; SceneGraphNodes can have attached actions for each
|
||||
// transition, which are automatically triggered. Additionally, an
|
||||
// EventCameraTransition event is fired that contains information about the focus node
|
||||
// and the transition state that caused the vent to fire.
|
||||
|
||||
// Diagram of events for a camera moving from right-to-left.
|
||||
// Interaction sphere is 'O' in middle, and ')' are spherical boundaries. The approach
|
||||
// factor, reach factor, and interaction sphere radius are all taken from the current
|
||||
// focus node.
|
||||
//
|
||||
// |<------------------->| Approach factor * Interaction sphere
|
||||
// |<------>| Reach Factor * Interaction sphere
|
||||
//
|
||||
// ( ( O ) )
|
||||
// ^ ^ ^ ^
|
||||
// OnExit OnMoveAway OnReach OnApproach
|
||||
const glm::dvec3 anchorPos = anchorNode()->worldPosition();
|
||||
const glm::dvec3 cameraPos = _camera->positionVec3();
|
||||
const double currDistance = glm::distance(anchorPos, cameraPos);
|
||||
const double d = anchorNode()->interactionSphere();
|
||||
const double af = anchorNode()->approachFactor();
|
||||
const double rf = anchorNode()->reachFactor();
|
||||
|
||||
using namespace std::string_literals;
|
||||
if (_inAnchorApproachSphere) {
|
||||
if (currDistance > d * (af + InteractionHystersis)) {
|
||||
// We left the approach sphere outwards
|
||||
_inAnchorApproachSphere = false;
|
||||
|
||||
if (!anchorNode()->onExitAction().empty()) {
|
||||
ghoul::Dictionary dict;
|
||||
dict.setValue("Node", anchorNode()->identifier());
|
||||
dict.setValue("Transition", "Exiting"s);
|
||||
for (const std::string& action : anchorNode()->onExitAction()) {
|
||||
global::actionManager->triggerAction(action, dict);
|
||||
}
|
||||
}
|
||||
|
||||
global::eventEngine->publishEvent<events::EventCameraFocusTransition>(
|
||||
_camera,
|
||||
anchorNode(),
|
||||
events::EventCameraFocusTransition::Transition::Exiting
|
||||
);
|
||||
}
|
||||
else if (currDistance < d * (rf - InteractionHystersis)) {
|
||||
// We transitioned from the approach sphere into the reach sphere
|
||||
_inAnchorApproachSphere = false;
|
||||
_inAnchorReachSphere = true;
|
||||
|
||||
if (!anchorNode()->onReachAction().empty()) {
|
||||
ghoul::Dictionary dict;
|
||||
dict.setValue("Node", anchorNode()->identifier());
|
||||
dict.setValue("Transition", "Reaching"s);
|
||||
for (const std::string& action : anchorNode()->onReachAction()) {
|
||||
global::actionManager->triggerAction(action, dict);
|
||||
}
|
||||
}
|
||||
|
||||
global::eventEngine->publishEvent<events::EventCameraFocusTransition>(
|
||||
_camera,
|
||||
anchorNode(),
|
||||
events::EventCameraFocusTransition::Transition::Reaching
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (_inAnchorReachSphere && currDistance > d * (rf + InteractionHystersis)) {
|
||||
// We transitioned from the reach sphere to the approach sphere
|
||||
_inAnchorReachSphere = false;
|
||||
_inAnchorApproachSphere = true;
|
||||
|
||||
if (!anchorNode()->onRecedeAction().empty()) {
|
||||
ghoul::Dictionary dict;
|
||||
dict.setValue("Node", anchorNode()->identifier());
|
||||
dict.setValue("Transition", "Receding"s);
|
||||
for (const std::string& action : anchorNode()->onRecedeAction()) {
|
||||
global::actionManager->triggerAction(action, dict);
|
||||
}
|
||||
}
|
||||
|
||||
global::eventEngine->publishEvent<events::EventCameraFocusTransition>(
|
||||
_camera,
|
||||
anchorNode(),
|
||||
events::EventCameraFocusTransition::Transition::Receding
|
||||
);
|
||||
}
|
||||
else if (!_inAnchorApproachSphere && !_inAnchorReachSphere &&
|
||||
currDistance < d * (af - InteractionHystersis))
|
||||
{
|
||||
// We moved into the approach sphere
|
||||
_inAnchorApproachSphere = true;
|
||||
|
||||
if (!anchorNode()->onApproachAction().empty()) {
|
||||
ghoul::Dictionary dict;
|
||||
dict.setValue("Node", anchorNode()->identifier());
|
||||
dict.setValue("Transition", "Approaching"s);
|
||||
for (const std::string& action : anchorNode()->onApproachAction()) {
|
||||
global::actionManager->triggerAction(action, dict);
|
||||
}
|
||||
}
|
||||
|
||||
global::eventEngine->publishEvent<events::EventCameraFocusTransition>(
|
||||
_camera,
|
||||
anchorNode(),
|
||||
events::EventCameraFocusTransition::Transition::Approaching
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NavigationHandler::setEnableKeyFrameInteraction() {
|
||||
_useKeyFrameInteraction = true;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/events/event.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/easing.h>
|
||||
#include <glm/gtx/rotate_vector.hpp>
|
||||
@@ -353,7 +356,12 @@ OrbitalNavigator::OrbitalNavigator()
|
||||
}
|
||||
SceneGraphNode* node = sceneGraphNode(_anchor.value());
|
||||
if (node) {
|
||||
const SceneGraphNode* previousAnchor = _anchorNode;
|
||||
setAnchorNode(node);
|
||||
global::eventEngine->publishEvent<events::EventFocusNodeChanged>(
|
||||
previousAnchor,
|
||||
node
|
||||
);
|
||||
}
|
||||
else {
|
||||
LERROR(fmt::format(
|
||||
@@ -804,8 +812,14 @@ glm::dvec3 OrbitalNavigator::cameraToSurfaceVector(const glm::dvec3& cameraPos,
|
||||
void OrbitalNavigator::setFocusNode(const SceneGraphNode* focusNode,
|
||||
bool resetVelocitiesOnChange)
|
||||
{
|
||||
const SceneGraphNode* previousAnchor = _anchorNode;
|
||||
setAnchorNode(focusNode, resetVelocitiesOnChange);
|
||||
setAimNode(nullptr);
|
||||
|
||||
global::eventEngine->publishEvent<events::EventFocusNodeChanged>(
|
||||
previousAnchor,
|
||||
focusNode
|
||||
);
|
||||
}
|
||||
|
||||
void OrbitalNavigator::setFocusNode(const std::string& focusNode, bool) {
|
||||
@@ -953,8 +967,8 @@ bool OrbitalNavigator::shouldFollowAnchorRotation(const glm::dvec3& cameraPositi
|
||||
|
||||
const double distanceToCamera =
|
||||
glm::distance(cameraPosition, _anchorNode->worldPosition());
|
||||
|
||||
return distanceToCamera < maximumDistanceForRotation;
|
||||
bool shouldFollow = distanceToCamera < maximumDistanceForRotation;
|
||||
return shouldFollow;
|
||||
}
|
||||
|
||||
bool OrbitalNavigator::followingAnchorRotation() const {
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include <openspace/camera/camera.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/events/event.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <openspace/navigation/keyframenavigator.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/navigation/orbitalnavigator.h>
|
||||
@@ -215,7 +217,7 @@ void ParallelPeer::handleMessage(const ParallelConnection::Message& message) {
|
||||
nConnectionsMessageReceived(message.content);
|
||||
break;
|
||||
default:
|
||||
//unknown message type
|
||||
// unknown message type
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -259,8 +261,7 @@ double ParallelPeer::latencyStandardDeviation() const {
|
||||
return std::sqrt(latencyVariance);
|
||||
}
|
||||
|
||||
void ParallelPeer::dataMessageReceived(const std::vector<char>& message)
|
||||
{
|
||||
void ParallelPeer::dataMessageReceived(const std::vector<char>& message) {
|
||||
size_t offset = 0;
|
||||
|
||||
// The type of data message received
|
||||
@@ -290,8 +291,10 @@ void ParallelPeer::dataMessageReceived(const std::vector<char>& message)
|
||||
pose.scale = kf._scale;
|
||||
pose.followFocusNodeRotation = kf._followNodeRotation;
|
||||
|
||||
global::navigationHandler->keyframeNavigator().addKeyframe(convertedTimestamp,
|
||||
pose);
|
||||
global::navigationHandler->keyframeNavigator().addKeyframe(
|
||||
convertedTimestamp,
|
||||
pose
|
||||
);
|
||||
break;
|
||||
}
|
||||
case datamessagestructures::Type::TimelineData: {
|
||||
@@ -359,10 +362,9 @@ void ParallelPeer::dataMessageReceived(const std::vector<char>& message)
|
||||
}
|
||||
}
|
||||
|
||||
void ParallelPeer::connectionStatusMessageReceived(const std::vector<char>& message)
|
||||
{
|
||||
void ParallelPeer::connectionStatusMessageReceived(const std::vector<char>& message) {
|
||||
if (message.size() < 2 * sizeof(uint32_t)) {
|
||||
LERROR("Malformed connection status message.");
|
||||
LERROR("Malformed connection status message");
|
||||
return;
|
||||
}
|
||||
size_t pointer = 0;
|
||||
@@ -376,7 +378,7 @@ void ParallelPeer::connectionStatusMessageReceived(const std::vector<char>& mess
|
||||
pointer += sizeof(uint32_t);
|
||||
|
||||
if (hostNameSize > message.size() - pointer) {
|
||||
LERROR("Malformed connection status message.");
|
||||
LERROR("Malformed connection status message");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -387,7 +389,7 @@ void ParallelPeer::connectionStatusMessageReceived(const std::vector<char>& mess
|
||||
pointer += hostNameSize;
|
||||
|
||||
if (status > ParallelConnection::Status::Host) {
|
||||
LERROR("Invalid status.");
|
||||
LERROR("Invalid status");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -410,7 +412,7 @@ void ParallelPeer::connectionStatusMessageReceived(const std::vector<char>& mess
|
||||
void ParallelPeer::nConnectionsMessageReceived(const std::vector<char>& message)
|
||||
{
|
||||
if (message.size() < sizeof(uint32_t)) {
|
||||
LERROR("Malformed host info message.");
|
||||
LERROR("Malformed host info message");
|
||||
return;
|
||||
}
|
||||
const uint32_t nConnections = *(reinterpret_cast<const uint32_t*>(&message[0]));
|
||||
@@ -532,9 +534,54 @@ void ParallelPeer::preSynchronization() {
|
||||
|
||||
void ParallelPeer::setStatus(ParallelConnection::Status status) {
|
||||
if (_status != status) {
|
||||
ParallelConnection::Status prevStatus = _status;
|
||||
_status = status;
|
||||
_timeJumped = true;
|
||||
_connectionEvent->publish("statusChanged");
|
||||
|
||||
|
||||
EventEngine* ee = global::eventEngine;
|
||||
const bool isConnected =
|
||||
status == ParallelConnection::Status::ClientWithoutHost ||
|
||||
status == ParallelConnection::Status::ClientWithHost ||
|
||||
status == ParallelConnection::Status::Host;
|
||||
const bool wasConnected =
|
||||
prevStatus == ParallelConnection::Status::ClientWithoutHost ||
|
||||
prevStatus == ParallelConnection::Status::ClientWithHost ||
|
||||
prevStatus == ParallelConnection::Status::Host;
|
||||
const bool isDisconnected = status == ParallelConnection::Status::Disconnected;
|
||||
const bool wasDisconnected =
|
||||
prevStatus == ParallelConnection::Status::Disconnected;
|
||||
const bool isHost = status == ParallelConnection::Status::Host;
|
||||
const bool wasHost = prevStatus == ParallelConnection::Status::Host;
|
||||
const bool isClient =
|
||||
status == ParallelConnection::Status::ClientWithoutHost ||
|
||||
status == ParallelConnection::Status::ClientWithHost;
|
||||
const bool wasClient =
|
||||
prevStatus == ParallelConnection::Status::ClientWithoutHost ||
|
||||
prevStatus == ParallelConnection::Status::ClientWithHost;
|
||||
|
||||
|
||||
if (isDisconnected && wasConnected) {
|
||||
ee->publishEvent<events::EventParallelConnection>(
|
||||
events::EventParallelConnection::State::Lost
|
||||
);
|
||||
}
|
||||
if (isConnected && wasDisconnected) {
|
||||
ee->publishEvent<events::EventParallelConnection>(
|
||||
events::EventParallelConnection::State::Established
|
||||
);
|
||||
}
|
||||
if (isHost && (wasClient || wasDisconnected)) {
|
||||
ee->publishEvent<events::EventParallelConnection>(
|
||||
events::EventParallelConnection::State::HostshipGained
|
||||
);
|
||||
}
|
||||
if ((isClient || isDisconnected) && wasHost) {
|
||||
ee->publishEvent<events::EventParallelConnection>(
|
||||
events::EventParallelConnection::State::HostshipLost
|
||||
);
|
||||
}
|
||||
}
|
||||
if (isHost()) {
|
||||
global::timeManager->addTimeJumpCallback([this]() {
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/events/event.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <openspace/properties/property.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/json_helper.h>
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/events/event.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/navigation/orbitalnavigator.h>
|
||||
#include <openspace/mission/missionmanager.h>
|
||||
@@ -1105,8 +1107,11 @@ void RenderEngine::addScreenSpaceRenderable(std::unique_ptr<ScreenSpaceRenderabl
|
||||
s->initialize();
|
||||
s->initializeGL();
|
||||
|
||||
global::screenSpaceRootPropertyOwner->addPropertySubOwner(s.get());
|
||||
ScreenSpaceRenderable* ssr = s.get();
|
||||
global::screenSpaceRootPropertyOwner->addPropertySubOwner(ssr);
|
||||
global::screenSpaceRenderables->push_back(std::move(s));
|
||||
|
||||
global::eventEngine->publishEvent<events::EventScreenSpaceRenderableAdded>(ssr);
|
||||
}
|
||||
|
||||
void RenderEngine::removeScreenSpaceRenderable(ScreenSpaceRenderable* s) {
|
||||
@@ -1119,9 +1124,10 @@ void RenderEngine::removeScreenSpaceRenderable(ScreenSpaceRenderable* s) {
|
||||
if (it != global::screenSpaceRenderables->end()) {
|
||||
s->deinitialize();
|
||||
global::screenSpaceRootPropertyOwner->removePropertySubOwner(s);
|
||||
|
||||
global::screenSpaceRenderables->erase(it);
|
||||
}
|
||||
|
||||
global::eventEngine->publishEvent<events::EventScreenSpaceRenderableRemoved>(s);
|
||||
}
|
||||
|
||||
void RenderEngine::removeScreenSpaceRenderable(const std::string& identifier) {
|
||||
@@ -1131,8 +1137,7 @@ void RenderEngine::removeScreenSpaceRenderable(const std::string& identifier) {
|
||||
}
|
||||
}
|
||||
|
||||
ScreenSpaceRenderable* RenderEngine::screenSpaceRenderable(
|
||||
const std::string& identifier)
|
||||
ScreenSpaceRenderable* RenderEngine::screenSpaceRenderable(const std::string& identifier)
|
||||
{
|
||||
const auto it = std::find_if(
|
||||
global::screenSpaceRenderables->begin(),
|
||||
|
||||
@@ -598,13 +598,9 @@ void Profile::removeAsset(const std::string& path) {
|
||||
}
|
||||
|
||||
const auto it = std::find(assets.cbegin(), assets.cend(), path);
|
||||
if (it == assets.end()) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Tried to remove non-existing asset '{}'", path
|
||||
));
|
||||
if (it != assets.end()) {
|
||||
assets.erase(it);
|
||||
}
|
||||
|
||||
assets.erase(it);
|
||||
}
|
||||
|
||||
std::string Profile::serialize() const {
|
||||
|
||||
@@ -125,6 +125,7 @@ void Scene::registerNode(SceneGraphNode* node) {
|
||||
_nodesByIdentifier[node->identifier()] = node;
|
||||
addPropertySubOwner(node);
|
||||
_dirtyNodeRegistry = true;
|
||||
global::eventEngine->publishEvent<events::EventSceneGraphNodeAdded>(node);
|
||||
}
|
||||
|
||||
void Scene::unregisterNode(SceneGraphNode* node) {
|
||||
@@ -144,6 +145,7 @@ void Scene::unregisterNode(SceneGraphNode* node) {
|
||||
}
|
||||
removePropertySubOwner(node);
|
||||
_dirtyNodeRegistry = true;
|
||||
global::eventEngine->publishEvent<events::EventSceneGraphNodeRemoved>(node);
|
||||
}
|
||||
|
||||
void Scene::markNodeRegistryDirty() {
|
||||
@@ -585,6 +587,10 @@ void Scene::updateInterpolations() {
|
||||
i.prop->interpolateValue(t, i.easingFunction);
|
||||
|
||||
i.isExpired = (t == 1.f);
|
||||
|
||||
if (i.isExpired) {
|
||||
global::eventEngine->publishEvent<events::EventInterpolationFinished>(i.prop);
|
||||
}
|
||||
}
|
||||
|
||||
_propertyInterpolationInfos.erase(
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/events/event.h>
|
||||
#include <openspace/events/eventengine.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/scene/profile.h>
|
||||
#include <ghoul/lua/luastate.h>
|
||||
|
||||
@@ -111,6 +111,20 @@ namespace {
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ApproachFactorInfo = {
|
||||
"ApproachFactor",
|
||||
"Approach Factor",
|
||||
"This value is a multiplication factor for the interaction sphere that "
|
||||
"determines when the camera is 'approaching' the scene graph node"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ReachFactorInfo = {
|
||||
"ReachFactor",
|
||||
"Reach Factor",
|
||||
"This value is a multiplication factor for the interaction sphere that "
|
||||
"determines when the camera has 'reached' the scene graph node"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo GuiPathInfo = {
|
||||
"GuiPath",
|
||||
"Gui Path",
|
||||
@@ -174,13 +188,10 @@ namespace {
|
||||
// children
|
||||
std::optional<ghoul::Dictionary> renderable [[codegen::reference("renderable")]];
|
||||
|
||||
// A hard-coded bounding sphere to be used for the cases where the Renderable is
|
||||
// not able to provide a reasonable bounding sphere or the calculated bounding
|
||||
// sphere needs to be overwritten for some reason
|
||||
// [[codegen::verbatim(BoundingSphereInfo.description)]]
|
||||
std::optional<double> boundingSphere;
|
||||
|
||||
// A hard-coded radius for limiting the interaction radius, meaning the minimal
|
||||
// distance that the camera can approach this scene graph node
|
||||
// [[codegen::verbatim(InteractionSphereInfo.description)]]
|
||||
std::optional<double> interactionSphere;
|
||||
|
||||
struct Transform {
|
||||
@@ -208,6 +219,36 @@ namespace {
|
||||
// corresponding to a 'Translation', a 'Rotation', and a 'Scale'
|
||||
std::optional<Transform> transform;
|
||||
|
||||
// This value is a multiplication factor for the interaction sphere that
|
||||
// determines when the camera is 'approaching' the scene graph node. If this value
|
||||
// is not specified, a default value of 5 is used instead. This value must be
|
||||
// larger than the reachFactor or unexpected things might happen
|
||||
std::optional<double> approachFactor [[codegen::greaterequal(0.0)]];
|
||||
|
||||
// This value is a multiplication factor for the interaction sphere that
|
||||
// determines when the camera has 'reached' the scene graph node. If this value is
|
||||
// not specified, a default value of 1.25 is used instead. This value must be
|
||||
// smaller than the approachFactor or unexpected things might happen
|
||||
std::optional<double> reachFactor [[codegen::greaterequal(0.0)]];
|
||||
|
||||
// One or multiple actions that are executed whenever the camera is focused on
|
||||
// this scene graph node and if it enters the interaction sphere of the node
|
||||
std::optional<std::variant<std::string, std::vector<std::string>>> onApproach;
|
||||
|
||||
// One or multiple actions that are executed whenever the camera is focused on
|
||||
// this scene graph node and if it transitions from the approach distance to the
|
||||
// reach distance of the node
|
||||
std::optional<std::variant<std::string, std::vector<std::string>>> onReach;
|
||||
|
||||
// One or multiple actions that are executed whenever the camera is focused on
|
||||
// this scene graph node and if it transitions from the reach distance to the
|
||||
// approach distance of the node
|
||||
std::optional<std::variant<std::string, std::vector<std::string>>> onRecede;
|
||||
|
||||
// One or multiple actions that are executed whenever the camera is focused on
|
||||
// this scene graph node and if it exits the interaction sphere of the node
|
||||
std::optional<std::variant<std::string, std::vector<std::string>>> onExit;
|
||||
|
||||
// Specifies the time frame for when this node should be active
|
||||
std::optional<ghoul::Dictionary> timeFrame
|
||||
[[codegen::reference("core_time_frame")]];
|
||||
@@ -287,6 +328,8 @@ ghoul::mm_unique_ptr<SceneGraphNode> SceneGraphNode::createFromDictionary(
|
||||
|
||||
result->_overrideBoundingSphere = p.boundingSphere;
|
||||
result->_overrideInteractionSphere = p.interactionSphere;
|
||||
result->_approachFactor = p.approachFactor.value_or(result->_approachFactor);
|
||||
result->_reachFactor = p.reachFactor.value_or(result->_reachFactor);
|
||||
|
||||
if (p.transform.has_value()) {
|
||||
if (p.transform->translation.has_value()) {
|
||||
@@ -378,6 +421,43 @@ ghoul::mm_unique_ptr<SceneGraphNode> SceneGraphNode::createFromDictionary(
|
||||
));
|
||||
}
|
||||
|
||||
// Extracting the actions from the dictionary
|
||||
if (p.onApproach.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.onApproach)) {
|
||||
result->_onApproachAction = { std::get<std::string>(*p.onApproach) };
|
||||
}
|
||||
else {
|
||||
result->_onApproachAction = std::get<std::vector<std::string>>(*p.onApproach);
|
||||
}
|
||||
}
|
||||
|
||||
if (p.onReach.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.onReach)) {
|
||||
result->_onReachAction = { std::get<std::string>(*p.onReach) };
|
||||
}
|
||||
else {
|
||||
result->_onReachAction = std::get<std::vector<std::string>>(*p.onReach);
|
||||
}
|
||||
}
|
||||
|
||||
if (p.onRecede.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.onRecede)) {
|
||||
result->_onRecedeAction = { std::get<std::string>(*p.onRecede) };
|
||||
}
|
||||
else {
|
||||
result->_onRecedeAction = std::get<std::vector<std::string>>(*p.onRecede);
|
||||
}
|
||||
}
|
||||
|
||||
if (p.onExit.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.onExit)) {
|
||||
result->_onExitAction = { std::get<std::string>(*p.onExit) };
|
||||
}
|
||||
else {
|
||||
result->_onExitAction = std::get<std::vector<std::string>>(*p.onExit);
|
||||
}
|
||||
}
|
||||
|
||||
if (p.tag.has_value()) {
|
||||
if (std::holds_alternative<std::string>(*p.tag)) {
|
||||
result->addTag(std::get<std::string>(*p.tag));
|
||||
@@ -425,6 +505,8 @@ SceneGraphNode::SceneGraphNode()
|
||||
}
|
||||
, _boundingSphere(BoundingSphereInfo, -1.0, -1.0, 1e12)
|
||||
, _interactionSphere(InteractionSphereInfo, -1.0, -1.0, 1e12)
|
||||
, _approachFactor(ApproachFactorInfo, 5.0)
|
||||
, _reachFactor(ReachFactorInfo, 1.25)
|
||||
, _computeScreenSpaceValues(ComputeScreenSpaceInfo, false)
|
||||
, _screenSpacePosition(ScreenSpacePositionInfo, glm::ivec2(-1, -1))
|
||||
, _screenVisibility(ScreenVisibilityInfo, false)
|
||||
@@ -463,6 +545,8 @@ SceneGraphNode::SceneGraphNode()
|
||||
// negative values
|
||||
//_interactionSphere.setExponent(10.f);
|
||||
addProperty(_interactionSphere);
|
||||
addProperty(_reachFactor);
|
||||
addProperty(_approachFactor);
|
||||
addProperty(_showDebugSphere);
|
||||
}
|
||||
|
||||
@@ -1066,6 +1150,22 @@ std::vector<SceneGraphNode*> SceneGraphNode::children() const {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& SceneGraphNode::onApproachAction() const {
|
||||
return _onApproachAction;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& SceneGraphNode::onReachAction() const {
|
||||
return _onReachAction;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& SceneGraphNode::onRecedeAction() const {
|
||||
return _onRecedeAction;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& SceneGraphNode::onExitAction() const {
|
||||
return _onExitAction;
|
||||
}
|
||||
|
||||
double SceneGraphNode::boundingSphere() const {
|
||||
if (_overrideBoundingSphere.has_value()) {
|
||||
return glm::compMax(scale() * *_overrideBoundingSphere);
|
||||
@@ -1092,6 +1192,14 @@ double SceneGraphNode::interactionSphere() const {
|
||||
}
|
||||
}
|
||||
|
||||
double SceneGraphNode::reachFactor() const {
|
||||
return _reachFactor;
|
||||
}
|
||||
|
||||
double SceneGraphNode::approachFactor() const {
|
||||
return _approachFactor;
|
||||
}
|
||||
|
||||
const Renderable* SceneGraphNode::renderable() const {
|
||||
return _renderable.get();
|
||||
}
|
||||
|
||||
51
src/util/tstring.cpp
Normal file
51
src/util/tstring.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2021 *
|
||||
* *
|
||||
* 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/tstring.h>
|
||||
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/util/memorymanager.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
tstring temporaryString(const std::string& str) {
|
||||
void* ptr = global::memoryManager->TemporaryMemory.do_allocate(str.size(), 8);
|
||||
std::strcpy(reinterpret_cast<char*>(ptr), str.data());
|
||||
return tstring(reinterpret_cast<char*>(ptr), str.size());
|
||||
}
|
||||
|
||||
tstring temporaryString(std::string_view str) {
|
||||
void* ptr = global::memoryManager->TemporaryMemory.do_allocate(str.size(), 8);
|
||||
std::strcpy(reinterpret_cast<char*>(ptr), str.data());
|
||||
return tstring(reinterpret_cast<char*>(ptr), str.size());
|
||||
}
|
||||
|
||||
tstring temporaryString(const char str[]) {
|
||||
size_t size = strlen(str);
|
||||
void* ptr = global::memoryManager->TemporaryMemory.do_allocate(size, 8);
|
||||
std::strcpy(reinterpret_cast<char*>(ptr), str);
|
||||
return tstring(reinterpret_cast<char*>(ptr), size);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
Reference in New Issue
Block a user