Toast Engine
Loading...
Searching...
No Matches
workspace.hpp
1
10
11#pragma once
12
13#include "editor_camera.hpp"
14#include "gizmo_layout.hpp"
15#include "node_owner.hpp"
16#include "workspace_history.hpp"
17
18#include <atomic>
19#include <glm/glm.hpp>
20#include <glm/gtc/quaternion.hpp>
21#include <memory>
22#include <toast/events/listener.hpp>
23#include <utility>
24
25namespace toast {
26
27class ProceduralVoxel;
28
39class TOAST_API Workspace : public INodeOwner {
40public:
42 glm::vec3 world_position {0.0f};
43 GizmoHandle handle = GizmoHandle::none;
44 };
45
46 static constexpr size_t k_max_size_handles = 6;
47
53 Workspace(std::string_view type, UID handle);
54
59 Workspace(UID uid);
60
68 Workspace(UID uid, std::string_view source_uri);
69
70 ~Workspace() override;
71
72 auto name() -> std::string override;
73
74 auto asWorkspace() -> Workspace* override { return this; }
75
77 void registerDependency(Node& from, Node& to) override;
78 void unregisterDependency(Node& from, Node& to) override;
79
80 void nodeEnabledChanged(Node& node) noexcept override;
81
82 [[nodiscard]]
83 auto participatesIn(NodeOwnerParticipation use) const noexcept -> bool override;
84
85 [[nodiscard]]
86 auto receivesEvents() const noexcept -> bool override;
87
89 auto findFrom(const Node& origin, std::string_view query) -> Box<Node> override;
90
92 auto findFrom(const Node& origin, const UID& uid) -> Box<Node> override;
93
95 auto searchFrom(const Node& origin, std::string_view query) -> std::vector<Box<Node>> override;
96
98 [[nodiscard]]
99 virtual auto isPlaying() const -> bool {
100 return false;
101 }
102
103 [[nodiscard]]
104 auto usesGameCamera() const noexcept -> bool {
105 return m_game_camera;
106 }
107
108 void inheritEditorCamera(const Workspace& source);
109 void preparePrefabReload(UID uid);
110 void finishPrefabReload();
111
112protected:
113 [[nodiscard]]
114 auto owningPrefabUid() const -> UID override {
115 return m_handle;
116 }
117
119 struct EmptyTag { };
120
122 Workspace(UID handle, EmptyTag);
123
124 UID m_handle;
125 // In-memory source assets must outlive the handles held by the node tree.
126 std::unique_ptr<assets::Prefab> m_owned_source_prefab;
127 Box<Node> m_root_node;
128 Box<Node> m_focused_node;
129 event::Listener m_listener;
130
131 // mirrored editor toolbar state; defaults match the editor's
132 struct SnapSetting {
133 bool enabled = true;
134 float value = 0.0f;
135 };
136
137 GizmoTool m_gizmo_tool = GizmoTool::select;
138 bool m_world_space = false;
139 SnapSetting m_translate_snap {true, 0.10f};
140 SnapSetting m_rotate_snap {true, 30.0f};
141 SnapSetting m_scale_snap {true, 0.10f};
142 bool m_game_camera = false;
143 std::unique_ptr<Camera> m_editor_camera;
145 std::unique_ptr<WorkspaceHistory> m_history;
146 std::mutex m_enabled_changes_mutex;
147 std::vector<Box<Node>> m_enabled_changes;
148
149 void sendEnabledChanges();
150
151 [[nodiscard]]
152 auto isActiveWorkspace() const noexcept -> bool;
153
155 // Translate-gizmo interaction
156 glm::vec2 m_gizmo_mouse_pos {0.0f, 0.0f};
157 GizmoHandle m_gizmo_hover = GizmoHandle::none;
158 GizmoHandle m_gizmo_drag = GizmoHandle::none;
159 glm::vec3 m_gizmo_drag_start_world_pos {0.0f};
160 glm::quat m_gizmo_drag_start_rotation {1.0f, 0.0f, 0.0f, 0.0f};
161 glm::vec3 m_gizmo_drag_start_scale {1.0f};
162 glm::vec3 m_gizmo_drag_anchor {0.0f};
163 glm::vec3 m_gizmo_drag_axis {0.0f};
164 glm::vec3 m_gizmo_drag_plane_normal {0.0f};
167
168 glm::vec3 m_gizmo_drag_start_size {0.0f};
169 glm::vec3 m_gizmo_drag_start_local_pos {0.0f};
170 glm::quat m_gizmo_drag_start_local_rot {1.0f, 0.0f, 0.0f, 0.0f};
172 std::optional<std::string> m_gizmo_history_start;
173
174 [[nodiscard]]
175 auto gizmoOrigin() const -> glm::vec3;
176 [[nodiscard]]
177 auto gizmoOrientation() const -> glm::quat;
178 [[nodiscard]]
179 auto gizmoScale() const -> float;
180 [[nodiscard]]
181 auto gizmoInteractionAllowed() const -> bool;
182
183 [[nodiscard]]
184 auto collectSizeHandles() const -> std::pair<std::array<SizeHandlePoint, k_max_size_handles>, uint32_t>;
185
186 void gizmoApplySizeDrag(float delta);
187 void gizmoUpdateHover();
188 void gizmoBeginDrag(GizmoHandle handle);
189 void gizmoUpdateDrag();
190 void gizmoEndDrag();
191
192 void eventSubscriptions();
193 void initializeHistory(bool available, bool initially_saved);
194 auto restoreHistorySnapshot(const assets::Prefab& snapshot) -> bool;
195 void destroyOwnedTree(Box<Node>& root);
196 auto duplicateNode(Box<Node> src, Box<Node> par, bool after_source) -> Box<Node>;
197
200
203 enum class Phase : uint8_t {
204 idle,
205 face,
206 part,
208 height,
209 cut,
210 pick_side,
211 };
212
213 uint32_t tool = 0;
214 uint8_t paint_id = 1;
216 uint8_t default_mode = 0;
217 Phase phase = Phase::idle;
218 bool dragging = false;
220 int axis = 2;
221 int32_t surface = 0;
222 float plane = 0.0f;
223 int32_t sign = 1;
224 int32_t depth = 1;
225 glm::ivec3 anchor {0};
226 glm::ivec3 current {0};
227 glm::ivec3 face_min {std::numeric_limits<int32_t>::min()};
228 glm::ivec3 face_max {std::numeric_limits<int32_t>::max()};
229 int cut_axis = 0;
230 int32_t cut_at = 0;
231 glm::vec2 cut_start {0.0f};
232 glm::vec4 cut_plane {0.0f};
233
235 [[nodiscard]]
236 auto box() const -> std::pair<glm::ivec3, glm::ivec3>;
237 };
238
239 VoxelToolState m_voxel_tool;
240
241 Box<Node> m_voxel_preview;
242 void voxelUpdatePreview(uint8_t kind);
243
244 void voxelReparent(Box<Node> node, Box<Node> parent, size_t index);
245 auto voxelWrapInGroup(Box<Node> node, std::string_view name) -> Box<Node>;
246
247 [[nodiscard]]
248 auto voxelToolShape() -> ProceduralVoxel*;
249 void voxelToolMouseMove();
250 auto voxelToolMouseButton(uint32_t button, bool pressed, int mods) -> bool;
251 void voxelToolCancel();
252
253 auto pickNodeUnderMouse() -> Box<Node>;
254 std::optional<glm::vec2> m_pick_press;
255
256 auto retypeNode(Box<Node>& target, std::string_view type, bool keep_fields) -> Box<Node>;
257 void promoteNode(Box<Node>& target, std::string_view path);
258
259 template<typename F>
260 void recordHistory(WorkspaceHistory::Context context, F&& mutation) {
261 const bool owned = m_history && m_history->beginAtomic(std::move(context));
262 std::forward<F>(mutation)();
263 if (m_history) {
264 m_history->finishAtomic(owned);
265 }
266 }
267
269 void initFromPrefab(const assets::Handle<assets::Prefab>& file);
270 void applyActiveCamera() override;
271
272private:
273 struct PendingPrefabReload {
274 Box<Node> node;
275 assets::Prefab reference;
276 };
277
278 std::vector<PendingPrefabReload> m_prefab_reloads;
279 double m_inspector_accum = 0.0;
280
287 void tickAnimationPreviews(const Node& node);
288
289public:
295 void tick() override;
296
297 [[nodiscard]]
298 auto rootNode() const -> const Node& {
299 return *m_root_node;
300 }
301
302 [[nodiscard]]
303 auto isValid() const -> bool {
304 return m_root_node.exists();
305 }
306
307 [[nodiscard]]
308 auto findPrefabInstance(UID prefab, UID instance) -> Box<Node>;
309
311 bool visible = false;
312 GizmoTool tool = GizmoTool::select;
313 glm::vec3 origin {0.0f};
314 glm::quat orientation {1.0f, 0.0f, 0.0f, 0.0f};
315 GizmoHandle hover = GizmoHandle::none;
316 GizmoHandle active = GizmoHandle::none;
317 float drag_scale_factor = 1.0f;
318
319 std::array<SizeHandlePoint, k_max_size_handles> size_handles {};
320 uint32_t size_handle_count = 0;
321 float size_handle_scale = 1.0f;
322 };
323
327 [[nodiscard]]
328 auto gizmoRenderState() const -> GizmoRenderState;
329};
330}
manages the lifetime, subscription, and unsubscription of callbacks
Definition listener.hpp:39
Intrusive reference-counted handle to a Node.
Definition box.hpp:35
auto exists() const noexcept -> bool
Whether this box holds a live node.
Definition box.inl:135
Definition editor_camera.hpp:15
Definition node.hpp:81
Definition procedural_voxel.hpp:41
Definition workspace_history.hpp:13
EditorCameraController m_editor_camera_controller
drives m_editor_camera; ticked from tick() below
Definition workspace.hpp:144
glm::vec2 m_gizmo_mouse_pos
The gizmo's current state.
Definition workspace.hpp:156
virtual auto isPlaying() const -> bool
True for PlayWorkspace, gates gizmo interaction off so it can never run against a live game.
Definition workspace.hpp:99
float m_gizmo_drag_start_angle
radians, for rotate drags
Definition workspace.hpp:165
auto asWorkspace() -> Workspace *override
Downcast helper for owners that need Workspace-specific state.
Definition workspace.hpp:74
glm::vec3 m_gizmo_drag_plane_normal
world-space plane normal, for plane/center/ring drags
Definition workspace.hpp:164
void subscribeVoxelEditing()
Definition workspace_voxel.cpp:694
float m_gizmo_drag_current_factor
live scale factor, for the scale feedback stretch
Definition workspace.hpp:166
bool m_world_space
false = local coordinates
Definition workspace.hpp:138
bool m_game_camera
false = editor camera
Definition workspace.hpp:142
glm::vec3 m_gizmo_drag_anchor
closest-point-on-axis or ray-plane hit at drag start
Definition workspace.hpp:162
std::optional< std::string > m_gizmo_history_start
dragged field's value at drag start, set while the drag owns the open history transaction
Definition workspace.hpp:172
Workspace(std::string_view type, UID handle)
Creates a new workspace rooted at a single fresh node of the given type.
Definition workspace.cpp:352
glm::vec3 m_gizmo_drag_axis
world-space axis direction, for axis/ring drags
Definition workspace.hpp:163
Geometry + hit-test constants shared between DebugPass (renders the gizmos) and Workspace (hit-tests/...
GizmoTool
Mirrors editor.WorkspaceViewModel.GizmoTool / proto SetGizmoTool - 0 Select, 1 Translate,...
Definition gizmo_layout.hpp:21
GizmoHandle
Which part of the active gizmo a ray/click is interacting with, axis_x/y/z and center are reused acro...
Definition gizmo_layout.hpp:32
Definition uid.hpp:20
disambiguates the protected ctor from Workspace(UID)
Definition workspace.hpp:119
Definition workspace.hpp:310
float drag_scale_factor
scale tool only: live multiplicative factor for the active handle
Definition workspace.hpp:317
Definition workspace.hpp:41
Definition workspace.hpp:132
Definition workspace.hpp:202
bool dragging
if its drawing the mouse make it 2 clicks rather than 3
Definition workspace.hpp:218
int32_t cut_at
Extrude: the voxel boundary the cut sits on.
Definition workspace.hpp:230
int axis
The face the box lies on.
Definition workspace.hpp:220
float plane
Where along axis the mouse ray is cut to find the rectangle.
Definition workspace.hpp:222
int32_t surface
The voxel layer of the face that was clicked.
Definition workspace.hpp:221
UID extrude_source
The piece Extrude grows from.
Definition workspace.hpp:219
Phase
Definition workspace.hpp:203
uint8_t default_mode
voxel::WriteMode new fill volumes land with
Definition workspace.hpp:216
int32_t sign
Which way is out of the face.
Definition workspace.hpp:223
int cut_axis
Extrude: 0 first in face axis, 1 second.
Definition workspace.hpp:229
UID default_script
What new volumes draw with.
Definition workspace.hpp:215
glm::ivec3 face_min
Extrude keeps the footprint on its face.
Definition workspace.hpp:227
auto box() const -> std::pair< glm::ivec3, glm::ivec3 >
Definition workspace_voxel.cpp:218