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},
scene::{
commands::{
effect::{AddAudioBusCommand, LinkAudioBuses, RemoveAudioBusCommand},
effect::{AddOrRemoveAudioBusCommand, LinkAudioBuses},
sound_context::{
SetDistanceModelCommand, SetHrtfRendererHrirSphereResource, SetRendererCommand,
},
@@ -189,10 +189,11 @@ fn fetch_possible_parent_buses(
let mut stack = vec![graph.primary_bus_handle()];
let mut result = Vec::new();
while let Some(other_bus) = stack.pop() {
let other_bus_ref = graph.try_get_bus_ref(other_bus).expect("Malformed graph!");
if other_bus != bus {
result.push((other_bus, other_bus_ref.name().to_owned()));
stack.extend_from_slice(other_bus_ref.children());
if let Ok(other_bus_ref) = graph.try_get_bus_ref(other_bus) {
if other_bus != bus {
result.push((other_bus, other_bus_ref.name().to_owned()));
stack.extend_from_slice(other_bus_ref.children());
}
}
}
result
@@ -375,7 +376,7 @@ impl AudioPanel {
) {
if let Some(ButtonMessage::Click) = message.data() {
if message.destination() == self.add_bus {
sender.do_command(AddAudioBusCommand::new(AudioBus::new(
sender.do_command(AddOrRemoveAudioBusCommand::new_add(AudioBus::new(
"AudioBus".to_string(),
)))
} else if message.destination() == self.remove_bus {
@@ -385,7 +386,7 @@ impl AudioPanel {
))];
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));
+48 -70
View File
@@ -25,107 +25,85 @@ use crate::fyrox::{
use crate::{command::CommandContext, CommandTrait, GameSceneContext};
#[derive(Debug)]
pub struct AddAudioBusCommand {
pub struct AddOrRemoveAudioBusCommand {
bus: Option<AudioBus>,
handle: Handle<AudioBus>,
ticket: Option<Ticket<AudioBus>>,
add: bool,
}
impl AddAudioBusCommand {
pub fn new(bus: AudioBus) -> Self {
impl AddOrRemoveAudioBusCommand {
pub fn new_add(bus: AudioBus) -> Self {
Self {
bus: Some(bus),
handle: Default::default(),
ticket: None,
add: true,
}
}
}
impl CommandTrait for AddAudioBusCommand {
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 {
pub fn new_remove(handle: Handle<AudioBus>) -> Self {
Self {
bus: None,
handle,
ticket: None,
add: false,
}
}
}
impl CommandTrait for RemoveAudioBusCommand {
fn name(&mut self, _: &dyn CommandContext) -> String {
"Remove Effect".to_owned()
fn add(&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();
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 (ticket, effect) = context
if let Ok((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);
{
self.bus = Some(effect);
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) {
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);
if self.add {
self.remove(context);
} else {
self.add(context);
}
}
fn finalize(&mut self, context: &mut dyn CommandContext) {