khora_data/render/editor_view.rs
1// Copyright 2025 eraflo
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! `EditorViewportOverride` — fallback view consumed by [`RenderFlow`] when
16//! no active scene `Camera` exists.
17//!
18//! Tools that drive their own camera outside the ECS (the editor in
19//! Editing mode, headless screenshot tools, …) write the desired
20//! [`ExtractedView`] here once per frame **before** the scheduler runs.
21//! `RenderFlow` reads it during `project()` and appends it to
22//! `RenderWorld.views` if the world produced none of its own.
23//!
24//! The type is intentionally generic — it lives in the data layer so that
25//! [`RenderFlow`] does not need to know about any editor crate.
26//!
27//! [`RenderFlow`]: crate::flow::RenderFlow
28
29use std::sync::{Arc, RwLock};
30
31use super::ExtractedView;
32
33/// Shared, mutable per-frame view override.
34///
35/// Cloning shares the inner state — every `Arc` clone observes the same
36/// override.
37#[derive(Clone, Default)]
38pub struct EditorViewportOverride(Arc<RwLock<Option<ExtractedView>>>);
39
40impl EditorViewportOverride {
41 /// Creates a new, empty override.
42 pub fn new() -> Self {
43 Self::default()
44 }
45
46 /// Replaces the current override view (or clears it with `None`).
47 pub fn set(&self, view: Option<ExtractedView>) {
48 if let Ok(mut slot) = self.0.write() {
49 *slot = view;
50 }
51 }
52
53 /// Returns the current override view, if any.
54 pub fn get(&self) -> Option<ExtractedView> {
55 self.0.read().ok().and_then(|slot| slot.clone())
56 }
57
58 /// Clears the current override.
59 pub fn clear(&self) {
60 self.set(None);
61 }
62}