forked from 1b-agent/opencadstudio-upstream
Point clouds: POINTCLOUDMANAGER palette
A dockable Point Cloud Manager lists each point cloud of the drawing (only the selected ones while any is selected) with Regions (disabled, region data is not read), Unassigned Points and Scans, the scans named by their file stems. Each switch shows or hides points: the cloud, its unassigned points, all scans or one scan. The hidden set is the cloud's OCS_POINTCLOUD_VISIBILITY extended data (scan names plus *CLOUD_OFF / *UNASSIGNED_OFF markers, app id registered), written as one undo step and kept on save. The drawn points skip hidden scans by their index ranges, and the hidden set is part of the placed-cloud key. Collapse all / expand all, row highlight and a search box that filters rows (keeping parents of matches). POINTCLOUDMANAGERCLOSE closes it; the pc_manager_toggle automation action flips a switch. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
7761652a9f
commit
ac9a6b07b9
35 files changed
+673
-13
No files matched your search
@@ -736,6 +736,8 @@ inventory::submit!(crate::command::CommandRegistration {
|
||||
"EXPORTSTEP",
|
||||
"EXPORTSTL",
|
||||
"EXTERNALREFERENCES",
|
||||
"POINTCLOUDMANAGER",
|
||||
"POINTCLOUDMANAGERCLOSE",
|
||||
"EXTRIM",
|
||||
"FILETAB",
|
||||
"FIND",
|
||||
|
||||
@@ -34,7 +34,13 @@ impl OpenCADStudio {
|
||||
common.color.clone()
|
||||
};
|
||||
let color = color.rgb().map_or([255; 3], |(r, g, b)| [r, g, b]);
|
||||
if let Some(placed) = crate::scene::model::point_cloud::placed(document, data, color, None) {
|
||||
if let Some(placed) = crate::scene::model::point_cloud::placed(
|
||||
document,
|
||||
data,
|
||||
color,
|
||||
None,
|
||||
&crate::scene::model::point_cloud::hidden(common),
|
||||
) {
|
||||
clouds.push((common.handle, placed));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,6 +162,59 @@ impl OpenCADStudio {
|
||||
self.refresh_properties();
|
||||
}
|
||||
|
||||
/// A Point Cloud Manager click: a switch writes the cloud's visibility
|
||||
/// extended data as one undo step; the rest is palette state.
|
||||
pub(in crate::app) fn update_pc_manager(&mut self, message: crate::ui::window::pc_manager::PcManagerMsg) -> Task<Message> {
|
||||
use crate::scene::model::point_cloud::VISIBILITY_APP;
|
||||
use crate::ui::window::pc_manager::{self, PcManagerMsg};
|
||||
let i = self.active_tab;
|
||||
match message {
|
||||
PcManagerMsg::Toggle(handle, row) => {
|
||||
let Some(cloud) =
|
||||
pc_manager::clouds(&self.tabs[i].scene.document, &[]).into_iter().find(|c| c.handle == handle)
|
||||
else {
|
||||
return Task::none();
|
||||
};
|
||||
if self.tabs[i].scene.is_layer_locked(handle) {
|
||||
return Task::none();
|
||||
}
|
||||
let hidden = pc_manager::toggled(&cloud.hidden, &cloud.scans, &row);
|
||||
self.push_undo_snapshot(i, "POINTCLOUDMANAGER");
|
||||
self.tabs[i].scene.ensure_app_id(VISIBILITY_APP);
|
||||
let app_handle = self.tabs[i].scene.document.app_ids.get(VISIBILITY_APP).map(|a| a.handle.value());
|
||||
if let Some(entity) = self.tabs[i].scene.document.get_entity_mut(handle) {
|
||||
let data = &mut entity.common_mut().extended_data;
|
||||
if let Some(app) = app_handle {
|
||||
data.raw_dwg_eed.retain(|(a, _)| *a != app);
|
||||
}
|
||||
data.remove_record(VISIBILITY_APP);
|
||||
if !hidden.is_empty() {
|
||||
let mut record = codec::xdata::ExtendedDataRecord::new(VISIBILITY_APP);
|
||||
for name in hidden {
|
||||
record.add_value(codec::xdata::XDataValue::String(name));
|
||||
}
|
||||
data.add_record(record);
|
||||
}
|
||||
}
|
||||
self.tabs[i].scene.bump_entities(&[(handle, crate::scene::ChangeKind::Modified)]);
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
PcManagerMsg::Expand(key) => {
|
||||
if !self.pc_manager.collapsed.remove(&key) {
|
||||
self.pc_manager.collapsed.insert(key);
|
||||
}
|
||||
}
|
||||
PcManagerMsg::Select(key) => self.pc_manager.selected = Some(key),
|
||||
PcManagerMsg::Search(text) => self.pc_manager.search = text,
|
||||
PcManagerMsg::CollapseAll => {
|
||||
let clouds = pc_manager::clouds(&self.tabs[i].scene.document, &[]);
|
||||
self.pc_manager.collapsed.extend(pc_manager::folding_keys(&clouds));
|
||||
}
|
||||
PcManagerMsg::ExpandAll => self.pc_manager.collapsed.clear(),
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
/// One undo step that edits every selected PDF underlay.
|
||||
fn edit_selected_underlays(&mut self, i: usize, label: &str, edit: impl Fn(&mut Underlay)) {
|
||||
let handles: Vec<_> = self
|
||||
@@ -319,7 +372,23 @@ impl OpenCADStudio {
|
||||
crop.inverted = !crop.inverted;
|
||||
}
|
||||
}),
|
||||
"_PCUNCROP" => self.edit_selected_point_clouds(i, "POINTCLOUDUNCROP", |data| data.croppings.clear()),
|
||||
// The Point Cloud Manager docks on the right like External
|
||||
// References and opens expanded.
|
||||
"POINTCLOUDMANAGER" => {
|
||||
let id = crate::ui::dock::PanelId::PointCloudManager;
|
||||
self.pc_manager.show = true;
|
||||
if self.dock.location(id).is_none() {
|
||||
self.dock.dock(id, crate::app::config::DockSide::Right, usize::MAX);
|
||||
}
|
||||
self.dock_expanded = Some(id);
|
||||
}
|
||||
"POINTCLOUDMANAGERCLOSE" => {
|
||||
self.pc_manager.show = false;
|
||||
if self.dock_expanded == Some(crate::ui::dock::PanelId::PointCloudManager) {
|
||||
self.dock_expanded = None;
|
||||
}
|
||||
}
|
||||
"_PCUNCROP" =>self.edit_selected_point_clouds(i, "POINTCLOUDUNCROP", |data| data.croppings.clear()),
|
||||
"_PDFULUNCLIP" => {
|
||||
self.edit_selected_underlays(i, "PDFCLIP", |u| {
|
||||
u.clip_boundary_vertices.clear();
|
||||
|
||||
Reference in new issue
Block a user