diff options
| author | HampusM <hampus@hampusmat.com> | 2026-08-20 19:15:59 +0200 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-08-20 19:15:59 +0200 |
| commit | 3a225d721757e67405a2fa095e68118895ae048f (patch) | |
| tree | c956e02f43e7b3363316c2ec5c77df1d0c9004a4 /engine/src/ui | |
| parent | 14bd4580f580f36920bc2ea465592bfc08b50b2b (diff) | |
feat(engine): use color edit widgets for colors in world ui view
Diffstat (limited to 'engine/src/ui')
| -rw-r--r-- | engine/src/ui/view/world.rs | 187 |
1 files changed, 184 insertions, 3 deletions
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<ItemType> { + if let Some(TypeReflection::Struct(_)) = ty { + if type_id == TypeId::of::<Rgb<f32>>() { + return Some(ItemType::Color(ColorItemType::Rgb, LiteralType::F32)); + } + if type_id == TypeId::of::<Rgb<u8>>() { + return Some(ItemType::Color(ColorItemType::Rgb, LiteralType::U8)); + } + + if type_id == TypeId::of::<Rgba<f32>>() { + return Some(ItemType::Color(ColorItemType::Rgba, LiteralType::F32)); + } + if type_id == TypeId::of::<Rgba<u8>>() { + 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::<String>() { Some(ItemType::String) } else if type_id == TypeId::of::<Cow<'static, str>>() { @@ -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<T: Clone + 'static>(self) -> OwnedOrRefMut<'item, T> + { + match self { + ItemRef::Mutable(item) => OwnedOrRefMut::Ref( + (*item) + .downcast_mut::<T>() + .expect("Cannot downcast: wrong item type"), + ), + ItemRef::Immutable(item) => OwnedOrRefMut::Owned( + (*item) + .downcast_ref::<T>() + .expect("Cannot downcast: wrong item type") + .clone(), + ), + } + } } impl AsRef<dyn Any> for ItemRef<'_> @@ -947,6 +991,37 @@ impl AsRef<dyn Any> for ItemRef<'_> } } +#[derive(Debug)] +pub enum OwnedOrRefMut<'a, Value> +{ + Ref(&'a mut Value), + Owned(Value), +} + +impl<Value> Deref for OwnedOrRefMut<'_, Value> +{ + type Target = Value; + + fn deref(&self) -> &Self::Target + { + match self { + Self::Ref(value) => *value, + Self::Owned(value) => value, + } + } +} + +impl<Value> 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::<Rgb<f32>>(); + + 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::<Rgb<u8>>(); + + 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::<Rgba<f32>>(); + + 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::<Rgba<u8>>(); + + 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!(), } } |
