From 3a225d721757e67405a2fa095e68118895ae048f Mon Sep 17 00:00:00 2001 From: HampusM Date: Thu, 20 Aug 2026 19:15:59 +0200 Subject: feat(engine): use color edit widgets for colors in world ui view --- engine/src/ui/view/world.rs | 187 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 3 deletions(-) (limited to 'engine') diff --git a/engine/src/ui/view/world.rs b/engine/src/ui/view/world.rs index 335756f..ff4c13a 100644 --- a/engine/src/ui/view/world.rs +++ b/engine/src/ui/view/world.rs @@ -1,7 +1,9 @@ use std::any::{Any, TypeId}; use std::borrow::Cow; use std::io::Cursor; +use std::ops::{Deref, DerefMut}; +use crate::color::{Rgb, Rgba}; use crate::ecs::actions::Actions; use crate::ecs::component::local::Local; use crate::ecs::component::{ @@ -843,6 +845,7 @@ enum ItemType Reflected(&'static TypeReflection), String, CowStr, + Color(ColorItemType, LiteralType), } impl ItemType @@ -859,6 +862,7 @@ impl ItemType Self::Reflected(TypeReflection::Reference(ref_ty)) => { ItemType::Reflected(ref_ty.ty).spans_multiple_rows() } + Self::Color(..) => false, Self::Reflected(TypeReflection::Literal(_)) | Self::String | Self::CowStr => { false } @@ -881,11 +885,34 @@ impl ItemType } } +#[derive(Debug)] +enum ColorItemType +{ + Rgb, + Rgba, +} + fn get_item_type(ty: Option<&'static TypeReflection>, type_id: TypeId) -> Option { + if let Some(TypeReflection::Struct(_)) = ty { + if type_id == TypeId::of::>() { + return Some(ItemType::Color(ColorItemType::Rgb, LiteralType::F32)); + } + if type_id == TypeId::of::>() { + return Some(ItemType::Color(ColorItemType::Rgb, LiteralType::U8)); + } + + if type_id == TypeId::of::>() { + return Some(ItemType::Color(ColorItemType::Rgba, LiteralType::F32)); + } + if type_id == TypeId::of::>() { + return Some(ItemType::Color(ColorItemType::Rgba, LiteralType::U8)); + } + } + if let Some(ty) = ty { - Some(ItemType::Reflected(ty)) + return Some(ItemType::Reflected(ty)); } else if type_id == TypeId::of::() { Some(ItemType::String) } else if type_id == TypeId::of::>() { @@ -901,7 +928,7 @@ enum ItemRef<'item> Immutable(&'item dyn Any), } -impl ItemRef<'_> +impl<'item> ItemRef<'item> { fn get_struct_field( &mut self, @@ -934,6 +961,23 @@ impl ItemRef<'_> } } } + + fn into_writable(self) -> OwnedOrRefMut<'item, T> + { + match self { + ItemRef::Mutable(item) => OwnedOrRefMut::Ref( + (*item) + .downcast_mut::() + .expect("Cannot downcast: wrong item type"), + ), + ItemRef::Immutable(item) => OwnedOrRefMut::Owned( + (*item) + .downcast_ref::() + .expect("Cannot downcast: wrong item type") + .clone(), + ), + } + } } impl AsRef for ItemRef<'_> @@ -947,6 +991,37 @@ impl AsRef for ItemRef<'_> } } +#[derive(Debug)] +pub enum OwnedOrRefMut<'a, Value> +{ + Ref(&'a mut Value), + Owned(Value), +} + +impl Deref for OwnedOrRefMut<'_, Value> +{ + type Target = Value; + + fn deref(&self) -> &Self::Target + { + match self { + Self::Ref(value) => *value, + Self::Owned(value) => value, + } + } +} + +impl DerefMut for OwnedOrRefMut<'_, Value> +{ + fn deref_mut(&mut self) -> &mut Self::Target + { + match self { + Self::Ref(value) => *value, + Self::Owned(value) => value, + } + } +} + fn create_item_title_widget( frame: &dear_imgui_bindings::Ui, item_title: &str, @@ -1374,6 +1449,111 @@ fn add_item_to_frame<'a>( *data_changed = true; } } + ItemType::Color(ColorItemType::Rgb, LiteralType::F32) => { + let mut item = item.into_writable::>(); + + let mut scratch = [item.r, item.g, item.b]; + + if frame + .color_edit3_config( + create_item_label(&item_tag, "value_input", &prev_item_tags), + &mut scratch, + ) + .display_mode(dear_imgui_bindings::ColorDisplayMode::Hex) + .build() + { + let [new_r, new_g, new_b] = scratch; + + *item = Rgb { r: new_r, g: new_g, b: new_b }; + + *data_changed = true; + } + } + ItemType::Color(ColorItemType::Rgb, LiteralType::U8) => { + let mut item = item.into_writable::>(); + + let mut scratch = [ + item.r as f32 / 255.0, + item.g as f32 / 255.0, + item.b as f32 / 255.0, + ]; + + if frame + .color_edit3_config( + create_item_label(&item_tag, "value_input", &prev_item_tags), + &mut scratch, + ) + .display_mode(dear_imgui_bindings::ColorDisplayMode::Hex) + .build() + { + let [new_r, new_g, new_b] = scratch; + + *item = Rgb { + r: (new_r * 255.0) as u8, + g: (new_g * 255.0) as u8, + b: (new_b * 255.0) as u8, + }; + + *data_changed = true; + } + } + ItemType::Color(ColorItemType::Rgba, LiteralType::F32) => { + let mut item = item.into_writable::>(); + + let mut scratch = [item.r, item.g, item.b, item.a]; + + if frame + .color_edit4_config( + create_item_label(&item_tag, "value_input", &prev_item_tags), + &mut scratch, + ) + .display_mode(dear_imgui_bindings::ColorDisplayMode::Hex) + .build() + { + let [new_r, new_g, new_b, new_a] = scratch; + + *item = Rgba { + r: new_r, + g: new_g, + b: new_b, + a: new_a, + }; + + *data_changed = true; + } + } + ItemType::Color(ColorItemType::Rgba, LiteralType::U8) => { + let mut item = item.into_writable::>(); + + let mut scratch = [ + item.r as f32 / 255.0, + item.g as f32 / 255.0, + item.b as f32 / 255.0, + item.a as f32 / 255.0, + ]; + + if frame + .color_edit4_config( + create_item_label(&item_tag, "value_input", &prev_item_tags), + &mut scratch, + ) + .display_mode(dear_imgui_bindings::ColorDisplayMode::Hex) + .build() + { + let [new_r, new_g, new_b, new_a] = scratch; + + *item = Rgba { + r: (new_r * 255.0) as u8, + g: (new_g * 255.0) as u8, + b: (new_b * 255.0) as u8, + a: (new_a * 255.0) as u8, + }; + + *data_changed = true; + } + } + ItemType::Color(ColorItemType::Rgb, _) => unreachable!(), + ItemType::Color(ColorItemType::Rgba, _) => unreachable!(), ItemType::Reflected(_) => unimplemented!(), } } @@ -1809,7 +1989,8 @@ fn get_whole_type_is_user_editable( | TypeReflection::Literal(_), ) | ItemType::String - | ItemType::CowStr => true, + | ItemType::CowStr + | ItemType::Color(..) => true, ItemType::Reflected(_) => unimplemented!(), } } -- cgit v1.2.3-18-g5258