From e9e2bccc42dd9ca6261d23bebe20d5048bba8507 Mon Sep 17 00:00:00 2001 From: QueenOfSquiggles <8940604+QueenOfSquiggles@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:37:06 -0500 Subject: [PATCH] INDEV - working on editor-side systems pt3 --- .../sqore_options_menu.tscn | 166 ++++++++++++------ src/scene/gui/collapsable_container.rs | 14 +- src/scene/gui/labelled_hslider.rs | 91 ++++++++-- 3 files changed, 201 insertions(+), 70 deletions(-) diff --git a/scenes/prefabs/sqore_options_menu/sqore_options_menu.tscn b/scenes/prefabs/sqore_options_menu/sqore_options_menu.tscn index 7773bcc..8e6fa3a 100644 --- a/scenes/prefabs/sqore_options_menu/sqore_options_menu.tscn +++ b/scenes/prefabs/sqore_options_menu/sqore_options_menu.tscn @@ -16,85 +16,137 @@ heading_text = "Gameplay" layout_mode = 2 script = ExtResource("2_n73id") -[node name="HFlowContainer" type="HFlowContainer" parent="Gameplay"] -visible = false +[node name="Graphics" type="CollapsingVBoxContainer" parent="."] +heading_text = "Graphics" layout_mode = 2 -[node name="CheckSSAO" type="CheckButton" parent="Gameplay/HFlowContainer"] +[node name="Label" type="Label" parent="Graphics"] layout_mode = 2 -text = "Use SSAO" +text = "Graphics Details" +horizontal_alignment = 1 -[node name="CheckBloom" type="CheckButton" parent="Gameplay/HFlowContainer"] +[node name="HFlowContainer" type="HFlowContainer" parent="Graphics"] layout_mode = 2 +alignment = 1 -[node name="CheckSDFGI" type="CheckButton" parent="Gameplay/HFlowContainer"] +[node name="CheckSSAO" type="CheckButton" parent="Graphics/HFlowContainer"] layout_mode = 2 +text = "Use Ambient Occlusion (SSAO)" -[node name="CheckSSIL" type="CheckButton" parent="Gameplay/HFlowContainer"] +[node name="CheckBloom" type="CheckButton" parent="Graphics/HFlowContainer"] layout_mode = 2 +text = "Use Bloom" -[node name="CheckSSR" type="CheckButton" parent="Gameplay/HFlowContainer"] +[node name="CheckSDFGI" type="CheckButton" parent="Graphics/HFlowContainer"] layout_mode = 2 +text = "Use Global Illumination (SDFGI)" -[node name="Graphics" type="CollapsingVBoxContainer" parent="."] -heading_text = "Graphics" +[node name="CheckSSIL" type="CheckButton" parent="Graphics/HFlowContainer"] layout_mode = 2 +text = "Use Indirect Lighting (SSIL)" -[node name="Controls" type="CollapsingVBoxContainer" parent="."] -heading_text = "Controls" +[node name="CheckSSR" type="CheckButton" parent="Graphics/HFlowContainer"] layout_mode = 2 +text = "Use Reflections (SSR)" -[node name="Audio" type="CollapsingVBoxContainer" parent="."] -heading_text = "Audio" +[node name="Label2" type="Label" parent="Graphics"] layout_mode = 2 +text = "Color Balancing" +horizontal_alignment = 1 -[node name="HSlider" type="HSlider" parent="."] -custom_minimum_size = Vector2(0, 64) +[node name="SliderValue" type="LabelledHSlider" parent="Graphics"] +text = "Value" +enable_reset = true +label_decimal_places = 1 +custom_minimum_size = Vector2(32, 64) +layout_mode = 2 +max_value = 1.0 +step = 0.1 +value = 1.0 + +[node name="SliderContrast" type="LabelledHSlider" parent="Graphics"] +text = "Contrast" +enable_reset = true +label_decimal_places = 1 +custom_minimum_size = Vector2(32, 64) +layout_mode = 2 +max_value = 1.0 +step = 0.1 +value = 1.0 + +[node name="SliderSaturation" type="LabelledHSlider" parent="Graphics"] +text = "Saturation" +enable_reset = true +label_decimal_places = 1 +custom_minimum_size = Vector2(32, 64) +layout_mode = 2 +max_value = 1.0 +step = 0.1 +value = 1.0 + +[node name="SliderExposure" type="LabelledHSlider" parent="Graphics"] +text = "Exposure" +enable_reset = true +label_decimal_places = 1 +custom_minimum_size = Vector2(32, 64) layout_mode = 2 +max_value = 8.0 +step = 0.1 +value = 1.0 -[node name="Title" type="Label" parent="HSlider"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -text = "asdasdasd" +[node name="Label3" type="Label" parent="Graphics"] +layout_mode = 2 +text = "Window" +horizontal_alignment = 1 -[node name="Min" type="Label" parent="HSlider"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -text = "0" -vertical_alignment = 2 +[node name="Windowing" type="HBoxContainer" parent="Graphics"] +layout_mode = 2 -[node name="Max" type="Label" parent="HSlider"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -text = "1" -horizontal_alignment = 2 -vertical_alignment = 2 +[node name="Label" type="Label" parent="Graphics/Windowing"] +layout_mode = 2 +text = "Windowing" -[node name="Current" type="Label" parent="HSlider"] -layout_mode = 1 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -text = "0.55556" -horizontal_alignment = 1 -vertical_alignment = 2 +[node name="OptionWindowing" type="OptionButton" parent="Graphics/Windowing"] +layout_mode = 2 +size_flags_horizontal = 3 +item_count = 5 +selected = 0 +allow_reselect = true +popup/item_0/text = "Windowed" +popup/item_0/id = 0 +popup/item_1/text = "Minimized" +popup/item_1/id = 1 +popup/item_2/text = "Maximized" +popup/item_2/id = 2 +popup/item_3/text = "Windowed Fullscreen" +popup/item_3/id = 3 +popup/item_4/text = "Exclusive Fullscreen" +popup/item_4/id = 4 + +[node name="Scaling" type="HBoxContainer" parent="Graphics"] +layout_mode = 2 + +[node name="Label" type="Label" parent="Graphics/Scaling"] +layout_mode = 2 +text = "Graphics Scaling" + +[node name="OptionScaling" type="OptionButton" parent="Graphics/Scaling"] +layout_mode = 2 +size_flags_horizontal = 3 +item_count = 3 +selected = 0 +allow_reselect = true +popup/item_0/text = "Standard" +popup/item_0/id = 0 +popup/item_1/text = "AMD FSR 1.0" +popup/item_1/id = 1 +popup/item_2/text = "AMD FSR 2.2" +popup/item_2/id = 2 -[node name="LabelledHSlider" type="LabelledHSlider" parent="."] -text = "This is a cool slider" -custom_minimum_size = Vector2(0, 64) +[node name="Controls" type="CollapsingVBoxContainer" parent="."] +heading_text = "Controls" +layout_mode = 2 + +[node name="Audio" type="CollapsingVBoxContainer" parent="."] +heading_text = "Audio" layout_mode = 2 -max_value = 89.46 diff --git a/src/scene/gui/collapsable_container.rs b/src/scene/gui/collapsable_container.rs index 3e2f4be..08c8d3e 100644 --- a/src/scene/gui/collapsable_container.rs +++ b/src/scene/gui/collapsable_container.rs @@ -1,5 +1,6 @@ use godot::engine::Button; use godot::engine::Control; +use godot::engine::Engine; use godot::engine::IVBoxContainer; use godot::engine::VBoxContainer; use godot::prelude::*; @@ -45,6 +46,13 @@ impl IVBoxContainer for CollapsingVBoxContainer { impl CollapsingVBoxContainer { #[func] fn on_heading_toggle(&mut self, is_toggled: bool) { + let toggle_value = if Engine::singleton().is_editor_hint() { + // in the editor, always show collapseable items + true + } else { + is_toggled + }; + let mut children: Vec> = self.base_mut().get_children().iter_shared().collect(); if let Some(btn) = &self.heading { let btn_base = &btn.clone().upcast::(); @@ -52,13 +60,13 @@ impl CollapsingVBoxContainer { } for child in children { if let Ok(control) = &mut child.clone().try_cast::() { - control.set_visible(is_toggled); + control.set_visible(toggle_value); } if let Ok(node2d) = &mut child.clone().try_cast::() { - node2d.set_visible(is_toggled); + node2d.set_visible(toggle_value); } if let Ok(node3d) = &mut child.clone().try_cast::() { - node3d.set_visible(is_toggled); + node3d.set_visible(toggle_value); } } } diff --git a/src/scene/gui/labelled_hslider.rs b/src/scene/gui/labelled_hslider.rs index 03bbaf8..db3198a 100644 --- a/src/scene/gui/labelled_hslider.rs +++ b/src/scene/gui/labelled_hslider.rs @@ -2,7 +2,7 @@ use godot::{ engine::{ control::LayoutPreset, global::{HorizontalAlignment, VerticalAlignment}, - HSlider, IHSlider, Label, + HSlider, IHSlider, Label, ResourceLoader, Texture2D, TextureButton, }, obj::WithBaseField, prelude::*, @@ -15,6 +15,18 @@ pub struct LabelledHSlider { #[var(get, set=set_text)] text: GString, + #[export] + #[var(get, set=set_reset_enabled)] + enable_reset: bool, + + #[export(range=(0.0, 10.0))] + #[var(get, set=set_label_decimal_places)] + label_decimal_places: u32, + + #[var] + reset_value: f64, + + button_reset: Option>, label_title: Option>, label_min: Option>, label_max: Option>, @@ -25,16 +37,30 @@ pub struct LabelledHSlider { #[godot_api] impl IHSlider for LabelledHSlider { - fn enter_tree(&mut self) { + fn ready(&mut self) { //pass let mut l_title = Label::new_alloc(); let mut l_min = Label::new_alloc(); let mut l_max = Label::new_alloc(); let mut l_cur = Label::new_alloc(); + let mut b_reset = TextureButton::new_alloc(); + l_title.set_text(self.text.clone()); - l_min.set_text(Self::as_text(self.base().get_min())); - l_max.set_text(Self::as_text(self.base().get_max())); - l_cur.set_text(Self::as_text(self.base().get_value())); + l_min.set_text(self.as_text(self.base().get_min())); + l_max.set_text(self.as_text(self.base().get_max())); + l_cur.set_text(self.as_text(self.base().get_value())); + b_reset.set_tooltip_text("Reset".into()); + + if let Some(texture) = ResourceLoader::singleton() + .load("res://addons/sqore/assets/runtime/undo_FILL0_wght400_GRAD0_opsz24.svg".into()) + { + if let Ok(texture) = texture.try_cast::() { + b_reset.set_texture_normal(texture.clone()); + b_reset.set_texture_hover(texture.clone()); + b_reset.set_texture_pressed(texture); + b_reset.set_custom_minimum_size(Vector2 { x: 16.0, y: 16.0 }); + } + } let call_range = Callable::from_object_method(&self.to_gd(), "update_range"); let call_value = Callable::from_object_method(&self.to_gd(), "update_value"); @@ -42,6 +68,7 @@ impl IHSlider for LabelledHSlider { self.base_mut().add_child(l_min.clone().upcast()); self.base_mut().add_child(l_max.clone().upcast()); self.base_mut().add_child(l_cur.clone().upcast()); + self.base_mut().add_child(b_reset.clone().upcast()); self.base_mut() .connect(StringName::from("changed"), call_range); self.base_mut() @@ -62,6 +89,19 @@ impl IHSlider for LabelledHSlider { l_cur.set_anchors_and_offsets_preset(LayoutPreset::FULL_RECT); l_cur.set_vertical_alignment(VerticalAlignment::BOTTOM); l_cur.set_horizontal_alignment(HorizontalAlignment::CENTER); + + b_reset.set_anchors_and_offsets_preset(LayoutPreset::TOP_RIGHT); + b_reset.connect( + StringName::from("pressed"), + Callable::from_object_method(&self.to_gd(), "reset"), + ); + self.reset_value = self.base().get_value(); + self.label_current = Some(l_cur); + self.label_max = Some(l_max); + self.label_min = Some(l_min); + self.button_reset = Some(b_reset); + + self.set_reset_enabled(self.enable_reset); } } @@ -74,27 +114,58 @@ impl LabelledHSlider { label.set_text(n_text); } } + + #[func] + fn set_reset_enabled(&mut self, n_enabled: bool) { + self.enable_reset = n_enabled; + if let Some(btn) = &mut self.button_reset { + btn.set_disabled(!n_enabled); + btn.set_visible(n_enabled); + } + } + #[func] fn update_range(&mut self) { let min = self.base().get_min(); let max = self.base().get_max(); + let min_text = self.as_text(min); + let max_text = self.as_text(max); if let Some(l_min) = &mut self.label_min { - l_min.set_text(Self::as_text(min)); + l_min.set_text(min_text); } if let Some(l_max) = &mut self.label_max { - l_max.set_text(Self::as_text(max)); + l_max.set_text(max_text); } } #[func] fn update_value(&mut self, value: f64) { + let text = self.as_text(value); let Some(label) = &mut self.label_current else { return; }; - label.set_text(Self::as_text(value)); + label.set_text(text); + } + + #[func] + fn reset(&mut self) { + let nval = self.reset_value; + self.base_mut().set_value(nval); + } + + #[func] + fn set_label_decimal_places(&mut self, n_value: u32) { + self.label_decimal_places = n_value; + + // update labels + let val = self.base().get_value(); + self.update_range(); + self.update_value(val); } - fn as_text(num: f64) -> GString { - format!("{}", num).to_godot() + fn as_text(&self, num: f64) -> GString { + let target_decimal = self.label_decimal_places as usize; + // Rust is mega chad for letting me specify the precision using another variable instead of needing a hardcoded string + format!("{0:.1$}", num, target_decimal).to_godot() } }