diff --git a/example/Main.gd b/example/Main.gd index 0530169..43d3128 100644 --- a/example/Main.gd +++ b/example/Main.gd @@ -15,6 +15,7 @@ extends Control @onready var _piano_view: Control = %PianoView @onready var _tunes_view: Control = %TunesView +@onready var _volume_slider: HSlider = %VolumeSlider @onready var _kenney_label := %KenneyLabel var _current_view: Controller.AppView = Controller.AppView.WELCOME_VIEW @@ -23,9 +24,11 @@ var _current_view: Controller.AppView = Controller.AppView.WELCOME_VIEW func _ready() -> void: get_window().min_size = Vector2(640, 360) _update_active_view(Controller.AppView.WELCOME_VIEW, true) + Controller.music_player.change_volume(int(_volume_slider.value)) _piano_view_button.pressed.connect(Controller.change_app_view.bind(Controller.AppView.PIANO_VIEW)) _tunes_view_button.pressed.connect(Controller.change_app_view.bind(Controller.AppView.TUNES_VIEW)) + _volume_slider.value_changed.connect(Controller.music_player.change_volume) _kenney_label.meta_clicked.connect(_handle_meta_clicked) Controller.app_view_changed.connect(_update_active_view.bind(false)) diff --git a/example/Main.tscn b/example/Main.tscn index f00ea14..164905b 100644 --- a/example/Main.tscn +++ b/example/Main.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=9 format=3 uid="uid://btlcavlirkxet"] +[gd_scene load_steps=10 format=3 uid="uid://btlcavlirkxet"] [ext_resource type="Script" path="res://Main.gd" id="1_8sk4m"] [ext_resource type="PackedScene" uid="uid://dp02gpc8hg7fw" path="res://gui/components/FlatButton.tscn" id="2_7ss6h"] @@ -8,6 +8,7 @@ [ext_resource type="Texture2D" uid="uid://5pxu35ux4hkn" path="res://icons/piano.png" id="3_cw50e"] [ext_resource type="PackedScene" uid="uid://cwl0nh1ofpudo" path="res://gui/TunesView.tscn" id="3_k0wkn"] [ext_resource type="Texture2D" uid="uid://ceui0jym6bois" path="res://icons/note.png" id="4_s2pjj"] +[ext_resource type="Texture2D" uid="uid://cunfeny5nkxdn" path="res://icons/volume.png" id="9_te82j"] [node name="Main" type="Control"] layout_mode = 3 @@ -28,7 +29,7 @@ grow_vertical = 2 theme_override_constants/margin_left = 12 theme_override_constants/margin_top = 110 theme_override_constants/margin_right = 12 -theme_override_constants/margin_bottom = 36 +theme_override_constants/margin_bottom = 48 [node name="WelcomeView" parent="Views" instance=ExtResource("2_d1bku")] unique_name_in_owner = true @@ -62,12 +63,12 @@ text = "GDSiON" [node name="ViewSelectorFiller" type="Control" parent="TopBar"] unique_name_in_owner = true -visible = false layout_mode = 2 size_flags_horizontal = 3 [node name="ViewSelector" type="HBoxContainer" parent="TopBar"] unique_name_in_owner = true +visible = false layout_mode = 2 size_flags_horizontal = 3 alignment = 1 @@ -94,6 +95,31 @@ texture = ExtResource("3_7khnb") expand_mode = 1 stretch_mode = 5 +[node name="Volume" type="HBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_left = 10.0 +offset_top = -40.0 +offset_right = 246.0 +offset_bottom = -8.0 +grow_vertical = 0 + +[node name="VolumeIcon" type="TextureRect" parent="Volume"] +custom_minimum_size = Vector2(32, 32) +layout_mode = 2 +texture = ExtResource("9_te82j") +expand_mode = 1 +stretch_mode = 5 + +[node name="VolumeSlider" type="HSlider" parent="Volume"] +unique_name_in_owner = true +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +size_flags_vertical = 1 +value = 75.0 + [node name="KenneyLabel" type="RichTextLabel" parent="."] unique_name_in_owner = true layout_mode = 1 @@ -104,7 +130,7 @@ anchor_right = 1.0 anchor_bottom = 1.0 offset_left = -249.0 offset_top = -27.0 -offset_right = -2.0 +offset_right = -7.0 offset_bottom = -7.0 grow_horizontal = 0 grow_vertical = 0 diff --git a/example/globals/MusicPlayer.gd b/example/globals/MusicPlayer.gd index 99f05a5..edf0659 100644 --- a/example/globals/MusicPlayer.gd +++ b/example/globals/MusicPlayer.gd @@ -169,6 +169,12 @@ func change_filter_power(value: int) -> void: filter_changed.emit() +func change_volume(value: int) -> void: + var volume := clampi(value, 0, 100) + + _driver.volume = (volume / 100.0) + + # Output and streaming control. func stop() -> void: diff --git a/example/gui/TunesView.gd b/example/gui/TunesView.gd index 09219e0..ee1d4e5 100644 --- a/example/gui/TunesView.gd +++ b/example/gui/TunesView.gd @@ -32,6 +32,7 @@ func _ready() -> void: func _set_view_active() -> void: if not visible: _tune_status.text = "" + _tune_status.tooltip_text = "" return @@ -48,11 +49,13 @@ func _play_selected() -> void: _tune_status.text = "Now Playing: %s" % [ selected_tune.title ] else: _tune_status.text = "Now Playing: %s by %s" % [ selected_tune.title, selected_tune.author ] + _tune_status.tooltip_text = _tune_status.text func _stop_playback() -> void: Controller.music_player.stop() _tune_status.text = "" + _tune_status.tooltip_text = "" # Tune management. diff --git a/example/gui/TunesView.tscn b/example/gui/TunesView.tscn index db060fc..1ca9600 100644 --- a/example/gui/TunesView.tscn +++ b/example/gui/TunesView.tscn @@ -31,8 +31,8 @@ theme_override_constants/separation = 16 [node name="Controls" type="HBoxContainer" parent="Layout/Playback"] layout_mode = 2 -size_flags_horizontal = 8 theme_override_constants/separation = 12 +alignment = 2 [node name="PlayButton" parent="Layout/Playback/Controls" instance=ExtResource("2_c6y1p")] unique_name_in_owner = true @@ -59,7 +59,9 @@ size_flags_vertical = 3 [node name="TuneStatus" type="Label" parent="Layout/Playback"] unique_name_in_owner = true layout_mode = 2 +mouse_filter = 1 theme_override_font_sizes/font_size = 24 +text_overrun_behavior = 1 [node name="HTTPRequest" type="HTTPRequest" parent="."] unique_name_in_owner = true diff --git a/example/icons/volume.png b/example/icons/volume.png new file mode 100644 index 0000000..3250a72 Binary files /dev/null and b/example/icons/volume.png differ diff --git a/example/icons/volume.png.import b/example/icons/volume.png.import new file mode 100644 index 0000000..5c0c484 --- /dev/null +++ b/example/icons/volume.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cunfeny5nkxdn" +path="res://.godot/imported/volume.png-4aaf602240d33d2298951d35d959a50c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icons/volume.png" +dest_files=["res://.godot/imported/volume.png-4aaf602240d33d2298951d35d959a50c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/example/project_theme.tres b/example/project_theme.tres index a310b9b..d5de3c6 100644 --- a/example/project_theme.tres +++ b/example/project_theme.tres @@ -1,4 +1,4 @@ -[gd_resource type="Theme" load_steps=7 format=3 uid="uid://bm402itx0nq0t"] +[gd_resource type="Theme" load_steps=8 format=3 uid="uid://bm402itx0nq0t"] [ext_resource type="FontFile" uid="uid://c4b0xfmxt4on2" path="res://fonts/NotoSans-SemiBold.ttf" id="1_2oopj"] [ext_resource type="FontFile" uid="uid://y70lqerdtol1" path="res://fonts/Kenney Future Narrow.ttf" id="1_8d45h"] @@ -27,6 +27,22 @@ corner_radius_top_right = 4 corner_radius_bottom_right = 4 corner_radius_bottom_left = 4 +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_wqqdn"] +content_margin_left = 12.0 +content_margin_top = 8.0 +content_margin_right = 12.0 +content_margin_bottom = 8.0 +bg_color = Color(0.123694, 0.138055, 0.166794, 1) +border_width_left = 1 +border_width_top = 1 +border_width_right = 1 +border_width_bottom = 1 +border_color = Color(0.0343809, 0.0400633, 0.0557284, 1) +corner_radius_top_left = 2 +corner_radius_top_right = 2 +corner_radius_bottom_right = 2 +corner_radius_bottom_left = 2 + [resource] default_font = ExtResource("1_8d45h") default_font_size = 30 @@ -50,5 +66,6 @@ ItemList/styles/panel = SubResource("StyleBoxFlat_h73hr") ItemList/styles/selected = SubResource("StyleBoxFlat_6uu3r") TooltipLabel/font_sizes/font_size = 20 TooltipLabel/fonts/font = ExtResource("1_2oopj") +TooltipPanel/styles/panel = SubResource("StyleBoxFlat_wqqdn") WelcomeLabel/base_type = &"Label" WelcomeLabel/fonts/font = ExtResource("1_2oopj") diff --git a/src/sequencer/simml_sequencer.cpp b/src/sequencer/simml_sequencer.cpp index 2687339..b34face 100644 --- a/src/sequencer/simml_sequencer.cpp +++ b/src/sequencer/simml_sequencer.cpp @@ -472,23 +472,15 @@ void SiMMLSequencer::process() { // Parser. -String SiMMLSequencer::_expand_macro(String p_macro, bool p_nested) { +String SiMMLSequencer::_expand_macro(String p_macro, uint32_t p_macro_flags) { // Note that the original code has a broken circular call check. It never updates the flag // storage, and the check is written incorrectly too. We attempt to fix it here based on the // intention of the original code rather than the actual implementation. - static uint32_t flag_macro_expanded = 0; - if (p_macro.is_empty()) { return ""; } - if (!p_nested) { - // This is a top-level call, so we reset the flag storage. - // We expect only one chain of _expand_macro() calls to be executed at the same time. - flag_macro_expanded = 0; - } - String expanded_macro = p_macro; Ref re_macro = RegEx::create_from_string("([A-Z])(\\(([\\-\\d]+)\\))?"); @@ -496,27 +488,33 @@ String SiMMLSequencer::_expand_macro(String p_macro, bool p_nested) { // Iterate backwards so we can do in-place replacements without disturbing indices. for (int i = matches.size() - 1; i >= 0; i--) { Ref res = matches[i]; - int index = res->get_string(1).unicode_at(0) - 'A'; // Check for circular calls. + + // The set of flags is unique to each chain of nested calls, which is how we detect circular + // calls without getting false positives on sibling macros (e.g. "AAA"). + uint32_t expanded_macro_flags = p_macro_flags; + int flag = 1 << index; - ERR_FAIL_COND_V_MSG(flag_macro_expanded & flag, p_macro, vformat("SiMMLSequencer: Failed to expand a macro due to a circular reference, '%s'.", res->get_string())); - flag_macro_expanded |= flag; + ERR_FAIL_COND_V_MSG(expanded_macro_flags & flag, p_macro, vformat("SiMMLSequencer: Failed to expand a macro due to a circular reference, '%s'.", res->get_string())); + expanded_macro_flags |= flag; + + // Find the replacement string. String replacement; if (!_macro_strings[index].is_empty()) { const String macro_string = _macro_strings[index]; + replacement = (_macro_expand_dynamic ? _expand_macro(macro_string, expanded_macro_flags) : macro_string); + // Apply a note shift to the expanded macro. if (!res->get_string(2).is_empty()) { - int t = 0; + int note_shift = 0; if (!res->get_string(3).is_empty()) { - t = res->get_string(3).to_int(); + note_shift = res->get_string(3).to_int(); } - replacement = "!@ns" + itos(t) + (_macro_expand_dynamic ? _expand_macro(macro_string, true) : macro_string) + "!@ns" + itos(-t); - } else { - replacement = (_macro_expand_dynamic ? _expand_macro(macro_string, true) : macro_string); + replacement = "!@ns" + itos(note_shift) + replacement + "!@ns" + itos(-note_shift); } } diff --git a/src/sequencer/simml_sequencer.h b/src/sequencer/simml_sequencer.h index e0c83f0..b1e3cbd 100644 --- a/src/sequencer/simml_sequencer.h +++ b/src/sequencer/simml_sequencer.h @@ -67,7 +67,7 @@ class SiMMLSequencer : public MMLSequencer { Vector _macro_strings; bool _macro_expand_dynamic = false; - String _expand_macro(String p_macro, bool p_nested = false); + String _expand_macro(String p_macro, uint32_t p_macro_flags = 0); int _internal_table_index = 0;