bevel and emboss geliştirme

This commit is contained in:
2026-07-13 20:33:39 +03:00
parent 2284a7d81f
commit 5e03065165
25 changed files with 1165 additions and 405 deletions
+165 -1
View File
@@ -129,6 +129,9 @@ pub struct HcieIcedApp {
pub style_color_picker_idx: usize,
/// HSL color state for the style color picker (hue 0..360, sat 0..1, light 0..1).
pub style_color_hsl: (f32, f32, f32),
/// True when the color picker is editing the shadow color (BevelEmboss),
/// false when editing the highlight color or the single-color style's color.
pub style_color_is_shadow: bool,
/// Currently active color picker tab (0=Wheel, 1=Sliders, 2=Grid).
pub color_tab: usize,
/// Layer Style dialog drag offset from center (x, y) in pixels.
@@ -295,7 +298,12 @@ pub enum Message {
LayerStyleUpdateParam(usize, String, f32),
LayerStyleUpdateBlendMode(usize, String),
LayerStyleUpdateColor(usize, [u8; 4]),
LayerStyleUpdateString(usize, String, String),
LayerStyleUpdateShadowColor(usize, [u8; 4]),
LayerStyleUpdateShadowBlend(usize, String),
LayerStyleUpdateShadowOpacity(usize, f32),
ShowStyleColorPicker(usize),
ShowStyleShadowColorPicker(usize),
HideStyleColorPicker,
OpenLayerStyleDialog,
LayerStyleDialogDragStart(f32, f32),
@@ -532,6 +540,7 @@ impl HcieIcedApp {
show_style_color_picker: false,
style_color_picker_idx: 0,
style_color_hsl: (0.0, 0.0, 0.0),
style_color_is_shadow: false,
color_tab: 0,
layer_style_offset: (0.0, 0.0),
layer_style_dragging: false,
@@ -1238,6 +1247,12 @@ impl HcieIcedApp {
*highlight_opacity = value;
*shadow_opacity = value;
},
(LayerStyle::BevelEmboss { highlight_opacity, .. }, "highlight_opacity") => {
*highlight_opacity = value;
},
(LayerStyle::BevelEmboss { shadow_opacity, .. }, "shadow_opacity") => {
*shadow_opacity = value;
},
(LayerStyle::Satin { opacity, .. }, "opacity") => *opacity = value,
(LayerStyle::Satin { angle, .. }, "angle") => *angle = value,
(LayerStyle::Satin { distance, .. }, "distance") => *distance = value,
@@ -1292,6 +1307,7 @@ impl HcieIcedApp {
| LayerStyle::GradientOverlay { blend_mode, .. }
| LayerStyle::PatternOverlay { blend_mode, .. }
| LayerStyle::Stroke { blend_mode, .. } => *blend_mode = mode,
LayerStyle::BevelEmboss { highlight_blend_mode, .. } => *highlight_blend_mode = mode,
_ => {}
}
self.documents[self.active_doc].engine.update_layer_style(layer_id, new_style);
@@ -1333,7 +1349,13 @@ impl HcieIcedApp {
| LayerStyle::ColorOverlay { color, .. }
| LayerStyle::Satin { color, .. }
| LayerStyle::Stroke { color, .. } => *color = new_color,
LayerStyle::BevelEmboss { highlight_color, .. } => *highlight_color = new_color,
LayerStyle::BevelEmboss { highlight_color, shadow_color, .. } => {
if self.style_color_is_shadow {
*shadow_color = new_color;
} else {
*highlight_color = new_color;
}
}
_ => {}
}
self.documents[self.active_doc].engine.update_layer_style(layer_id, updated_style);
@@ -1353,9 +1375,151 @@ impl HcieIcedApp {
self.refresh_composite_if_needed();
return Task::perform(async {}, |_| Message::CompositeRefresh);
}
Message::LayerStyleUpdateString(index, param, value) => {
let layer_id = self.documents[self.active_doc].engine.active_layer_id();
if layer_id != 0 {
let styles = self.documents[self.active_doc].engine.get_layer_styles(layer_id);
let disc_names = ["DropShadow", "InnerShadow", "OuterGlow", "InnerGlow",
"BevelEmboss", "Satin", "ColorOverlay", "GradientOverlay", "PatternOverlay", "Stroke"];
if index < disc_names.len() {
let disc = disc_names[index];
let existing = styles.iter().find(|s| {
matches!((disc, s),
("BevelEmboss", LayerStyle::BevelEmboss { .. })
| ("DropShadow", LayerStyle::DropShadow { .. })
| ("InnerShadow", LayerStyle::InnerShadow { .. })
)
});
if let Some(style) = existing {
let mut new_style = style.clone();
match (&mut new_style, param.as_str()) {
(LayerStyle::BevelEmboss { style, .. }, "style") => *style = value,
(LayerStyle::BevelEmboss { technique, .. }, "technique") => *technique = value,
(LayerStyle::BevelEmboss { direction, .. }, "direction") => *direction = value,
(LayerStyle::BevelEmboss { highlight_blend_mode, .. }, "highlight_blend") => *highlight_blend_mode = value,
(LayerStyle::BevelEmboss { shadow_blend_mode, .. }, "shadow_blend") => *shadow_blend_mode = value,
_ => {}
}
self.documents[self.active_doc].engine.update_layer_style(layer_id, new_style);
}
}
}
self.refresh_composite_if_needed();
return Task::perform(async {}, |_| Message::CompositeRefresh);
}
Message::LayerStyleUpdateShadowColor(index, new_color) => {
let layer_id = self.documents[self.active_doc].engine.active_layer_id();
if layer_id != 0 {
let styles = self.documents[self.active_doc].engine.get_layer_styles(layer_id);
let disc_names = ["DropShadow", "InnerShadow", "OuterGlow", "InnerGlow",
"BevelEmboss", "Satin", "ColorOverlay", "GradientOverlay", "PatternOverlay", "Stroke"];
if index < disc_names.len() {
let disc = disc_names[index];
let existing = styles.iter().find(|s| {
matches!((disc, s), ("BevelEmboss", LayerStyle::BevelEmboss { .. }))
});
if let Some(style) = existing {
let mut updated_style = style.clone();
if let LayerStyle::BevelEmboss { shadow_color, .. } = &mut updated_style {
*shadow_color = new_color;
}
self.documents[self.active_doc].engine.update_layer_style(layer_id, updated_style);
}
}
}
let r = new_color[0] as f32 / 255.0;
let g = new_color[1] as f32 / 255.0;
let b = new_color[2] as f32 / 255.0;
let max = r.max(g).max(b);
let min = r.min(g).min(b);
let l = (max + min) / 2.0;
let s = if max == min { 0.0 } else if l > 0.5 { (max - min) / (2.0 - max - min) } else { (max - min) / (max + min) };
let h = if max == min { 0.0 } else if max == r { ((g - b) / (max - min) + if g < b { 6.0 } else { 0.0 }) / 6.0 * 360.0 } else if max == g { ((b - r) / (max - min) + 2.0) / 6.0 * 360.0 } else { ((r - g) / (max - min) + 4.0) / 6.0 * 360.0 };
self.style_color_hsl = (h, s, l);
self.refresh_composite_if_needed();
return Task::perform(async {}, |_| Message::CompositeRefresh);
}
Message::LayerStyleUpdateShadowBlend(index, mode) => {
let layer_id = self.documents[self.active_doc].engine.active_layer_id();
if layer_id != 0 {
let styles = self.documents[self.active_doc].engine.get_layer_styles(layer_id);
let disc_names = ["DropShadow", "InnerShadow", "OuterGlow", "InnerGlow",
"BevelEmboss", "Satin", "ColorOverlay", "GradientOverlay", "PatternOverlay", "Stroke"];
if index < disc_names.len() {
let disc = disc_names[index];
let existing = styles.iter().find(|s| {
matches!((disc, s), ("BevelEmboss", LayerStyle::BevelEmboss { .. }))
});
if let Some(style) = existing {
let mut updated_style = style.clone();
if let LayerStyle::BevelEmboss { shadow_blend_mode, .. } = &mut updated_style {
*shadow_blend_mode = mode;
}
self.documents[self.active_doc].engine.update_layer_style(layer_id, updated_style);
}
}
}
self.refresh_composite_if_needed();
return Task::perform(async {}, |_| Message::CompositeRefresh);
}
Message::LayerStyleUpdateShadowOpacity(index, value) => {
let layer_id = self.documents[self.active_doc].engine.active_layer_id();
if layer_id != 0 {
let styles = self.documents[self.active_doc].engine.get_layer_styles(layer_id);
let disc_names = ["DropShadow", "InnerShadow", "OuterGlow", "InnerGlow",
"BevelEmboss", "Satin", "ColorOverlay", "GradientOverlay", "PatternOverlay", "Stroke"];
if index < disc_names.len() {
let disc = disc_names[index];
let existing = styles.iter().find(|s| {
matches!((disc, s), ("BevelEmboss", LayerStyle::BevelEmboss { .. }))
});
if let Some(style) = existing {
let mut updated_style = style.clone();
if let LayerStyle::BevelEmboss { shadow_opacity, .. } = &mut updated_style {
*shadow_opacity = value;
}
self.documents[self.active_doc].engine.update_layer_style(layer_id, updated_style);
}
}
}
self.refresh_composite_if_needed();
return Task::perform(async {}, |_| Message::CompositeRefresh);
}
Message::ShowStyleShadowColorPicker(idx) => {
self.show_style_color_picker = true;
self.style_color_picker_idx = idx;
self.style_color_is_shadow = true;
let disc_names = ["DropShadow", "InnerShadow", "OuterGlow", "InnerGlow",
"BevelEmboss", "Satin", "ColorOverlay", "GradientOverlay", "PatternOverlay", "Stroke"];
let layer_id = self.documents[self.active_doc].engine.active_layer_id();
if layer_id != 0 && idx < disc_names.len() {
let disc = disc_names[idx];
let styles = self.documents[self.active_doc].engine.get_layer_styles(layer_id);
if let Some(style) = styles.iter().find(|s| {
matches!((disc, s), ("BevelEmboss", LayerStyle::BevelEmboss { .. }))
}) {
let color = if let LayerStyle::BevelEmboss { shadow_color, .. } = style {
*shadow_color
} else {
[0, 0, 0, 255]
};
let r = color[0] as f32 / 255.0;
let g = color[1] as f32 / 255.0;
let b = color[2] as f32 / 255.0;
let max = r.max(g).max(b);
let min = r.min(g).min(b);
let l = (max + min) / 2.0;
let s = if max == min { 0.0 } else if l > 0.5 { (max - min) / (2.0 - max - min) } else { (max - min) / (max + min) };
let h = if max == min { 0.0 } else if max == r { ((g - b) / (max - min) + if g < b { 6.0 } else { 0.0 }) / 6.0 * 360.0 } else if max == g { ((b - r) / (max - min) + 2.0) / 6.0 * 360.0 } else { ((r - g) / (max - min) + 4.0) / 6.0 * 360.0 };
self.style_color_hsl = (h, s, l);
}
}
return Task::none();
}
Message::ShowStyleColorPicker(idx) => {
self.show_style_color_picker = true;
self.style_color_picker_idx = idx;
self.style_color_is_shadow = false;
// Initialize HSL from current color
let disc_names = ["DropShadow", "InnerShadow", "OuterGlow", "InnerGlow",
"BevelEmboss", "Satin", "ColorOverlay", "GradientOverlay", "PatternOverlay", "Stroke"];