summaryrefslogtreecommitdiff
path: root/engine/src/ui/view/world.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/ui/view/world.rs')
-rw-r--r--engine/src/ui/view/world.rs397
1 files changed, 321 insertions, 76 deletions
diff --git a/engine/src/ui/view/world.rs b/engine/src/ui/view/world.rs
index ccdbfb3..2bf3ca5 100644
--- a/engine/src/ui/view/world.rs
+++ b/engine/src/ui/view/world.rs
@@ -17,7 +17,10 @@ use crate::ecs::{Component, Query, World};
use crate::image::{Format as ImageFormat, Image};
use crate::reflection::{
Enum as EnumReflection,
+ EnumVariant as EnumVariantReflection,
+ GetError as ReflectionGetError,
LiteralType,
+ Struct as StructReflection,
Type as TypeReflection,
Visibility,
};
@@ -333,6 +336,13 @@ fn create_component_widgets(
let mut component_changed = false;
+ create_item_title_widget(
+ frame,
+ component_info.name,
+ &ItemType::Reflected(component_type),
+ None,
+ );
+
add_item_to_frame(
frame,
ItemRef::Mutable(&mut *component),
@@ -452,6 +462,13 @@ fn create_pair_component_widgets(
let mut component_changed = false;
+ create_item_title_widget(
+ frame,
+ pair_data_comp_info.name,
+ &ItemType::Reflected(pair_data_ty),
+ None,
+ );
+
add_item_to_frame(
frame,
ItemRef::Mutable(&mut *pair_data),
@@ -727,6 +744,13 @@ fn show_add_component_popup(
unreachable!();
};
+ create_item_title_widget(
+ frame,
+ new_component_info.name,
+ &ItemType::Reflected(new_component_type),
+ None,
+ );
+
add_item_to_frame(
frame,
ItemRef::Mutable(&mut **new_component),
@@ -820,6 +844,27 @@ enum ItemType
CowStr,
}
+impl ItemType
+{
+ fn spans_multiple_rows(&self) -> bool
+ {
+ match self {
+ Self::Reflected(
+ TypeReflection::Struct(_)
+ | TypeReflection::Array(_)
+ | TypeReflection::Slice(_),
+ ) => true,
+ Self::Reflected(TypeReflection::Enum(enum_ty)) if !enum_ty.is_unit_only => {
+ true
+ }
+ Self::Reflected(TypeReflection::Reference(ref_ty)) => {
+ ItemType::Reflected(ref_ty.ty).spans_multiple_rows()
+ }
+ _ => false,
+ }
+ }
+}
+
fn get_item_type(ty: Option<&'static TypeReflection>, type_id: TypeId)
-> Option<ItemType>
{
@@ -840,6 +885,41 @@ enum ItemRef<'item>
Immutable(&'item dyn Any),
}
+impl ItemRef<'_>
+{
+ fn get_struct_field(
+ &mut self,
+ ty: &StructReflection,
+ field_index: usize,
+ ) -> Result<ItemRef<'_>, ReflectionGetError>
+ {
+ match self {
+ ItemRef::Mutable(item) => {
+ (ty.try_get_field_mut)(*item, field_index).map(ItemRef::Mutable)
+ }
+ ItemRef::Immutable(item) => {
+ (ty.try_get_field)(*item, field_index).map(ItemRef::Immutable)
+ }
+ }
+ }
+
+ fn get_enum_variant_field(
+ &mut self,
+ variant: &EnumVariantReflection,
+ field_index: usize,
+ ) -> Result<ItemRef<'_>, ReflectionGetError>
+ {
+ match self {
+ ItemRef::Mutable(item) => {
+ (variant.try_get_field_mut)(*item, field_index).map(ItemRef::Mutable)
+ }
+ ItemRef::Immutable(item) => {
+ (variant.try_get_field)(*item, field_index).map(ItemRef::Immutable)
+ }
+ }
+ }
+}
+
impl AsRef<dyn Any> for ItemRef<'_>
{
fn as_ref(&self) -> &dyn Any
@@ -851,6 +931,24 @@ impl AsRef<dyn Any> for ItemRef<'_>
}
}
+fn create_item_title_widget(
+ frame: &dear_imgui_bindings::Ui,
+ item_title: &str,
+ item_type: &ItemType,
+ item_type_name: Option<&str>,
+)
+{
+ if !matches!(item_type, ItemType::Reflected(TypeReflection::Reference(_))) {
+ frame.text(&item_title);
+
+ if let Some(item_type_name) = item_type_name {
+ if frame.is_item_hovered() {
+ frame.tooltip_text(item_type_name);
+ }
+ }
+ }
+}
+
fn add_item_to_frame<'a>(
frame: &dear_imgui_bindings::Ui,
mut item: ItemRef<'_>,
@@ -865,16 +963,6 @@ fn add_item_to_frame<'a>(
prev_item_tags: &[&'a str],
)
{
- if !matches!(item_type, ItemType::Reflected(TypeReflection::Reference(_))) {
- frame.text(&item_title);
-
- if let Some(item_type_name) = item_type_name {
- if frame.is_item_hovered() {
- frame.tooltip_text(item_type_name);
- }
- }
- }
-
let _disabled = frame.begin_disabled_with_cond(
!matches!(
item_type,
@@ -888,56 +976,18 @@ fn add_item_to_frame<'a>(
);
match item_type {
- ItemType::Reflected(TypeReflection::Struct(struct_reflection)) => {
+ ItemType::Reflected(TypeReflection::Struct(struct_ty)) => {
frame.indent();
- let mut prev_item_tags = prev_item_tags.to_vec();
-
- prev_item_tags.push(item_tag.as_ref());
-
- for (field_index, field) in struct_reflection.fields.iter().enumerate() {
- let field_name = field
- .name
- .map(Cow::Borrowed)
- .unwrap_or_else(|| field_index.to_string().into());
-
- let Some(field_item_type) =
- get_item_type(field.type_reflection(), field.type_id)
- else {
- continue;
- };
-
- let Ok(field_item) = (match &mut item {
- ItemRef::Mutable(item) => {
- (struct_reflection.try_get_field_mut)(*item, field_index)
- .map(ItemRef::Mutable)
- }
- ItemRef::Immutable(item) => {
- (struct_reflection.try_get_field)(*item, field_index)
- .map(ItemRef::Immutable)
- }
- }) else {
- unreachable!();
- };
-
- add_item_to_frame(
- frame,
- field_item,
- data_changed,
- ItemInfo {
- item_title: field_name.as_ref(),
- item_tag: field_name.as_ref(),
- item_type_name: Some(field.type_name()),
- item_type: field_item_type,
- item_is_read_only: item_is_read_only
- || matches!(
- field.visibility,
- Visibility::Private | Visibility::PubScoped(_)
- ),
- },
- &prev_item_tags,
- );
- }
+ create_struct_widgets(
+ frame,
+ &mut item,
+ data_changed,
+ item_tag,
+ item_is_read_only,
+ struct_ty,
+ prev_item_tags,
+ );
frame.unindent();
}
@@ -1163,6 +1213,13 @@ fn add_item_to_frame<'a>(
unreachable!();
};
+ create_item_title_widget(
+ frame,
+ &array_item_name,
+ &ItemType::Reflected(array_type.item_type),
+ Some(array_type.item_type_name()),
+ );
+
add_item_to_frame(
frame,
item_item,
@@ -1201,6 +1258,13 @@ fn add_item_to_frame<'a>(
let mut slice_item_changed = false;
+ create_item_title_widget(
+ frame,
+ &item_name,
+ &ItemType::Reflected(slice_type.item_type),
+ Some(slice_type.item_type_name()),
+ );
+
add_item_to_frame(
frame,
ItemRef::Immutable(item_item),
@@ -1227,6 +1291,13 @@ fn add_item_to_frame<'a>(
unreachable!();
};
+ create_item_title_widget(
+ frame,
+ item_title,
+ &ItemType::Reflected(ref_type.ty),
+ item_type_name,
+ );
+
add_item_to_frame(
frame,
ItemRef::Immutable(derefed_item),
@@ -1344,6 +1415,132 @@ fn create_scalar_item_input<Scalar>(
}
}
+fn item_layout_table<'frame>(
+ frame: &'frame dear_imgui_bindings::Ui,
+ prev_item_tags: &[&str],
+) -> dear_imgui_bindings::TableBuilder<'frame>
+{
+ frame
+ .table(create_item_label("item_layout", "table", &prev_item_tags))
+ .headers(false)
+ .sizing_policy(dear_imgui_bindings::TableSizingPolicy::StretchSame)
+ .columns([
+ dear_imgui_bindings::TableColumnSetup::new("a"),
+ dear_imgui_bindings::TableColumnSetup::new("b").stretch_weight(2.0),
+ ])
+}
+
+fn create_struct_widgets(
+ frame: &dear_imgui_bindings::Ui,
+ item: &mut ItemRef<'_>,
+ data_changed: &mut bool,
+ item_tag: &str,
+ item_is_read_only: bool,
+ struct_ty: &StructReflection,
+ prev_item_tags: &[&str],
+)
+{
+ let mut prev_item_tags = prev_item_tags.to_vec();
+
+ prev_item_tags.push(item_tag.as_ref());
+
+ let struct_fields =
+ struct_ty
+ .fields
+ .iter()
+ .enumerate()
+ .filter_map(|(field_index, field)| {
+ let field_item_type =
+ get_item_type(field.type_reflection(), field.type_id)?;
+
+ Some((field_index, field, field_item_type))
+ });
+
+ item_layout_table(frame, &prev_item_tags).build(|frame| {
+ for (field_index, field, field_item_type) in struct_fields
+ .clone()
+ .filter(|(.., field_item_type)| !field_item_type.spans_multiple_rows())
+ {
+ frame.table_next_row();
+ frame.table_next_column();
+
+ let field_name = field
+ .name
+ .map(Cow::Borrowed)
+ .unwrap_or_else(|| field_index.to_string().into());
+
+ let Ok(field_item) = item.get_struct_field(struct_ty, field_index) else {
+ unreachable!();
+ };
+
+ create_item_title_widget(
+ frame,
+ &field_name,
+ &field_item_type,
+ Some(field.type_name()),
+ );
+
+ frame.table_next_column();
+
+ add_item_to_frame(
+ frame,
+ field_item,
+ data_changed,
+ ItemInfo {
+ item_title: field_name.as_ref(),
+ item_tag: field_name.as_ref(),
+ item_type_name: Some(field.type_name()),
+ item_type: field_item_type,
+ item_is_read_only: item_is_read_only
+ || matches!(
+ field.visibility,
+ Visibility::Private | Visibility::PubScoped(_)
+ ),
+ },
+ &prev_item_tags,
+ );
+ }
+ });
+
+ for (field_index, field, field_item_type) in struct_fields
+ .filter(|(.., field_item_type)| field_item_type.spans_multiple_rows())
+ {
+ let field_name = field
+ .name
+ .map(Cow::Borrowed)
+ .unwrap_or_else(|| field_index.to_string().into());
+
+ let Ok(field_item) = item.get_struct_field(struct_ty, field_index) else {
+ unreachable!();
+ };
+
+ create_item_title_widget(
+ frame,
+ &field_name,
+ &field_item_type,
+ Some(field.type_name()),
+ );
+
+ add_item_to_frame(
+ frame,
+ field_item,
+ data_changed,
+ ItemInfo {
+ item_title: field_name.as_ref(),
+ item_tag: field_name.as_ref(),
+ item_type_name: Some(field.type_name()),
+ item_type: field_item_type,
+ item_is_read_only: item_is_read_only
+ || matches!(
+ field.visibility,
+ Visibility::Private | Visibility::PubScoped(_)
+ ),
+ },
+ &prev_item_tags,
+ );
+ }
+}
+
fn create_enum_widgets(
frame: &dear_imgui_bindings::Ui,
item: &mut ItemRef<'_>,
@@ -1438,32 +1635,45 @@ fn create_enum_widgets(
let curr_variant = &enum_type.variants[curr_variant_index];
- if let Some(curr_variant_fields) = &curr_variant.fields {
- for (field_index, field) in curr_variant_fields.fields().iter().enumerate() {
- let Some(field_item_type) =
- get_item_type(field.type_reflection(), field.type_id)
- else {
- continue;
- };
+ let Some(curr_variant_fields) = &curr_variant.fields else {
+ return;
+ };
+
+ let variant_fields = curr_variant_fields.fields().iter().enumerate().filter_map(
+ |(field_index, field)| {
+ let field_item_type = get_item_type(field.type_reflection(), field.type_id)?;
+
+ Some((field_index, field, field_item_type))
+ },
+ );
+
+ item_layout_table(frame, &prev_item_tags).build(|_| {
+ for (field_index, field, field_item_type) in variant_fields
+ .clone()
+ .filter(|(.., field_item_type)| !field_item_type.spans_multiple_rows())
+ {
+ frame.table_next_row();
+ frame.table_next_column();
let field_name: Cow<str> = match field.name {
Some(field_name) => field_name.into(),
None => field_index.to_string().into(),
};
- let Ok(field_item) = (match item {
- ItemRef::Mutable(item) => {
- (curr_variant.try_get_field_mut)(*item, field_index)
- .map(ItemRef::Mutable)
- }
- ItemRef::Immutable(item) => {
- (curr_variant.try_get_field)(*item, field_index)
- .map(ItemRef::Immutable)
- }
- }) else {
+ let Ok(field_item) = item.get_enum_variant_field(curr_variant, field_index)
+ else {
unreachable!();
};
+ create_item_title_widget(
+ frame,
+ &field_name,
+ &field_item_type,
+ Some(field.type_name()),
+ );
+
+ frame.table_next_column();
+
add_item_to_frame(
frame,
field_item,
@@ -1478,7 +1688,42 @@ fn create_enum_widgets(
&prev_item_tags,
);
}
- };
+ });
+
+ for (field_index, field, field_item_type) in variant_fields
+ .filter(|(.., field_item_type)| field_item_type.spans_multiple_rows())
+ {
+ let field_name: Cow<str> = match field.name {
+ Some(field_name) => field_name.into(),
+ None => field_index.to_string().into(),
+ };
+
+ let Ok(field_item) = item.get_enum_variant_field(curr_variant, field_index)
+ else {
+ unreachable!();
+ };
+
+ create_item_title_widget(
+ frame,
+ &field_name,
+ &field_item_type,
+ Some(field.type_name()),
+ );
+
+ add_item_to_frame(
+ frame,
+ field_item,
+ data_changed,
+ ItemInfo {
+ item_title: field_name.as_ref(),
+ item_tag: field_name.as_ref(),
+ item_type_name: Some(field.type_name()),
+ item_type: field_item_type,
+ item_is_read_only: item_is_read_only,
+ },
+ &prev_item_tags,
+ );
+ }
}
fn create_item_label(item_tag: &str, value_name: &str, prev_item_tags: &[&str])