mod canvas;
mod canvas_geometry;
mod draw_tools;
mod edit;
mod generators;
mod inspector;
mod models;
mod modes;
mod picked_file;
mod properties;
mod shape;
mod state;
mod svg_path;
mod toolbar;
mod units;
use crate::assets::AssetEdits;
use crate::canvas::test_screen;
use crate::canvas::undo::UndoStack;
use crate::fixture_definition_editor::edit::Edit;
use crate::fixture_definition_editor::state::EditorState;
use crate::ui::asset_tree::{AssetTree, TREE_WIDTH, TreeSelection};
use crate::ui::file_pick::FilePick;
use crate::ui::window_common::{
embedded_close_clicked, gled_window_frame, raise, tool_window_builder,
};
use egui::{
CollapsingHeader, Context, Id, Key, KeyboardShortcut, Modifiers, ScrollArea, Ui, Vec2,
ViewportId, vec2,
};
use gled_model::asset::Asset;
use gled_model::asset_id::AssetId;
use gled_model::collection::Collections;
use gled_model::patching::definition::FixtureDefinition;
use std::sync::Arc;
const TITLE: &str = "Fixture Definitions";
#[derive(Debug, Default)]
pub(crate) struct FixtureDefinitionsWindow {
open: bool,
raise: bool,
dirty: bool,
tree: AssetTree<FixtureDefinition>,
state: EditorState,
undo: UndoStack<FixtureDefinition>,
open_request: Option<AssetId<FixtureDefinition>>,
}
impl FixtureDefinitionsWindow {
#[cfg_attr(feature = "profiling", profiling::function)]
pub(crate) fn update(&mut self, ctx: &Context, collections: &mut Collections) {
if !self.open {
self.dirty = false;
return;
}
if let Some(id) = self.open_request.take()
&& let Some(asset) = Asset::get(id, collections)
{
self.tree.selection = TreeSelection::Asset(Arc::unwrap_or_clone(asset));
self.dirty = false;
}
ctx.show_viewport_immediate(
ViewportId(Id::new("fixture definitions window")),
tool_window_builder(TITLE)
.with_inner_size(Vec2::new(1280.0, 820.0))
.with_min_inner_size(Vec2::new(900.0, 600.0)),
|ctx, _viewport_class| {
raise(ctx, &mut self.raise);
self.state.typing = ctx.text_edit_focused();
ctx.input(|input| {
if input.viewport().close_requested() || embedded_close_clicked(TITLE) {
self.open = false;
self.state.file_pick = FilePick::default();
}
});
if ctx.input_mut(|input| {
input.consume_shortcut(&KeyboardShortcut::new(Modifiers::COMMAND, Key::S))
}) && let TreeSelection::Asset(asset) = &self.tree.selection
{
asset.clone().save(collections);
self.dirty = false;
}
gled_window_frame(ctx, TITLE, |ui| {
egui::Panel::left("fixture definitions tree")
.exact_size(TREE_WIDTH)
.resizable(false)
.show(ui, |ui| {
if self.tree.show(
ui,
ui.make_persistent_id("fixture_definitions_tree"),
collections,
) {
self.dirty = false;
}
});
egui::CentralPanel::default().show(ui, |ui| {
self.tree.common_settings(ui, &mut self.dirty, collections);
self.follow_selection();
if let TreeSelection::Asset(asset) = &mut self.tree.selection {
editor(ui, asset, &mut self.state, &mut self.undo, &mut self.dirty);
}
});
});
},
);
}
pub(crate) fn open(&mut self) {
self.open = true;
self.raise = true;
}
pub(crate) fn open_with(&mut self, definition: Option<AssetId<FixtureDefinition>>) {
self.open();
self.open_request = definition;
}
fn follow_selection(&mut self) {
match &self.tree.selection {
TreeSelection::Asset(asset) if self.state.editing != Some(asset.id.id) => {
self.state.reset_for(Some(asset.id.id), &asset.data);
self.undo.clear();
}
TreeSelection::Asset(asset) => self.state.clamp(&asset.data),
_ if self.state.editing.is_some() => {
self.state.editing = None;
self.undo.clear();
}
_ => {}
}
}
}
fn editor(
ui: &mut Ui,
asset: &mut Asset<FixtureDefinition>,
state: &mut EditorState,
undo: &mut UndoStack<FixtureDefinition>,
dirty: &mut bool,
) {
let asset_id = asset.id.id;
let mut edit = Edit::new(&mut asset.data, undo);
state.caches.begin_frame();
if let Some(picked) = state.file_pick.take() {
picked_file::apply_picked_file(&ui.ctx().clone(), &mut edit, state, asset_id, picked);
}
egui::Panel::right("fixture definition panels")
.default_size(340.0)
.size_range(280.0..=560.0)
.resizable(true)
.show(ui, |ui| {
ScrollArea::vertical().show(ui, |ui| {
CollapsingHeader::new("Selection")
.default_open(true)
.show(ui, |ui| inspector::show(ui, &mut edit, state));
CollapsingHeader::new("Modes")
.default_open(true)
.show(ui, |ui| modes::show(ui, &mut edit, state));
CollapsingHeader::new("Test screen").show(ui, |ui| {
let width = ui.available_width();
let (rect, _) =
ui.allocate_exact_size(vec2(width, width * 0.75), egui::Sense::hover());
test_screen::show_definition(ui, rect, edit.value, state.mode);
});
CollapsingHeader::new("Models")
.default_open(true)
.show(ui, |ui| models::show(ui, asset_id, &mut edit, state));
CollapsingHeader::new("Fixture")
.default_open(true)
.show(ui, |ui| properties::show(ui, &mut edit, state));
});
});
egui::Panel::top("fixture definition toolbar")
.show(ui, |ui| toolbar::show(ui, &mut edit, state));
egui::CentralPanel::default().show(ui, |ui| canvas::show(ui, asset_id, &mut edit, state));
generators::show(ui.ctx(), &mut edit, state);
*dirty |= edit.changed();
}