forked from 1b-agent/opencadstudio-upstream
The codec and kernel repositories and crates are renamed opencadcodec and opencadkernel. Inside OCS they are depended on under short keys, so code reads `codec::`, `kernel::` and the new `graph::` (opencadgraph, the node graph engine). File-format and protocol spellings stay as they were: the ACIS product id `acadrust`, the ACADRUST_* switches and the plugin version keys `acadrust_version` / `acadrust_source`. A button left of MCP on the command line opens a translucent node graph over the viewport, with a palette of object, input, math, logic, list, text and geometry nodes added by click or drag. An object node owns drawing entities and its rows are the Properties panel's own rows for them: the single-object page is extracted from refresh_properties as entity_property_sections, values use the control protocol's property_json, and writes go through set_property_value with a property target override, so the panel, MCP and the graph share one read/write path. A list reaching an object row makes one entity per element. Each graph action is one undo step; the canvas pans and zooms. Co-Authored-By: Claude Opus 5.5 <[email protected]>
121 lines
5.3 KiB
Rust
121 lines
5.3 KiB
Rust
// BEDIT — block editor as a dedicated "space" tab (issue #261).
|
|
//
|
|
// Workflow:
|
|
// 1. BEDIT: user picks an INSERT (or has one pre-selected).
|
|
// 2. A block-editor space opens: rendering, picking and new geometry are
|
|
// scoped to the block's record, so ONLY the block's own (block-local)
|
|
// entities are drawn — no INSERT transform, they show exactly as stored.
|
|
// 3. The user edits them with normal commands. Because they ARE the block
|
|
// definition's entities, edits are live.
|
|
// 4. Save Block (BEDIT_SAVE): keep the edits and leave the block space.
|
|
// Discard (BEDIT_DISCARD): restore the block to its on-entry snapshot.
|
|
//
|
|
// Unlike REFEDIT (which copies entities into model space with the INSERT
|
|
// transform and inverse-transforms them back on save), a BEDIT space edits the
|
|
// block record in place, so there is no copy-back and no transform — the space
|
|
// render filter (`current_layout_block_handle`) already draws only the block.
|
|
|
|
use codec::{EntityType, Handle};
|
|
use glam::DVec3;
|
|
|
|
use crate::command::{CadCommand, CmdResult};
|
|
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
|
|
|
/// Right-edge side-toolbar buttons shown while a BEDIT block-editor space is
|
|
/// active: save the block edits and leave, or discard them.
|
|
pub fn block_edit_tools() -> Vec<ToolDef> {
|
|
vec![
|
|
ToolDef {
|
|
id: "BEDIT_SAVE",
|
|
label: "Save Block",
|
|
icon: IconKind::Svg(include_bytes!("../../../../assets/icons/mt_ok.svg")),
|
|
event: ModuleEvent::Command("BEDIT_SAVE".to_string()),
|
|
},
|
|
ToolDef {
|
|
id: "BEDIT_DISCARD",
|
|
label: "Discard Block Edit",
|
|
icon: IconKind::Svg(include_bytes!("../../../../assets/icons/mt_cancel.svg")),
|
|
event: ModuleEvent::Command("BEDIT_DISCARD".to_string()),
|
|
},
|
|
]
|
|
}
|
|
|
|
// ── Session state (held in DocumentTab) ───────────────────────────────────
|
|
|
|
/// One open BEDIT block-editor tab. Lives in `DocumentTab::block_edits`.
|
|
#[derive(Clone)]
|
|
pub struct BlockEditSession {
|
|
/// Name of the block being edited (also the space-tab label).
|
|
pub block_name: String,
|
|
/// Handle of the block record whose entities are being edited.
|
|
pub br_handle: Handle,
|
|
/// Space to return to when the block editor closes (the layout that was
|
|
/// active when BEDIT began).
|
|
pub return_layout: String,
|
|
/// Parent block tab to return to for a nested BEDIT session. `None` returns
|
|
/// to `return_layout`.
|
|
pub return_block: Option<String>,
|
|
/// The complete block definition captured on entry, so Discard restores
|
|
/// structural markers and content with their original handles.
|
|
pub snapshot: Vec<EntityType>,
|
|
/// Baked anonymous dimension-block entities transformed alongside
|
|
/// dimensions in this definition. They remain in place, so Discard can
|
|
/// restore their shared before-images directly.
|
|
pub dependent_snapshot: Vec<std::sync::Arc<EntityType>>,
|
|
/// Inline ATTRIB values/positions on every existing INSERT of this block.
|
|
/// Rebasing the origin moves them with the definition; Discard restores
|
|
/// their exact on-entry state.
|
|
pub reference_attributes:
|
|
Vec<(Handle, Vec<codec::entities::AttributeEntity>)>,
|
|
/// Camera state of the space that was active when BEDIT began, restored
|
|
/// on Save/Discard so the view returns exactly where it was (#425).
|
|
pub return_camera: crate::scene::view::camera::Camera,
|
|
/// Camera owned by this block tab. Updated whenever another space tab is
|
|
/// activated, then restored when the user returns to this block.
|
|
pub editor_camera: crate::scene::view::camera::Camera,
|
|
/// Transient UCS being manipulated in this block tab. On commit its full
|
|
/// frame is baked into the definition and this returns to `None`.
|
|
pub editor_ucs: Option<codec::tables::Ucs>,
|
|
}
|
|
|
|
// ── BEDIT pick command ─────────────────────────────────────────────────────
|
|
|
|
/// Step 1: wait for the user to pick a single INSERT entity to edit.
|
|
pub struct BlockEditPickCommand;
|
|
|
|
impl BlockEditPickCommand {
|
|
pub fn new() -> Self {
|
|
Self
|
|
}
|
|
}
|
|
|
|
impl CadCommand for BlockEditPickCommand {
|
|
fn name(&self) -> &'static str {
|
|
"BEDIT"
|
|
}
|
|
fn prompt(&self) -> String {
|
|
crate::t!("BEDIT Select block reference to edit:").into_owned()
|
|
}
|
|
fn needs_entity_pick(&self) -> bool {
|
|
true
|
|
}
|
|
fn on_entity_pick(&mut self, handle: Handle, _pt: DVec3) -> CmdResult {
|
|
if handle.is_null() {
|
|
return CmdResult::NeedPoint;
|
|
}
|
|
// Signal the host to open the block-editor space for this INSERT.
|
|
CmdResult::Relaunch(format!("BEDIT_BEGIN:{}", handle.value()), vec![handle])
|
|
}
|
|
fn on_point(&mut self, _pt: DVec3) -> CmdResult {
|
|
CmdResult::NeedPoint
|
|
}
|
|
fn on_enter(&mut self) -> CmdResult {
|
|
CmdResult::Cancel
|
|
}
|
|
}
|
|
|
|
// ── Autocomplete registry ─────────────────────────────────
|
|
inventory::submit!(crate::command::CommandRegistration { names: &["BEDIT"] }); // BlockEditPickCommand
|
|
inventory::submit!(crate::command::CommandRegistration { names: &["BEDIT_SAVE"] });
|
|
inventory::submit!(crate::command::CommandRegistration { names: &["BEDIT_DISCARD"] });
|