/***************************************************************************************** * * * OpenSpace * * * * Copyright (c) 2014-2023 * * * * 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 __OPENSPACE_CORE___EVENT___H__ #define __OPENSPACE_CORE___EVENT___H__ #include #include #include namespace openspace { namespace properties { class Property; } class Camera; class Layer; class Profile; class Renderable; class SceneGraphNode; class ScreenSpaceRenderable; class Time; } // namespace openspace namespace openspace::events { struct Event { // Steps to add a new event type: // 1. Add a new entry into this enum list // 2. Create a new subclass of Event in this file with a constructor that sets the // Event's `type` to this new enum entry // 3. In the cpp file, add a new `log` message that takes the new type as an argument // and that prints something useful when the log is encountered and the user wants // to see all events. // 4. Add a new case into the logAllEvents function that handles the new enum entry // 5. If the new event type has any parameters it takes in its constructor, go into // the `toParameter` function and add a case label for the new enum type and // return a dictionary with these parameters. This dictionary is passed to actions // if they are triggered by events // 6. Add the new enum entry into the `toString` and `fromString` methods enum class Type : uint8_t { SceneGraphNodeAdded, SceneGraphNodeRemoved, ParallelConnection, ProfileLoadingFinished, ApplicationShutdown, ScreenSpaceRenderableAdded, ScreenSpaceRenderableRemoved, CameraFocusTransition, TimeOfInterestReached, MissionEventReached, PlanetEclipsed, InterpolationFinished, FocusNodeChanged, LayerAdded, LayerRemoved, SessionRecordingPlayback, PointSpacecraft, RenderableEnabled, RenderableDisabled, CameraPathStarted, CameraPathFinished, CameraMovedPosition, Custom }; constexpr explicit Event(Type type_) : type(type_) {} const Type type; const Event* next = nullptr; }; template T* asType(Event* e) { ghoul_assert(e->type == T::Type, "Wrong type requested, check 'isType'"); return static_cast(e); } template bool isType(Event* e) { return e->type == T::Type; } std::string_view toString(Event::Type type); Event::Type fromString(std::string_view str); ghoul::Dictionary toParameter(const Event& e); void logAllEvents(const Event* e); // // Events // /** * This event is created whenever a new scene graph node is added to the system. By the * time this event is signalled, the scene graph node has already been created and added * to the scene. */ struct EventSceneGraphNodeAdded : public Event { static constexpr Type Type = Event::Type::SceneGraphNodeAdded; /** * Creates an instance of an EventSceneGraphNodeAdded event. * * \param node_ The identifier of the node that was added * * \pre node_ must not be nullptr */ explicit EventSceneGraphNodeAdded(const SceneGraphNode* node_); const tstring node; }; /** * This event is created whenever a scene graph node was removed. By the time this event * is signalled, the scene graph node has already been removed. */ struct EventSceneGraphNodeRemoved : public Event { static constexpr Type Type = Event::Type::SceneGraphNodeRemoved; /** * Creates an instance of an EventSceneGraphNodeRemoved event. * * \param node_ The identifier of the node that was removed * * \pre node_ must not be nullptr */ explicit EventSceneGraphNodeRemoved(const SceneGraphNode* node_); const tstring node; }; /** * This event is created whenever something in the parallel connection subsystem changes. * The new state is sent as an argument with this event. */ struct EventParallelConnection : public Event { static constexpr Type Type = Event::Type::ParallelConnection; enum class State : uint8_t { Established, Lost, HostshipGained, HostshipLost }; /** * Creates an instance of an EventParallelConnection event. * * \param state_ The new state of the parallel connection system; is one of * `Established`, `Lost`, `HostshipGained`, or `HostshipLost` */ explicit EventParallelConnection(State state_); State state; }; /** * This event is created when the loading of a profile is finished. This is emitted * regardless of whether it is the initial profile, or any subsequent profile is loaded. */ struct EventProfileLoadingFinished : public Event { static constexpr Type Type = Event::Type::ProfileLoadingFinished; /** * Creates an instance of an EventProfileLoadingFinished event. */ EventProfileLoadingFinished(); }; /** * This event is created whenever some information about the application shutdown sequence * changes. This can either be that the seqeuence started, was aborted, or is finished, * which means that OpenSpace is just about the shutdown. */ struct EventApplicationShutdown : public Event { static constexpr Type Type = Event::Type::ApplicationShutdown; enum class State : uint8_t { Started, Aborted, Finished }; /** * Creates an instance of an EventApplicationShutdown event. * * \param state_ The next state of the application shutdown sequence; is one of * `Started`, `Aborted`, or `Finished` */ explicit EventApplicationShutdown(State state_); const State state; }; /** * This event is created when a new screenspace renderable has been created. By the time * this event is craeted, the screenspace renderable is already registered and available. */ struct EventScreenSpaceRenderableAdded : public Event { static constexpr Type Type = Event::Type::ScreenSpaceRenderableAdded; /** * Creates an instance of an EventScreenSpaceRenderableAdded event. * * \param renderable_ The the new screenspace renderable that was added to the system * * \pre renderable_ must not be nullptr */ explicit EventScreenSpaceRenderableAdded(const ScreenSpaceRenderable* renderable_); const tstring renderable; }; /** * This event is created when a screenspace renderable has been removed from the system. * When this event is created, the screenspace renderable has already been removed and is * no longer available */ struct EventScreenSpaceRenderableRemoved : public Event { static constexpr Type Type = Event::Type::ScreenSpaceRenderableRemoved; /** * Creates an instance of an EventScreenSpaceRenderableRemoved event. * * \param renderable_ The the new screenspace renderable that was removed */ explicit EventScreenSpaceRenderableRemoved(const ScreenSpaceRenderable* renderable_); const tstring renderable; }; /** * This event is created when the camera transitions between different interaction sphere * distances. Right now, only movement relative to camera's focus node is considered. * Each scene graph node has an interaction sphere radius that serves as the reference * distance for all spheres. ``` 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 ) ) ^ ^ ^ ^ Exiting Receding Reaching Approaching ``` */ struct EventCameraFocusTransition : public Event { static constexpr Type Type = Event::Type::CameraFocusTransition; enum class Transition { Approaching, Reaching, Receding, Exiting }; /** * Creates an instance of an EventCameraFocusTransition event. * * \param camera_ The camera object that caused the transition * \param node_ The name of the node the camera is transitioning relative to. * Currently is always the same as the camera's focus node * \param transition_ The transition type that the camera just finished; is one of * `Approaching`, `Reaching`, `Receding`, or `Exiting` * * \pre camera_ must not be nullptr * \pre node_ must not be nullptr */ EventCameraFocusTransition(const Camera* camera_, const SceneGraphNode* node_, Transition transition_); const Camera* camera = nullptr; const tstring node; const Transition transition; }; /** * This event is created with a specific time of interest is reached. This event is * currently unused. */ struct EventTimeOfInterestReached : public Event { static constexpr Type Type = Event::Type::TimeOfInterestReached; /** * Creates an instance of an EventTimeOfInterestReached event. * * \param time_ The time of interest that has been reached * \param camera_ Information about the camera for the specific transition */ EventTimeOfInterestReached(const Time* time_, const Camera* camera_); const Time* time = nullptr; const Camera* camera = nullptr; }; /** * This event is created when the end of a mission phase is reached. This event is * currently unused. */ struct EventMissionEventReached : public Event { static constexpr Type Type = Event::Type::MissionEventReached; // Not sure which kind of parameters we want to pass here EventMissionEventReached(); }; /** * This event is created when a planet is eclipsed by a moon or a different planet. This * event is currently unused. */ struct EventPlanetEclipsed : public Event { static constexpr Type Type = Event::Type::PlanetEclipsed; /** * Creates an instance of an EventPlanetEclipsed event. * * \param eclipsee_ The scene graph node that is eclipsed by another object * \param eclipser_ The scene graph node that is eclipsing the other object * * \pre eclipsee_ must not be nullptr * \pre eclipser_ must not be nullptr */ EventPlanetEclipsed(const SceneGraphNode* eclipsee_, const SceneGraphNode* eclipser_); const tstring eclipsee; const tstring eclipser; }; /** * This event is created when the interpolation of a property value is finished. If the * interpolation time of a property change is 0s, this event is not fired */ struct EventInterpolationFinished : public Event { static constexpr Type Type = Event::Type::InterpolationFinished; /** * Creates an instance of an EventInterpolationFinished event. * * \param property_ The property whose interpolation has finished * * \pre property_ must not be nullptr */ EventInterpolationFinished(const properties::Property* property_); const tstring property; }; /** * This event is created when the camera changes focus nodes. Even if the camera position * is interpolated, the node change happens instantaneously and the event is fired at the * same time. */ struct EventFocusNodeChanged : public Event { static constexpr Type Type = Event::Type::FocusNodeChanged; /** * Creates an instance of an EventFocusNodeChanged event. * * \param oldNode_ The scene graph node which was the old focus node * \param newNode_ The scene graph node that is the new focus node * * \pre oldNode_ must not be nullptr * \pre newNode_ must not be nullptr */ EventFocusNodeChanged(const SceneGraphNode* oldNode_, const SceneGraphNode* newNode_); const tstring oldNode; const tstring newNode; }; /** * This event is created when a layer is added to to a globe. */ struct EventLayerAdded : public Event { static constexpr Type Type = Event::Type::LayerAdded; /** * Creates an instance of an EventLayerAdded event. * * \param node_ The identifier of the globe to which the layer is added * \param layerGroup_ The identifier of the layer group to which the layer is added * \param layer_ The identifier of the layer that was added * * \pre node_ must not be empty * \pre layerGroup_ must not be empty * \pre layer_ must not be empty */ explicit EventLayerAdded(std::string_view node_, std::string_view layerGroup_, std::string_view layer_); const tstring node; const tstring layerGroup; const tstring layer; }; /** * This event is created when a layer is removed from a globe. */ struct EventLayerRemoved : public Event { static constexpr Type Type = Event::Type::LayerRemoved; /** * Creates an instance of an EventLayerRemoved event. * * \param node_ The identifier of the globe to which the layer is removed * \param layerGroup_ The identifier of the layer group to which the layer is removed * \param layer_ The identifier of the layer that was removed * * \pre node_ must not be empty * \pre layerGroup_ must not be empty * \pre layer_ must not be empty */ explicit EventLayerRemoved(std::string_view node_, std::string_view layerGroup_, std::string_view layer_); const tstring node; const tstring layerGroup; const tstring layer; }; /** * This event is created when something regarding a session recording playback changes. * The event contains information about the new state of the session recording subsystem. */ struct EventSessionRecordingPlayback : public Event { static constexpr Type Type = Event::Type::SessionRecordingPlayback; enum class State { Started, Paused, Resumed, Finished }; /** * Creates an instance of an EventSessionRecordingPlayback event. * * \param state_ The new state of the session recording; one of `Started`, `Paused`, * `Resumed`, `Finished` */ EventSessionRecordingPlayback(State state_); const State state; }; /** * This event is created when a request for pointing a spacecraft towards a Ra Dec * coordinate in the sky is issued. The event contains information about the sky * coordinate to point the spacecraft towards, and an optional argument for the duration * it should do the pointing. */ struct EventPointSpacecraft : public Event { static constexpr Type Type = Event::Type::PointSpacecraft; /** * Creates an instance of an EventSessionRecordingPlayback event. * * \param ra_ The Ra part of the sky coordinate in decimal degrees to point towards * \param dec_ The Dec part of the sky coordinate in decimal degrees to point towards * \param duration_ The duration of time in seconds that the spacecraft should * redirect itself to the coordinate. Default is 3 seconds */ EventPointSpacecraft(double ra_, double dec_, double duration_ = 3.0); const double ra; const double dec; const double duration; }; /** * This event is created whenever a renderable is enabled. By the time this event is * signalled, the renderable has already been enabled. */ struct EventRenderableEnabled : public Event { static constexpr Type Type = Event::Type::RenderableEnabled; /** * Creates an instance of an EventRenderableEnabled event. * * \param node_ The identifier of the node that contains the renderable * * \pre node_ must not be nullptr */ explicit EventRenderableEnabled(const SceneGraphNode* node_); const tstring node; }; /** * This event is created whenever a renderable is disabled. By the time this event is * signalled, the renderable has already been disabled. */ struct EventRenderableDisabled : public Event { static constexpr Type Type = Event::Type::RenderableDisabled; /** * Creates an instance of an EventRenderableDisabled event. * * \param node_ The identifier of that node that contains the renderable * * \pre node_ must not be nullptr */ explicit EventRenderableDisabled(const SceneGraphNode* node_); const tstring node; }; /** * This event is created when the a camera path is started */ struct EventCameraPathStarted : public Event { static constexpr Type Type = Event::Type::CameraPathStarted; /** * Creates an instance of an EventCameraPathStarted event. * * \param origin_ The scene graph node from which the path started * \param destination_ The scene graph node at which the path ends */ EventCameraPathStarted(const SceneGraphNode* origin_, const SceneGraphNode* destination_); const tstring origin; const tstring destination; }; /** * This event is created when the a camera path is finished */ struct EventCameraPathFinished : public Event { static constexpr Type Type = Event::Type::CameraPathFinished; /** * Creates an instance of an EventCameraPathStarted event. * * \param origin_ The scene graph node from which the path started * \param destination_ The scene graph node where the path ended */ EventCameraPathFinished(const SceneGraphNode* origin_, const SceneGraphNode* destination_); const tstring origin; const tstring destination; }; /** * This event is created when the a camera moves location */ struct EventCameraMovedPosition : public Event { static constexpr Type Type = Event::Type::CameraMovedPosition; /** * Creates an instance of an EventCameraMovedPosition event. */ EventCameraMovedPosition(); }; /** * A custom event type that can be used in a pinch when no explicit event type is * available. This should only be used in special circumstances and it should be * transitioned to a specific event type, if it is deemed to be useful. */ struct CustomEvent : public Event { static constexpr Type Type = Event::Type::Custom; /** * Creates an instance of a CustomEvent event. * * \param subtype_ A textual description of the custom subtype that is emitted * \param payload_ The payload in a string form * * \pre subtype_ must not be empty */ CustomEvent(std::string_view subtype_, std::string_view payload_); const tstring subtype; const tstring payload; }; } // namespace openspace::events #endif // __OPENSPACE_CORE___EVENT___H__