feat(plugin-api): let add-ons ask for a visual style by name

Removing the binary wireframe event left add-ons with no way to set a
visual style except by spelling out a command string. Give them the
intent back, in the vocabulary everything else now speaks.

The name is carried as text rather than the render-mode type: this crate
is dependency-free by default and only pulls acadrust in behind the host
feature, which is not a weight to add to the manifest contract for one
enum. The host resolves it against the same list its ribbon, its picker
and its commands read, so an add-on can offer exactly the styles the
application does and no others. An unknown name says so and lists the
ones that exist, from that same list.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
Hakan SevenandClaude Opus 5 committed 2026-08-07 14:29:01 +03:00
1 parent b5a1146966
commit f7590b1aa8
3 files changed
+32

No files matched your search

+9
View File
@@ -17,6 +17,15 @@ pub enum ModuleEvent {
/// Remove all loaded models from the scene.
#[allow(dead_code)]
ClearModels,
/// Put the active viewport in a named visual style.
///
/// The name is one of the render modes the viewport can be drawn in:
/// `WIREFRAME2D`, `WIREFRAME3D`, `HIDDENLINE`, `FLATSHADED`,
/// `GOURAUDSHADED`, `FLATSHADEDWITHEDGES`, `GOURAUDSHADEDWITHEDGES`
/// (case-insensitive). The host resolves it against the same list its own
/// ribbon and commands read, so an add-on offers exactly the styles the
/// application does. An unknown name is reported and nothing changes.
SetVisualStyle(String),
/// Toggle the layer manager panel.
ToggleLayers,
/// Ask the host to open a native file picker. On selection the host
+15
View File
@@ -158,6 +158,21 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
self.tabs[i].properties = PropertiesPanel::empty();
self.command_line.push_output(crate::t!("Scene cleared.").as_ref());
}
ModuleEvent::SetVisualStyle(name) => {
use crate::modules::view::visual_style;
match visual_style::mode_for_keyword(&name) {
Some(mode) => return Task::done(Message::SetRenderMode(mode)),
None => {
// Name the styles that do exist, from the same
// list every other caller reads.
self.command_line.push_error(
crate::tf!("Unknown visual style \"{name}\".").as_ref(),
);
self.command_line
.push_info(visual_style::keyword_prompt());
}
}
}
ModuleEvent::ToggleLayers => {
return Task::done(Message::ToggleLayers);
}
+8
View File
@@ -1122,6 +1122,14 @@ pub fn module_event_to_message(event: ModuleEvent) -> Message {
ModuleEvent::Command(cmd) => Message::Command(cmd),
ModuleEvent::OpenFileDialog => Message::OpenFile,
ModuleEvent::ClearModels => Message::ClearScene,
ModuleEvent::SetVisualStyle(name) => {
match crate::modules::view::visual_style::mode_for_keyword(&name) {
Some(mode) => Message::SetRenderMode(mode),
// Report through the command line rather than silently doing
// nothing, so a plugin author sees the typo.
None => Message::Command(format!("VISUALSTYLES {name}")),
}
}
ModuleEvent::ToggleLayers => Message::ToggleLayers,
// Needs the tool context + async picker — route through the normal
// ribbon-click handler rather than a direct 1:1 message.