Skip to content

Commit

Permalink
Unify all inspectors into a single tab (#46)
Browse files Browse the repository at this point in the history
With the addition of animation state machines, the number of different
inspector tabs was getting a bit ridiculous. Rather than have a separate
tab per kind of inspector, this PR adopts the approach taken by most
modern editors where only an "active" inspector is shown, generally for
the last thing you clicked.
  • Loading branch information
mbrea-c authored Jun 29, 2024
1 parent 9afae9d commit 388d501
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 64 deletions.
10 changes: 5 additions & 5 deletions assets/animation_graphs/toplevel.animgraph.ron
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
(
nodes: [
(
name: "Le big fsm",
name: "Locomotion FSM",
node: Fsm("fsm/meme.fsm.ron"),
),
],
edges_inverted: {
OutputTime: NodeTime("Le big fsm"),
NodeData("Le big fsm", "driver events"): InputData("les eventos"),
OutputData("pose"): NodeData("Le big fsm", "pose"),
OutputTime: NodeTime("Locomotion FSM"),
OutputData("pose"): NodeData("Locomotion FSM", "pose"),
NodeData("Locomotion FSM", "driver events"): InputData("les eventos"),
},
default_parameters: {
"les eventos": EventQueue((
Expand All @@ -30,7 +30,7 @@
output_time: Some(()),
extra: (
node_positions: {
"Le big fsm": (467.3684, 642.7369),
"Locomotion FSM": (447.06067, 482.12152),
},
input_position: (192.0, 475.0),
output_position: (727.0, 463.0),
Expand Down
14 changes: 14 additions & 0 deletions crates/bevy_animation_graph_editor/src/egui_fsm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ pub struct FrameState {
graph_changes: Vec<EguiFsmChange>,

nodes_tmp: HashMap<usize, Node>,
/// Whether the node got clicked in this frame
just_selected_node: bool,
just_selected_transition: bool,
}

/// The settings that are used by the node editor context
Expand Down Expand Up @@ -109,6 +112,8 @@ impl FrameState {
Option::take(&mut self.active_pin);

self.graph_changes.clear();
self.just_selected_node = false;
self.just_selected_transition = false;
}

pub fn canvas_origin_screen_space(&self) -> egui::Vec2 {
Expand Down Expand Up @@ -355,6 +360,13 @@ impl FsmUiContext {
pub fn get_changes(&self) -> &Vec<EguiFsmChange> {
&self.frame_state.graph_changes
}

pub fn is_node_just_selected(&self) -> bool {
self.frame_state.just_selected_node
}
pub fn is_transition_just_selected(&self) -> bool {
self.frame_state.just_selected_transition
}
}

impl FsmUiContext {
Expand Down Expand Up @@ -1024,6 +1036,7 @@ impl FsmUiContext {
self.state.selected_node_indices.clear();
self.state.selected_link_indices.clear();
self.state.selected_link_indices.push(idx);
self.frame_state.just_selected_transition = true;
}

fn find_duplicate_link(&self, start_pin_idx: usize, end_pin_idx: usize) -> Option<usize> {
Expand All @@ -1047,6 +1060,7 @@ impl FsmUiContext {
self.state.selected_node_indices.clear();
self.state.selected_link_indices.clear();
self.state.selected_node_indices.push(idx);
self.frame_state.just_selected_node = true;

if let Some(depth_idx) = self.state.node_depth_order.iter().position(|x| *x == idx) {
let id = self.state.node_depth_order.remove(depth_idx);
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_animation_graph_editor/src/egui_nodes/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub struct FrameState {

pins_tmp: HashMap<usize, Pin>,
nodes_tmp: HashMap<usize, Node>,
just_selected_node: bool,
}

/// The settings that are used by the node editor context
Expand Down Expand Up @@ -112,6 +113,7 @@ impl FrameState {
Option::take(&mut self.active_pin);

self.graph_changes.clear();
self.just_selected_node = false;
}

pub fn canvas_origin_screen_space(&self) -> egui::Vec2 {
Expand Down Expand Up @@ -521,6 +523,10 @@ impl NodesContext {
pub fn get_node_dimensions(&self, id: usize) -> Option<egui::Vec2> {
self.nodes.get(&id).map(|n| n.state.rect.size())
}

pub fn is_node_just_selected(&self) -> bool {
self.frame_state.just_selected_node
}
}

impl NodesContext {
Expand Down Expand Up @@ -1424,6 +1430,7 @@ impl NodesContext {
self.state.selected_node_indices.clear();
self.state.selected_link_indices.clear();
self.state.selected_node_indices.push(idx);
self.frame_state.just_selected_node = true;

if let Some(depth_idx) = self.state.node_depth_order.iter().position(|x| *x == idx) {
let id = self.state.node_depth_order.remove(depth_idx);
Expand Down
117 changes: 58 additions & 59 deletions crates/bevy_animation_graph_editor/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ pub struct FsmSelection {
pub enum InspectorSelection {
FsmTransition(FsmTransitionSelection),
FsmState(FsmStateSelection),
Node(NodeSelection),
/// The selection data is contained in the GraphSelection, not here. This is because the graph
/// should not become unselected whenever the inspector window shows something else.
Graph,
/// The selection data is contained in the FsmSelection, not here. This is because the FSM
/// should not become unselected whenever the inspector window shows something else.
Fsm,
#[default]
Nothing,
}
Expand All @@ -93,7 +100,6 @@ pub struct NodeSelection {
pub struct SceneSelection {
scene: Handle<AnimatedScene>,
respawn: bool,
// TODO: Use context ids
active_context: HashMap<UntypedAssetId, GraphContextId>,
}

Expand All @@ -107,7 +113,6 @@ pub struct EditorSelection {
pub graph_editor: Option<GraphSelection>,
pub fsm_editor: Option<FsmSelection>,
pub inspector_selection: InspectorSelection,
node: Option<NodeSelection>,
scene: Option<SceneSelection>,
node_creation: NodeCreation,
entity_path: Option<EntityPath>,
Expand Down Expand Up @@ -138,18 +143,8 @@ impl UiState {
pub fn new() -> Self {
let mut state = DockState::new(vec![EguiWindow::GraphEditor, EguiWindow::FsmEditor]);
let tree = state.main_surface_mut();
let [graph_editor, inspectors] = tree.split_right(
NodeIndex::root(),
0.75,
vec![
EguiWindow::NodeInspector,
EguiWindow::StateInspector,
EguiWindow::GraphInspector,
EguiWindow::NodeCreate,
EguiWindow::Inspector,
EguiWindow::FsmInspector,
],
);
let [graph_editor, inspectors] =
tree.split_right(NodeIndex::root(), 0.75, vec![EguiWindow::Inspector]);
let [_graph_editor, graph_selector] =
tree.split_left(graph_editor, 0.2, vec![EguiWindow::GraphSelector]);
let [_graph_selector, scene_selector] =
Expand Down Expand Up @@ -207,17 +202,12 @@ impl UiState {
enum EguiWindow {
GraphEditor,
FsmEditor,
NodeCreate,
Preview,
PreviewHierarchy,
PreviewErrors,
GraphSelector,
SceneSelector,
FsmSelector,
NodeInspector,
StateInspector,
GraphInspector,
FsmInspector,
Inspector,
GraphSaver(AssetId<AnimationGraph>, String, bool),
FsmSaver(AssetId<StateMachine>, String, bool),
Expand All @@ -227,21 +217,16 @@ impl EguiWindow {
pub fn display_name(&self) -> String {
match self {
EguiWindow::GraphEditor => "Graph Editor".into(),
EguiWindow::NodeCreate => "Create Node".into(),
EguiWindow::Preview => "Preview Scene".into(),
EguiWindow::PreviewHierarchy => "Preview Hierarchy".into(),
EguiWindow::PreviewErrors => "Errors".into(),
EguiWindow::GraphSelector => "Select Graph".into(),
EguiWindow::SceneSelector => "Select Scene".into(),
EguiWindow::FsmSelector => "Select FSM".into(),
EguiWindow::NodeInspector => "Inspect Node".into(),
EguiWindow::GraphInspector => "Inspect Graph IO".into(),
EguiWindow::GraphSaver(_, _, _) => "Save Graph".into(),
EguiWindow::FsmSaver(_, _, _) => "Save State Machine".into(),
EguiWindow::FsmEditor => "FSM Editor".into(),
EguiWindow::StateInspector => "Inspect State".into(),
EguiWindow::Inspector => "Inspector (FSM State/Transition)".into(),
EguiWindow::FsmInspector => "Inspect FSM".into(),
EguiWindow::Inspector => "Inspector".into(),
}
}
}
Expand Down Expand Up @@ -275,21 +260,9 @@ impl egui_dock::TabViewer for TabViewer<'_> {
self.save_requests,
);
}
EguiWindow::NodeInspector => {
Self::node_inspector(self.world, ui, self.selection, self.graph_changes);
}
EguiWindow::GraphInspector => {
Self::graph_inspector(self.world, ui, self.selection, self.graph_changes);
}
EguiWindow::FsmInspector => {
Self::fsm_inspector(self.world, ui, self.selection, self.global_changes);
}
EguiWindow::Preview => {
Self::animated_scene_preview(self.world, ui, self.preview_image, self.selection);
}
EguiWindow::NodeCreate => {
Self::node_creator(self.world, ui, self.selection, self.graph_changes);
}
EguiWindow::GraphSaver(graph, path, done) => {
Self::graph_saver(ui, self.graph_save_events, *graph, path, done);
}
Expand All @@ -311,7 +284,6 @@ impl egui_dock::TabViewer for TabViewer<'_> {
self.save_requests,
);
}
EguiWindow::StateInspector => {}
EguiWindow::Inspector => match &self.selection.inspector_selection {
InspectorSelection::FsmTransition(_) => {
Self::transition_inspector(self.world, ui, self.selection, self.global_changes)
Expand All @@ -320,6 +292,15 @@ impl egui_dock::TabViewer for TabViewer<'_> {
Self::state_inspector(self.world, ui, self.selection, self.global_changes)
}
InspectorSelection::Nothing => {}
InspectorSelection::Node(_) => {
Self::node_inspector(self.world, ui, self.selection, self.graph_changes)
}
InspectorSelection::Graph => {
Self::graph_inspector(self.world, ui, self.selection, self.graph_changes)
}
InspectorSelection::Fsm => {
Self::fsm_inspector(self.world, ui, self.selection, self.global_changes)
}
},
}

Expand Down Expand Up @@ -541,20 +522,23 @@ impl TabViewer<'_> {
.name(*selected_node)
.unwrap();
graph.nodes.get_mut(node_name).unwrap().should_debug = true;
if let Some(node_selection) = &mut selection.node {
if let InspectorSelection::Node(node_selection) =
&mut selection.inspector_selection
{
if &node_selection.node != node_name
|| node_selection.graph != graph_selection.graph
{
node_selection.node.clone_from(node_name);
node_selection.name_buf.clone_from(node_name);
node_selection.graph = graph_selection.graph;
}
} else {
selection.node = Some(NodeSelection {
graph: graph_selection.graph,
node: node_name.clone(),
name_buf: node_name.clone(),
});
} else if graph_selection.nodes_context.is_node_just_selected() {
selection.inspector_selection =
InspectorSelection::Node(NodeSelection {
graph: graph_selection.graph,
node: node_name.clone(),
name_buf: node_name.clone(),
});
}
}
}
Expand Down Expand Up @@ -664,11 +648,13 @@ impl TabViewer<'_> {
.state_indices
.name(*selected_node)
.unwrap();
selection.inspector_selection =
InspectorSelection::FsmState(FsmStateSelection {
fsm: fsm_selection.fsm,
state: state_name.clone(),
});
if fsm_selection.nodes_context.is_node_just_selected() {
selection.inspector_selection =
InspectorSelection::FsmState(FsmStateSelection {
fsm: fsm_selection.fsm,
state: state_name.clone(),
});
}
}

if let Some(selected_transition) = fsm_selection
Expand All @@ -682,11 +668,13 @@ impl TabViewer<'_> {
.transition_indices
.edge(*selected_transition)
.unwrap();
selection.inspector_selection =
InspectorSelection::FsmTransition(FsmTransitionSelection {
fsm: fsm_selection.fsm,
state: transition_id.clone(),
});
if fsm_selection.nodes_context.is_transition_just_selected() {
selection.inspector_selection =
InspectorSelection::FsmTransition(FsmTransitionSelection {
fsm: fsm_selection.fsm,
state: transition_id.clone(),
});
}
}
// ----------------------------------------------------------------
});
Expand Down Expand Up @@ -736,6 +724,7 @@ impl TabViewer<'_> {
graph_indices: Self::update_graph_indices(world, chosen_id),
nodes_context: NodesContext::default(),
});
selection.inspector_selection = InspectorSelection::Graph;
}
}

Expand Down Expand Up @@ -807,6 +796,7 @@ impl TabViewer<'_> {
state_creation: State::default(),
transition_creation: Transition::default(),
});
selection.inspector_selection = InspectorSelection::Fsm;
}
}

Expand All @@ -816,6 +806,12 @@ impl TabViewer<'_> {
selection: &mut EditorSelection,
graph_changes: &mut Vec<GraphChange>,
) {
ui.heading("Animation graph");

ui.collapsing("Create node", |ui| {
Self::node_creator(world, ui, selection, graph_changes)
});

let mut changes = Vec::new();

select_graph_context(world, ui, selection);
Expand Down Expand Up @@ -868,6 +864,7 @@ impl TabViewer<'_> {
selection: &mut EditorSelection,
global_changes: &mut Vec<GlobalChange>,
) {
ui.heading("State machine");
let mut changes = Vec::new();

select_graph_context_fsm(world, ui, selection);
Expand Down Expand Up @@ -1011,9 +1008,11 @@ impl TabViewer<'_> {
selection: &mut EditorSelection,
graph_changes: &mut Vec<GraphChange>,
) {
ui.heading("Graph node");

let mut changes = Vec::new();

let Some(node_selection) = &mut selection.node else {
let InspectorSelection::Node(node_selection) = &mut selection.inspector_selection else {
return;
};

Expand All @@ -1032,7 +1031,7 @@ impl TabViewer<'_> {
};
let graph = graph_assets.get_mut(node_selection.graph).unwrap();
let Some(node) = graph.nodes.get_mut(&node_selection.node) else {
selection.node = None;
selection.inspector_selection = InspectorSelection::Nothing;
return;
};

Expand Down Expand Up @@ -1076,7 +1075,7 @@ impl TabViewer<'_> {
selection: &mut EditorSelection,
graph_changes: &mut Vec<GlobalChange>,
) {
ui.label("FSM State");
ui.heading("FSM State");

let mut changes = Vec::new();

Expand Down Expand Up @@ -1138,7 +1137,7 @@ impl TabViewer<'_> {
selection: &mut EditorSelection,
global_changes: &mut Vec<GlobalChange>,
) {
ui.label("FSM Transition");
ui.heading("FSM Transition");
let mut changes = Vec::new();

let Some(fsm_selection) = &mut selection.fsm_editor else {
Expand Down

0 comments on commit 388d501

Please sign in to comment.