forked from 1b-agent/opencadstudio-upstream
- Gradients: the middle colour sits (horizon - 0.5) viewport widths from the centre and blends over height viewport heights each side; two colours blend over a viewport height each side. - Image backgrounds: offset in device pixels (right, down), negative scale mirrors, fitted with aspect ratio covers the viewport; the dialog keeps an image's offset and scale. - Layouts: a model-space view restored on a sheet asks for the viewport, enters it and gives it the view's camera, background and visual style; inside a viewport the view goes there; a paper-space view's background is kept on the sheet viewport but not drawn; floating viewports draw their background. - Background objects no view or viewport uses any more are erased; a view without a background restored where the viewport already is leaves the viewport's background. - The viewport's named visual style (Realistic, ...) shows by name and the render-mode picker records its style on the viewport record. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
150 lines
5.4 KiB
Rust
150 lines
5.4 KiB
Rust
// The visual styles a viewport can be drawn in, in one list.
|
|
//
|
|
// Three places offer the same choice and used to describe it separately: the
|
|
// Visual Style dropdown on the ribbon, the render-mode picker with its preview
|
|
// cube, and the VISUALSTYLES command. The ribbon's copy had drifted furthest —
|
|
// it named four styles, two of which reached nothing (its "Shaded" carried the
|
|
// id `SOLID`, which is the 2D solid *drawing* command, and `HIDDEN` matched no
|
|
// command at all). Naming each style once, next to the command that applies it,
|
|
// is what keeps the three in step. (#621)
|
|
|
|
use codec::entities::ViewportRenderMode as Mode;
|
|
|
|
use crate::modules::IconKind;
|
|
|
|
const WIREFRAME_ICON: IconKind =
|
|
IconKind::Svg(include_bytes!("../../../assets/icons/wireframe.svg"));
|
|
const HIDDEN_ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/hidden.svg"));
|
|
const SHADED_ICON: IconKind = IconKind::Svg(include_bytes!("../../../assets/icons/solid.svg"));
|
|
|
|
pub struct VisualStyle {
|
|
pub mode: Mode,
|
|
/// What the user sees, wherever the style is offered.
|
|
pub label: &'static str,
|
|
/// The command line that applies it. Ribbon items dispatch this verbatim,
|
|
/// so it doubles as the item's identity for the checkmark and the
|
|
/// last-used-tool memory. The keyword is the render mode's own name — there
|
|
/// is one set of styles now, so there is one set of names for them.
|
|
pub command: &'static str,
|
|
pub icon: IconKind,
|
|
}
|
|
|
|
/// Every style, in the order they are offered — wireframes, then hidden line,
|
|
/// then the shaded ones, each pair plain before with-edges.
|
|
pub const VISUAL_STYLES: &[VisualStyle] = &[
|
|
VisualStyle {
|
|
mode: Mode::Wireframe2D,
|
|
label: "Wireframe 2D",
|
|
command: "VISUALSTYLES WIREFRAME2D",
|
|
icon: WIREFRAME_ICON,
|
|
},
|
|
VisualStyle {
|
|
mode: Mode::Wireframe3D,
|
|
label: "Wireframe 3D",
|
|
command: "VISUALSTYLES WIREFRAME3D",
|
|
icon: WIREFRAME_ICON,
|
|
},
|
|
VisualStyle {
|
|
mode: Mode::HiddenLine,
|
|
label: "Hidden Line",
|
|
command: "VISUALSTYLES HIDDENLINE",
|
|
icon: HIDDEN_ICON,
|
|
},
|
|
VisualStyle {
|
|
mode: Mode::FlatShaded,
|
|
label: "Flat Shaded",
|
|
command: "VISUALSTYLES FLATSHADED",
|
|
icon: SHADED_ICON,
|
|
},
|
|
VisualStyle {
|
|
mode: Mode::GouraudShaded,
|
|
label: "Gouraud Shaded",
|
|
command: "VISUALSTYLES GOURAUDSHADED",
|
|
icon: SHADED_ICON,
|
|
},
|
|
VisualStyle {
|
|
mode: Mode::FlatShadedWithEdges,
|
|
label: "Flat Shaded + Edges",
|
|
command: "VISUALSTYLES FLATSHADEDWITHEDGES",
|
|
icon: SHADED_ICON,
|
|
},
|
|
VisualStyle {
|
|
mode: Mode::GouraudShadedWithEdges,
|
|
label: "Gouraud Shaded + Edges",
|
|
command: "VISUALSTYLES GOURAUDSHADEDWITHEDGES",
|
|
icon: SHADED_ICON,
|
|
},
|
|
];
|
|
|
|
impl VisualStyle {
|
|
/// The bare keyword, without the verb its `command` spells out.
|
|
pub fn keyword(&self) -> &'static str {
|
|
self.command
|
|
.strip_prefix("VISUALSTYLES ")
|
|
.unwrap_or(self.command)
|
|
}
|
|
}
|
|
|
|
/// The choices an interactive style prompt offers, in table order.
|
|
pub fn keyword_choices() -> Vec<(&'static str, &'static str, Option<&'static str>)> {
|
|
VISUAL_STYLES
|
|
.iter()
|
|
.map(|style| (style.label, style.keyword(), None))
|
|
.collect()
|
|
}
|
|
|
|
/// Stable source used by the shared command prompt translator.
|
|
pub fn keyword_prompt() -> &'static str {
|
|
"Visual style [Wireframe 2D/Wireframe 3D/Hidden Line/Flat Shaded/Gouraud Shaded/Flat Shaded + Edges/Gouraud Shaded + Edges]:"
|
|
}
|
|
|
|
pub fn label_for(mode: Mode) -> &'static str {
|
|
VISUAL_STYLES
|
|
.iter()
|
|
.find(|style| style.mode == mode)
|
|
.map(|style| style.label)
|
|
.unwrap_or("Wireframe 2D")
|
|
}
|
|
|
|
/// The render mode a named visual style draws as, and whether the name is a
|
|
/// style of its own (Realistic, Conceptual, …) rather than one of the modes.
|
|
pub fn mode_for_style_name(name: &str) -> Option<(Mode, bool)> {
|
|
Some(match name {
|
|
"2dWireframe" => (Mode::Wireframe2D, false),
|
|
"Wireframe" => (Mode::Wireframe3D, false),
|
|
"Hidden" => (Mode::HiddenLine, false),
|
|
"Flat" => (Mode::FlatShaded, false),
|
|
"FlatWithEdges" => (Mode::FlatShadedWithEdges, false),
|
|
"Gouraud" => (Mode::GouraudShaded, false),
|
|
"GouraudWithEdges" => (Mode::GouraudShadedWithEdges, false),
|
|
"Shaded with edges" => (Mode::GouraudShadedWithEdges, true),
|
|
"Realistic" | "Shaded" | "Conceptual" | "Shades of Gray" | "Sketchy" | "X-Ray" => {
|
|
(Mode::GouraudShaded, true)
|
|
}
|
|
_ => return None,
|
|
})
|
|
}
|
|
|
|
/// The name of the visual style a render mode is saved as.
|
|
pub fn style_name_for(mode: Mode) -> &'static str {
|
|
match mode {
|
|
Mode::Wireframe2D => "2dWireframe",
|
|
Mode::Wireframe3D => "Wireframe",
|
|
Mode::HiddenLine => "Hidden",
|
|
Mode::FlatShaded => "Flat",
|
|
Mode::FlatShadedWithEdges => "FlatWithEdges",
|
|
Mode::GouraudShaded => "Gouraud",
|
|
Mode::GouraudShadedWithEdges => "GouraudWithEdges",
|
|
}
|
|
}
|
|
|
|
/// The style a style keyword names. Only the seven exist; nothing maps onto a
|
|
/// nearest neighbour, because there is no longer anything else to map from.
|
|
pub fn mode_for_keyword(keyword: &str) -> Option<Mode> {
|
|
let keyword = keyword.trim().to_uppercase();
|
|
VISUAL_STYLES
|
|
.iter()
|
|
.find(|style| style.keyword() == keyword)
|
|
.map(|style| style.mode)
|
|
}
|