forked from 1b-agent/opencadstudio-upstream
fix(blocks): reopen evaluated references in their authoring definition
Resolve BEDIT reference entry through the native dynamic-definition link instead of editing the anonymous geometry variant. Preserve static-block fallback and existing lock/xref checks. Add synthetic regressions for evaluated-reference DWG reload and save/close/reedit, plus Rotation-only save/close/reopen followed by Flip placement. Validated with 334 block tests passing (6 existing opt-in tests ignored).
This commit is contained in:
1 parent
de7ed432fb
commit
1ee432ac64
2 files changed
+122
-1
No files matched your search
@@ -59,6 +59,117 @@ fn feed(app: &mut OpenCADStudio, text: &str) {
|
||||
let _ = app.update(Message::CommandSubmit);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_parameters_rotation_only_save_close_reopen_then_flip() {
|
||||
use crate::scene::block_actions::{self as actions, Kind};
|
||||
for save_command in ["BEDIT_SAVE", "BSAVE"] {
|
||||
let (mut app, reference) = fixture();
|
||||
begin(&mut app, reference);
|
||||
let i = app.active_tab;
|
||||
let def = app.tabs[i].active_block_edit_session().unwrap().br_handle;
|
||||
let _ = app.run_command_line("BPARAMETER ROTATION 0,0 10 0");
|
||||
assert_eq!(
|
||||
actions::parameters(&app.tabs[i].scene.document, def, Kind::Rotate).len(),
|
||||
1
|
||||
);
|
||||
let _ = app.dispatch_command(save_command);
|
||||
if save_command == "BSAVE" {
|
||||
let _ = app.dispatch_command("BCLOSE");
|
||||
}
|
||||
assert!(app.tabs[i].active_block_edit.is_none());
|
||||
begin(&mut app, reference);
|
||||
assert_eq!(
|
||||
actions::parameters(&app.tabs[i].scene.document, def, Kind::Rotate).len(),
|
||||
1,
|
||||
"{save_command}"
|
||||
);
|
||||
let _ = app.run_command_line("BPARAMETER FLIP 0,0 10,0 -2,2");
|
||||
assert_eq!(
|
||||
actions::parameters(&app.tabs[i].scene.document, def, Kind::Flip).len(),
|
||||
1
|
||||
);
|
||||
let _ = app.dispatch_command("BEDIT_SAVE");
|
||||
begin(&mut app, reference);
|
||||
assert_eq!(
|
||||
actions::parameters(&app.tabs[i].scene.document, def, Kind::Rotate).len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(
|
||||
actions::parameters(&app.tabs[i].scene.document, def, Kind::Flip).len(),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_actions_save_close_and_reedit_evaluated_reference() {
|
||||
use crate::scene::block_actions::{self as actions, Kind};
|
||||
let (mut app, reference) = fixture();
|
||||
begin(&mut app, reference);
|
||||
let i = app.active_tab;
|
||||
let def = app.tabs[i].active_block_edit_session().unwrap().br_handle;
|
||||
let _ = app.run_command_line("BPARAMETER LINEAR 0,0 10,0 5,2");
|
||||
let p = actions::parameters(&app.tabs[i].scene.document, def, Kind::Move)[0].clone();
|
||||
let targets = members(&app);
|
||||
actions::create(
|
||||
&mut app.tabs[i].scene.document,
|
||||
def,
|
||||
Kind::Move,
|
||||
p.handle,
|
||||
&targets,
|
||||
glam::DVec3::ZERO,
|
||||
)
|
||||
.unwrap();
|
||||
let _ = app.dispatch_command("BSAVE");
|
||||
let _ = app.dispatch_command("BCLOSE");
|
||||
assert!(app.tabs[i].active_block_edit.is_none());
|
||||
assert_eq!(
|
||||
actions::parameters(&app.tabs[i].scene.document, def, Kind::Move).len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(actions::actions(&app.tabs[i].scene.document, def).len(), 1);
|
||||
app.tabs[i].scene.selected.insert(reference);
|
||||
app.refresh_properties();
|
||||
let grip = app.tabs[i]
|
||||
.selected_grips
|
||||
.iter()
|
||||
.find(|g| super::block_actions::is_test_grip(g.id))
|
||||
.unwrap()
|
||||
.id;
|
||||
assert!(app.start_test_action_grip(reference, grip));
|
||||
feed(&mut app, "12,0");
|
||||
let EntityType::Insert(insert) = app.tabs[i].scene.document.get_entity(reference).unwrap()
|
||||
else {
|
||||
panic!()
|
||||
};
|
||||
assert_ne!(insert.block_name, "EDIT_ME");
|
||||
// Native save/reload must preserve the link from the evaluated variant to
|
||||
// the definition that owns the parameters and actions.
|
||||
let bytes = codec::DwgWriter::write_to_vec(&app.tabs[i].scene.document).unwrap();
|
||||
app.tabs[i].scene.document = codec::DwgReader::from_stream(std::io::Cursor::new(bytes))
|
||||
.read()
|
||||
.unwrap();
|
||||
app.tabs[i].scene.selected.insert(reference);
|
||||
let _ = app.dispatch_command("BEDIT");
|
||||
assert_eq!(
|
||||
app.tabs[i].active_block_edit_session().unwrap().br_handle,
|
||||
def
|
||||
);
|
||||
assert_eq!(
|
||||
actions::parameters(&app.tabs[i].scene.document, def, Kind::Move).len(),
|
||||
1
|
||||
);
|
||||
assert_eq!(actions::actions(&app.tabs[i].scene.document, def).len(), 1);
|
||||
let _ = app.dispatch_command("BSAVE");
|
||||
let _ = app.dispatch_command("BCLOSE");
|
||||
app.tabs[i].scene.selected.insert(reference);
|
||||
app.refresh_properties();
|
||||
assert!(app.tabs[i]
|
||||
.selected_grips
|
||||
.iter()
|
||||
.any(|g| super::block_actions::is_test_grip(g.id)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_actions_rotate_flip_mouse_grips_authoring_history_and_reopen() {
|
||||
use crate::scene::block_actions::{self as actions, Kind};
|
||||
|
||||
@@ -536,7 +536,17 @@ impl OpenCADStudio {
|
||||
return Some(Task::none());
|
||||
}
|
||||
match self.tabs[i].scene.document.get_entity(insert_handle) {
|
||||
Some(codec::EntityType::Insert(ins)) => ins.block_name.clone(),
|
||||
Some(codec::EntityType::Insert(ins)) => {
|
||||
// Evaluated INSERTs point at anonymous geometry variants.
|
||||
// Their authoring graph belongs to the original definition.
|
||||
let doc = &self.tabs[i].scene.document;
|
||||
doc.dynamic_definition_for_insert(insert_handle)
|
||||
.and_then(|definition| {
|
||||
doc.block_records.iter().find(|br| br.handle == definition)
|
||||
})
|
||||
.map(|br| br.name.clone())
|
||||
.unwrap_or_else(|| ins.block_name.clone())
|
||||
}
|
||||
_ => {
|
||||
self.command_line.push_error(
|
||||
crate::t!("BEDIT: selected object is not a block reference.")
|
||||
|
||||
Reference in new issue
Block a user