diff --git a/Data/Scripts/801_UI controls/002_ControlsContainer.rb b/Data/Scripts/801_UI controls/002_ControlsContainer.rb index 734b2d136..ea730223d 100644 --- a/Data/Scripts/801_UI controls/002_ControlsContainer.rb +++ b/Data/Scripts/801_UI controls/002_ControlsContainer.rb @@ -77,6 +77,12 @@ class UIControls::ControlsContainer add_control(id, UIControls::Label.new(*control_size(has_label), @viewport, label), has_label) end + def add_header_label(id, label) + ctrl = UIControls::Label.new(*control_size, @viewport, label) + ctrl.header = true + add_control(id, ctrl) + end + def add_checkbox(id, value, has_label = false) add_control(id, UIControls::Checkbox.new(*control_size(has_label), @viewport, value), has_label) end diff --git a/Data/Scripts/801_UI controls/Control elements/001_BaseControl.rb b/Data/Scripts/801_UI controls/Control elements/001_BaseControl.rb index 9a4e49736..e70b0f747 100644 --- a/Data/Scripts/801_UI controls/Control elements/001_BaseControl.rb +++ b/Data/Scripts/801_UI controls/Control elements/001_BaseControl.rb @@ -46,6 +46,16 @@ class UIControls::BaseControl < BitmapSprite @interactions = {} end + def mouse_in_control? + return false if !@interactions || @interactions.empty? + mouse_x, mouse_y = mouse_pos + return false if !mouse_x || !mouse_y + @interactions.each_pair do |area, rect| + return true if rect.contains?(mouse_x, mouse_y) + end + return false + end + #----------------------------------------------------------------------------- def invalid? diff --git a/Data/Scripts/801_UI controls/Control elements/002_Label.rb b/Data/Scripts/801_UI controls/Control elements/002_Label.rb index d306ec532..2dd898ab9 100644 --- a/Data/Scripts/801_UI controls/Control elements/002_Label.rb +++ b/Data/Scripts/801_UI controls/Control elements/002_Label.rb @@ -10,6 +10,7 @@ class UIControls::Label < UIControls::BaseControl def initialize(width, height, viewport, label) super(width, height, viewport) @label = label + @header = false end def label=(value) @@ -17,8 +18,19 @@ class UIControls::Label < UIControls::BaseControl refresh end + def header=(val) + @header = val + refresh + end + def refresh super - draw_text(self.bitmap, 4, TEXT_OFFSET_Y, @label) + if @header + draw_text_centered(self.bitmap, 0, TEXT_OFFSET_Y, width, @label) + text_size = self.bitmap.text_size(@label) + self.bitmap.fill_rect((width - text_size.width) / 2, TEXT_OFFSET_Y + text_size.height, text_size.width, 1, TEXT_COLOR) + else + draw_text(self.bitmap, 4, TEXT_OFFSET_Y, @label) + end end end diff --git a/Data/Scripts/801_UI controls/Control elements/004_TextBox.rb b/Data/Scripts/801_UI controls/Control elements/004_TextBox.rb index da5dd9539..72cb56e51 100644 --- a/Data/Scripts/801_UI controls/Control elements/004_TextBox.rb +++ b/Data/Scripts/801_UI controls/Control elements/004_TextBox.rb @@ -4,6 +4,8 @@ # decide which characters are selected. Maybe? Note that this method # is only triggered upon the initial mouse press, and isn't repeated # while it's still held down. +# TODO: Add a blacklist array. Can't type in any values in this array. Disable +# this control if @value is in this array. #=============================================================================== class UIControls::TextBox < UIControls::BaseControl TEXT_BOX_X = 2 diff --git a/Data/Scripts/801_UI controls/Control elements/007_Button.rb b/Data/Scripts/801_UI controls/Control elements/007_Button.rb index c6882ac0c..19bfa66de 100644 --- a/Data/Scripts/801_UI controls/Control elements/007_Button.rb +++ b/Data/Scripts/801_UI controls/Control elements/007_Button.rb @@ -66,7 +66,7 @@ class UIControls::Button < UIControls::BaseControl # Change this control's value if @captured_area == :button mouse_x, mouse_y = mouse_pos - if mouse_x && mouse_y && @interactions[@captured_area].contains?(mouse_x, mouse_y) + if mouse_x && mouse_y && @interactions[@captured_area].contains?(mouse_x, mouse_y) set_changed end end diff --git a/Data/Scripts/801_UI controls/Control elements/008_List.rb b/Data/Scripts/801_UI controls/Control elements/008_List.rb index fd2529cbe..beca0fa3d 100644 --- a/Data/Scripts/801_UI controls/Control elements/008_List.rb +++ b/Data/Scripts/801_UI controls/Control elements/008_List.rb @@ -43,6 +43,11 @@ class UIControls::List < UIControls::BaseControl @scrollbar.y = new_val + LIST_Y end + def z=(new_val) + super(new_val) + @scrollbar.z = new_val + 1 + end + # Each value in @values is an array: [id, text]. def values=(new_vals) @values = new_vals @@ -77,7 +82,18 @@ class UIControls::List < UIControls::BaseControl # Returns the ID of the selected row. def value return nil if @selected < 0 - return @values[@selected][0] + if @values.is_a?(Array) + return (@values[@selected].is_a?(Array)) ? @values[@selected][0] : @selected + elsif @values.is_a?(Hash) + return @values.keys[@selected] + end + return nil + end + + def mouse_in_control? + return true if super + return true if @scrollbar.mouse_in_control? + return false end def set_interactive_rects @@ -202,6 +218,17 @@ class UIControls::List < UIControls::BaseControl # Set the selected row to the row the mouse is over, if clicked on if @captured_area @selected = @hover_area if @hover_area.is_a?(Integer) + elsif @hover_area + wheel_v = Input.scroll_v + if wheel_v > 0 # Scroll up + @scrollbar.slider_top -= UIControls::Scrollbar::SCROLL_DISTANCE + elsif wheel_v < 0 # Scroll down + @scrollbar.slider_top += UIControls::Scrollbar::SCROLL_DISTANCE + end + if wheel_v != 0 + self.top_row = (@scrollbar.position.to_f / ROW_HEIGHT).round + update_hover_highlight + end end end end diff --git a/Data/Scripts/801_UI controls/Control elements/009_DropdownList.rb b/Data/Scripts/801_UI controls/Control elements/009_DropdownList.rb index f3c12db67..a1f2331a4 100644 --- a/Data/Scripts/801_UI controls/Control elements/009_DropdownList.rb +++ b/Data/Scripts/801_UI controls/Control elements/009_DropdownList.rb @@ -1,9 +1,147 @@ #=============================================================================== -# TODO +# #=============================================================================== class UIControls::DropdownList < UIControls::BaseControl + TEXT_BOX_X = 2 + TEXT_BOX_WIDTH = 172 + TEXT_BOX_HEIGHT = 24 + TEXT_BOX_PADDING = 4 # Gap between sides of text box and text + TEXT_OFFSET_Y = 5 + MAX_LIST_ROWS = 8 + def initialize(width, height, viewport, options, value) # NOTE: options is a hash: keys are symbols, values are display names. super(width, height, viewport) + @options = options + @value = value + @toggling_dropdown_list = false + end + + def dispose + remove_dropdown_menu + super + end + + def value=(new_value) + return if @value == new_value + @value = new_value + invalidate + end + + def set_interactive_rects + @button_rect = Rect.new(TEXT_BOX_X, (height - TEXT_BOX_HEIGHT) / 2, + [TEXT_BOX_WIDTH, width].min, TEXT_BOX_HEIGHT) + @interactions = { + :button => @button_rect + } + end + + #----------------------------------------------------------------------------- + + def busy? + return true if @dropdown_menu || @toggling_dropdown_list + return super + end + + #----------------------------------------------------------------------------- + + def make_dropdown_menu + menu_height = UIControls::List::ROW_HEIGHT * [@options.length, MAX_LIST_ROWS].min + # Draw menu's background + @dropdown_menu_bg = BitmapSprite.new(@button_rect.width, menu_height + 4, self.viewport) + @dropdown_menu_bg.x = self.x + @button_rect.x + @dropdown_menu_bg.y = self.y + @button_rect.y + @button_rect.height + @dropdown_menu_bg.z = self.z + 1 + @dropdown_menu_bg.bitmap.outline_rect(0, 0, @dropdown_menu_bg.width, @dropdown_menu_bg.height, Color.black) + @dropdown_menu_bg.bitmap.fill_rect(1, 1, @dropdown_menu_bg.width - 2, @dropdown_menu_bg.height - 2, Color.white) + # Create menu + @dropdown_menu = UIControls::List.new(@button_rect.width - 4, menu_height, self.viewport, @options) + @dropdown_menu.x = @dropdown_menu_bg.x + 2 + @dropdown_menu.y = @dropdown_menu_bg.y + 2 + @dropdown_menu.z = self.z + 2 + @dropdown_menu.set_interactive_rects + @dropdown_menu.repaint + end + + def remove_dropdown_menu + @dropdown_menu_bg&.dispose + @dropdown_menu_bg = nil + @dropdown_menu&.dispose + @dropdown_menu = nil + @captured_area = nil + end + + #----------------------------------------------------------------------------- + + def draw_area_highlight + return if @captured_area == :button + super + end + + def refresh + @dropdown_menu&.refresh + super + # Draw button outline + self.bitmap.outline_rect(@button_rect.x, @button_rect.y, + @button_rect.width, @button_rect.height, + Color.black) + # Draw value + draw_text(self.bitmap, @button_rect.x + TEXT_BOX_PADDING, TEXT_OFFSET_Y, @options[@value] || "???") + # Draw down arrow + arrow_area_x = @button_rect.x + @button_rect.width - @button_rect.height + 1 + arrow_area_width = @button_rect.height - 2 + self.bitmap.fill_rect(arrow_area_x, @button_rect.y + 1, arrow_area_width, arrow_area_width, + (@hover_area && @captured_area != :button) ? HOVER_COLOR : Color.white) + 6.times do |i| + self.bitmap.fill_rect(arrow_area_x + (arrow_area_width / 2) - 5 + i, + @button_rect.y + (arrow_area_width / 2) - 1 + i, + 11 - (2 * i), 1, Color.black) + end + end + + #----------------------------------------------------------------------------- + + def on_mouse_press + if @dropdown_menu + if !@dropdown_menu.mouse_in_control? + remove_dropdown_menu + @toggling_dropdown_list = true + end + else + @captured_area = nil + super + if @captured_area == :button + make_dropdown_menu + @toggling_dropdown_list = true + end + end + end + + def on_mouse_release + return if !@captured_area && !@dropdown_menu && !@toggling_dropdown_list + if @toggling_dropdown_list + @toggling_dropdown_list = false + return + end + if @dropdown_menu + if @dropdown_menu.changed? + new_val = @dropdown_menu.value + if new_val && new_val != @value + @value = new_val + set_changed + end + remove_dropdown_menu + super # Make this control not busy again + elsif !@dropdown_menu.mouse_in_control? + remove_dropdown_menu + super # Make this control not busy again + end + end + end + + def update + @dropdown_menu&.update + @dropdown_menu&.repaint + super end end diff --git a/Data/Scripts/902_Anim GameData/001_Animation.rb b/Data/Scripts/902_Anim GameData/001_Animation.rb index 52399a334..51c7ee917 100644 --- a/Data/Scripts/902_Anim GameData/001_Animation.rb +++ b/Data/Scripts/902_Anim GameData/001_Animation.rb @@ -34,6 +34,8 @@ module GameData # TODO: DamageFrame (keyframe at which the battle continues, i.e. damage # animations start playing). "Flags" => [:flags, "*s"], + # TODO: If this is changed to be more than just a string, edit the + # compiler's current_particle definition accordingly. "Particle" => [:particles, "s"] # Is a subheader line like } # For individual particles. Any property whose schema begins with "^" can diff --git a/Data/Scripts/903_Anim Compiler/001_Anim compiler.rb b/Data/Scripts/903_Anim Compiler/001_Anim compiler.rb index e572de783..7f3e8ea8e 100644 --- a/Data/Scripts/903_Anim Compiler/001_Anim compiler.rb +++ b/Data/Scripts/903_Anim Compiler/001_Anim compiler.rb @@ -41,8 +41,6 @@ module Compiler # New subsection [particle_name] value = get_csv_record($~[1], schema["Particle"]) current_particle = { - # TODO: If "Particle" is changed to be more than just a single - # string, add more properties accordingly. :name => value } data_hash[schema["Particle"][0]].push(current_particle) diff --git a/Data/Scripts/904_Anim Editor/001_AnimationEditor.rb b/Data/Scripts/904_Anim Editor/001_AnimationEditor.rb index 505f8dff3..84d6eb717 100644 --- a/Data/Scripts/904_Anim Editor/001_AnimationEditor.rb +++ b/Data/Scripts/904_Anim Editor/001_AnimationEditor.rb @@ -118,6 +118,7 @@ class AnimationEditor end def set_commands_pane_contents + @commands_pane.add_header_label(:header, _INTL("Edit particle at keyframe")) # :frame (related to graphic) - If the graphic is user's sprite/target's # sprite, make this instead a choice of front/back/same as the main sprite/ # opposite of the main sprite. Probably need two controls in the same space @@ -149,6 +150,7 @@ class AnimationEditor end def set_se_pane_contents + @se_pane.add_header_label(:header, _INTL("Edit sound effects at keyframe")) # TODO: A list containing all SE files that play this keyframe. Lists SE, # user cry and target cry. @se_pane.add_button(:add, _INTL("Add")) @@ -157,6 +159,7 @@ class AnimationEditor end def set_particle_pane_contents + @particle_pane.add_header_label(:header, _INTL("Edit particle properties")) # TODO: Name should blacklist certain names ("User", "Target", "SE") and # should be disabled if the value is one of those. @particle_pane.add_labelled_text_box(:name, _INTL("Name"), _INTL("Untitled")) @@ -178,7 +181,7 @@ class AnimationEditor end def set_keyframe_pane_contents - @keyframe_pane.add_label(:temp, _INTL("Keyframe pane")) + @keyframe_pane.add_header_label(:header, _INTL("Edit keyframe")) # TODO: Various command-shifting options. end @@ -267,7 +270,7 @@ class AnimationEditor next if !new_vals.include?(ctrl[0]) ctrl[1].value = new_vals[ctrl[0]] if ctrl[1].respond_to?("value=") end - # TODO: Disable the name and graphic controls for "User"/"Target". + # TODO: Disable the name, graphic and focus controls for "User"/"Target". end end diff --git a/Data/Scripts/904_Anim Editor/010_AnimationSelector.rb b/Data/Scripts/904_Anim Editor/010_AnimationSelector.rb index f4c0e86b3..7857dcfa4 100644 --- a/Data/Scripts/904_Anim Editor/010_AnimationSelector.rb +++ b/Data/Scripts/904_Anim Editor/010_AnimationSelector.rb @@ -131,12 +131,12 @@ class AnimationEditor::AnimationSelector Input.update update # Open editor with animation - @load_animation_id = 2 # TODO: For quickstart testing purposes. +# @load_animation_id = 2 # TODO: For quickstart testing purposes. if @load_animation_id screen = AnimationEditor.new(@load_animation_id, GameData::Animation.get(@load_animation_id).clone_as_hash) screen.run @load_animation_id = nil - break # TODO: For quickstart testing purposes. +# break # TODO: For quickstart testing purposes. # Refresh list of animations, in case the edited one changed its type, # move, version or name generate_list diff --git a/Data/Scripts/904_Anim Editor/Anim Editor elements/003_ParticleList.rb b/Data/Scripts/904_Anim Editor/Anim Editor elements/003_ParticleList.rb index c33b1baf8..e52791323 100644 --- a/Data/Scripts/904_Anim Editor/Anim Editor elements/003_ParticleList.rb +++ b/Data/Scripts/904_Anim Editor/Anim Editor elements/003_ParticleList.rb @@ -127,6 +127,7 @@ class AnimationEditor::ParticleList < UIControls::BaseControl end def particle_index + return -1 if @row_index < 0 ret = @particle_list[@row_index] return (ret.is_a?(Array)) ? ret[0] : ret end