Merge pull request #1549 from MarcelP102/codex/graphic-attributes-cleanup

[UX] Introducing graphic attributes panel

# Conflicts:
#	locales/ar-SA/opencadstudio.ftl
#	locales/bg-BG/opencadstudio.ftl
#	locales/cs-CZ/opencadstudio.ftl
#	locales/de-DE/opencadstudio.ftl
#	locales/el-GR/opencadstudio.ftl
#	locales/en-US/opencadstudio.ftl
#	locales/es-ES/opencadstudio.ftl
#	locales/fi-FI/opencadstudio.ftl
#	locales/fr-FR/opencadstudio.ftl
#	locales/hi-IN/opencadstudio.ftl
#	locales/hu-HU/opencadstudio.ftl
#	locales/it-IT/opencadstudio.ftl
#	locales/ja-JP/opencadstudio.ftl
#	locales/ko-KR/opencadstudio.ftl
#	locales/lo-LA/opencadstudio.ftl
#	locales/nl-NL/opencadstudio.ftl
#	locales/pl-PL/opencadstudio.ftl
#	locales/pt-BR/opencadstudio.ftl
#	locales/ru-RU/opencadstudio.ftl
#	locales/tr-TR/opencadstudio.ftl
#	locales/zh-CN/opencadstudio.ftl
#	locales/zh-TW/opencadstudio.ftl
#	src/app/mod.rs
#	src/app/update/dialog.rs
#	src/app/view/mod.rs
#	src/locale_catalog.rs
#	src/ui/dock.rs
This commit is contained in:
Hakan Seven committed 2026-10-12 00:49:27 +03:00
commit 1333efcad2
68 files changed
+6178 -173

No files matched your search

+8 -6
View File
@@ -103,7 +103,7 @@ fn family_from_stored_line(
/// Preserve the selected hue while moving its HSL lightness towards the
/// persisted one-colour tint/shade target (0 = black, 1 = white).
fn gradient_tint_color(base: [f32; 4], target: f32) -> [f32; 4] {
pub(crate) fn gradient_tint_color(base: [f32; 4], target: f32) -> [f32; 4] {
let max = base[0].max(base[1]).max(base[2]);
let min = base[0].min(base[1]).min(base[2]);
let lightness = (max + min) * 0.5;
@@ -1394,10 +1394,12 @@ impl Scene {
style.0 = crate::scene::view::render::adapt_to_bg(style.0, hatch_bg);
m.aci = style.4;
m.line_weight_px = style.3;
// A gradient's colour is its first stop (already baked into
// the cached model); only solid / pattern fills take the
// entity's resolved colour.
if !matches!(m.pattern, model::hatch_model::HatchPattern::Gradient { .. }) {
// Gradient RGB comes from its own colour stops, while
// transparency remains an entity property shared by both
// stops. Solid/pattern fills take the complete style.
if matches!(m.pattern, model::hatch_model::HatchPattern::Gradient { .. }) {
m.set_alpha(style.0[3]);
} else {
m.color = style.0;
}
if let EntityType::Hatch(dxf) = e {
@@ -2213,7 +2215,7 @@ impl Scene {
.colors
.get(i)
.and_then(|e| e.color.rgb())
.map(|(r, g, b)| [r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0, 1.0])
.map(|(r, g, b)| [r as f32 / 255.0, g as f32 / 255.0, b as f32 / 255.0, color[3]])
};
gradient_color1 = stop(0);
let color1 = gradient_color1.unwrap_or(color);
+37
View File
@@ -4,6 +4,43 @@ use codec::types::{Vector2, Vector3};
use kernel::geom2d::{refine_spline_boundary, triangulate_rings, Curve, NurbsCurve};
use kernel::tessellation::DEFAULT_ANGLE;
#[test]
fn gradient_stops_keep_entity_transparency() {
let mut hatch = Hatch::new();
hatch.is_solid = true;
hatch
.paths
.push(rectangle([0.0, 0.0], [10.0, 10.0], [0.0; 2]));
hatch.gradient_color.enabled = true;
hatch.gradient_color.name = "LINEAR".into();
hatch.gradient_color.colors = vec![
codec::entities::hatch::GradientColorEntry {
value: 0.0,
color: codec::types::Color::Rgb { r: 255, g: 0, b: 0 },
},
codec::entities::hatch::GradientColorEntry {
value: 1.0,
color: codec::types::Color::Rgb { r: 0, g: 0, b: 255 },
},
];
let mut model = Scene::hatch_model_from_dxf(&hatch, [0.2, 0.3, 0.4, 0.35]).unwrap();
assert!((model.color[3] - 0.35).abs() < f32::EPSILON);
let crate::scene::model::hatch_model::HatchPattern::Gradient { color2, .. } = &model.pattern
else {
panic!("gradient hatch must produce a gradient render pattern");
};
assert!((color2[3] - 0.35).abs() < f32::EPSILON);
model.set_alpha(0.6);
assert!((model.color[3] - 0.6).abs() < f32::EPSILON);
let crate::scene::model::hatch_model::HatchPattern::Gradient { color2, .. } = &model.pattern
else {
unreachable!();
};
assert!((color2[3] - 0.6).abs() < f32::EPSILON);
}
fn narrow(clearance: f64, offset: [f64; 2]) -> NurbsCurve {
let line = |a: [f64; 2], b: [f64; 2]| {
[
+1
View File
@@ -37,6 +37,7 @@ pub use page_setup::{apply_default_page_setup, document_page_setups, rotated_mar
mod dwg_native_constraints;
mod entity;
pub use camera_ops::named_view_center;
pub(crate) use entity::gradient_tint_color;
pub use entity::CreateBlockOptions;
mod group_layer;
#[cfg(test)]
+12
View File
@@ -272,6 +272,18 @@ pub struct HatchModel {
pub draw_depth: f32,
}
impl HatchModel {
/// Apply an entity's resolved opacity to every colour stop. Gradient stop
/// colours come from the HATCH payload, but transparency remains a common
/// entity property and must affect both ends equally.
pub(crate) fn set_alpha(&mut self, alpha: f32) {
self.color[3] = alpha;
if let HatchPattern::Gradient { color2, .. } = &mut self.pattern {
color2[3] = alpha;
}
}
}
impl HatchModel {
pub(crate) fn gradient_frame(
&self,
+10 -2
View File
@@ -475,7 +475,11 @@ impl Scene {
_ => model.clone(),
};
let style = self.render_style(entity);
m.color = style.0;
if matches!(m.pattern, model::hatch_model::HatchPattern::Gradient { .. }) {
m.set_alpha(style.0[3]);
} else {
m.color = style.0;
}
m.aci = style.4;
m.line_weight_px = style.3;
if let EntityType::Hatch(dxf) = entity {
@@ -600,7 +604,11 @@ impl Scene {
_ => model.clone(),
};
let style = self.render_style(entity);
hatch.color = style.0;
if matches!(hatch.pattern, model::hatch_model::HatchPattern::Gradient { .. }) {
hatch.set_alpha(style.0[3]);
} else {
hatch.color = style.0;
}
hatch.aci = style.4;
hatch.line_weight_px = style.3;
hatch.draw_depth = depth_map.get(&handle.value()).map_or(0.0, |depth| depth[0]);