fixed crash when adding/removing audio bus + fixed crashes in undo/redo

- #930
This commit is contained in:
Dmitry Stepanov
2026-09-22 22:50:29 +03:00
parent 30a27ae391
commit b6089617c6
2 changed files with 56 additions and 77 deletions
+8 -7
View File
@@ -51,7 +51,7 @@ use crate::{
plugins::inspector::editors::resource::{ResourceFieldBuilder, ResourceFieldMessage}, plugins::inspector::editors::resource::{ResourceFieldBuilder, ResourceFieldMessage},
scene::{ scene::{
commands::{ commands::{
effect::{AddAudioBusCommand, LinkAudioBuses, RemoveAudioBusCommand}, effect::{AddOrRemoveAudioBusCommand, LinkAudioBuses},
sound_context::{ sound_context::{
SetDistanceModelCommand, SetHrtfRendererHrirSphereResource, SetRendererCommand, SetDistanceModelCommand, SetHrtfRendererHrirSphereResource, SetRendererCommand,
}, },
@@ -189,10 +189,11 @@ fn fetch_possible_parent_buses(
let mut stack = vec![graph.primary_bus_handle()]; let mut stack = vec![graph.primary_bus_handle()];
let mut result = Vec::new(); let mut result = Vec::new();
while let Some(other_bus) = stack.pop() { while let Some(other_bus) = stack.pop() {
let other_bus_ref = graph.try_get_bus_ref(other_bus).expect("Malformed graph!"); if let Ok(other_bus_ref) = graph.try_get_bus_ref(other_bus) {
if other_bus != bus { if other_bus != bus {
result.push((other_bus, other_bus_ref.name().to_owned())); result.push((other_bus, other_bus_ref.name().to_owned()));
stack.extend_from_slice(other_bus_ref.children()); stack.extend_from_slice(other_bus_ref.children());
}
} }
} }
result result
@@ -375,7 +376,7 @@ impl AudioPanel {
) { ) {
if let Some(ButtonMessage::Click) = message.data() { if let Some(ButtonMessage::Click) = message.data() {
if message.destination() == self.add_bus { if message.destination() == self.add_bus {
sender.do_command(AddAudioBusCommand::new(AudioBus::new( sender.do_command(AddOrRemoveAudioBusCommand::new_add(AudioBus::new(
"AudioBus".to_string(), "AudioBus".to_string(),
))) )))
} else if message.destination() == self.remove_bus { } else if message.destination() == self.remove_bus {
@@ -385,7 +386,7 @@ impl AudioPanel {
))]; ))];
for &bus in &selection.buses { for &bus in &selection.buses {
commands.push(Command::new(RemoveAudioBusCommand::new(bus))); commands.push(Command::new(AddOrRemoveAudioBusCommand::new_remove(bus)));
} }
sender.do_command(CommandGroup::from(commands)); sender.do_command(CommandGroup::from(commands));
+48 -70
View File
@@ -25,107 +25,85 @@ use crate::fyrox::{
use crate::{command::CommandContext, CommandTrait, GameSceneContext}; use crate::{command::CommandContext, CommandTrait, GameSceneContext};
#[derive(Debug)] #[derive(Debug)]
pub struct AddAudioBusCommand { pub struct AddOrRemoveAudioBusCommand {
bus: Option<AudioBus>, bus: Option<AudioBus>,
handle: Handle<AudioBus>, handle: Handle<AudioBus>,
ticket: Option<Ticket<AudioBus>>, ticket: Option<Ticket<AudioBus>>,
add: bool,
} }
impl AddAudioBusCommand { impl AddOrRemoveAudioBusCommand {
pub fn new(bus: AudioBus) -> Self { pub fn new_add(bus: AudioBus) -> Self {
Self { Self {
bus: Some(bus), bus: Some(bus),
handle: Default::default(), handle: Default::default(),
ticket: None, ticket: None,
add: true,
} }
} }
}
impl CommandTrait for AddAudioBusCommand { pub fn new_remove(handle: Handle<AudioBus>) -> Self {
fn name(&mut self, _: &dyn CommandContext) -> String {
"Add Effect".to_owned()
}
fn execute(&mut self, context: &mut dyn CommandContext) {
let context = context.get_mut::<GameSceneContext>();
let mut state = context.scene.graph.sound_context.state();
let parent = state.bus_graph_ref().primary_bus_handle();
self.handle = state
.bus_graph_mut()
.add_bus(self.bus.take().unwrap(), parent);
}
fn revert(&mut self, context: &mut dyn CommandContext) {
let context = context.get_mut::<GameSceneContext>();
let (ticket, effect) = context
.scene
.graph
.sound_context
.state()
.bus_graph_mut()
.try_take_reserve_bus(self.handle)
.unwrap();
self.bus = Some(effect);
self.ticket = Some(ticket);
}
fn finalize(&mut self, context: &mut dyn CommandContext) {
let context = context.get_mut::<GameSceneContext>();
if let Some(ticket) = self.ticket.take() {
context
.scene
.graph
.sound_context
.state()
.bus_graph_mut()
.forget_bus_ticket(ticket);
}
}
}
#[derive(Debug)]
pub struct RemoveAudioBusCommand {
bus: Option<AudioBus>,
handle: Handle<AudioBus>,
ticket: Option<Ticket<AudioBus>>,
}
impl RemoveAudioBusCommand {
pub fn new(handle: Handle<AudioBus>) -> Self {
Self { Self {
bus: None, bus: None,
handle, handle,
ticket: None, ticket: None,
add: false,
} }
} }
}
impl CommandTrait for RemoveAudioBusCommand { fn add(&mut self, context: &mut dyn CommandContext) {
fn name(&mut self, _: &dyn CommandContext) -> String { let context = context.get_mut::<GameSceneContext>();
"Remove Effect".to_owned() let mut state = context.scene.graph.sound_context.state();
let parent = state.bus_graph_ref().primary_bus_handle();
if let Some(bus) = self.bus.take() {
let bus_graph = state.bus_graph_mut();
if let Some(ticket) = self.ticket.take() {
self.handle = bus_graph.put_bus_back(ticket, bus);
} else {
self.handle = bus_graph.add_bus(bus, parent);
}
}
} }
fn execute(&mut self, context: &mut dyn CommandContext) { fn remove(&mut self, context: &mut dyn CommandContext) {
let context = context.get_mut::<GameSceneContext>(); let context = context.get_mut::<GameSceneContext>();
let (ticket, effect) = context if let Ok((ticket, effect)) = context
.scene .scene
.graph .graph
.sound_context .sound_context
.state() .state()
.bus_graph_mut() .bus_graph_mut()
.try_take_reserve_bus(self.handle) .try_take_reserve_bus(self.handle)
.unwrap(); {
self.bus = Some(effect); self.bus = Some(effect);
self.ticket = Some(ticket); self.ticket = Some(ticket);
}
}
}
impl CommandTrait for AddOrRemoveAudioBusCommand {
fn name(&mut self, _: &dyn CommandContext) -> String {
if self.add {
"Add Audio Bus".to_owned()
} else {
"Remove Audio Bus".to_owned()
}
}
fn execute(&mut self, context: &mut dyn CommandContext) {
if self.add {
self.add(context)
} else {
self.remove(context)
}
} }
fn revert(&mut self, context: &mut dyn CommandContext) { fn revert(&mut self, context: &mut dyn CommandContext) {
let context = context.get_mut::<GameSceneContext>(); if self.add {
let mut state = context.scene.graph.sound_context.state(); self.remove(context);
let parent = state.bus_graph_ref().primary_bus_handle(); } else {
self.handle = state self.add(context);
.bus_graph_mut() }
.add_bus(self.bus.take().unwrap(), parent);
} }
fn finalize(&mut self, context: &mut dyn CommandContext) { fn finalize(&mut self, context: &mut dyn CommandContext) {