diff --git a/lib/dialog.rb b/lib/dialog.rb index cc74ad0..875d8e2 100644 --- a/lib/dialog.rb +++ b/lib/dialog.rb @@ -57,6 +57,38 @@ module TAC def try_commit end + def focus_next_element + elements = [] + + _deep_dive_interactive_elements(@dialog_content, elements) + + element_index = elements.find_index(self.focused) + + if element_index && elements.size.positive? + element = elements[element_index + 1] + element ||= elements.first + + if element + request_focus(element) + end + end + end + + def _deep_dive_interactive_elements(element, list) + element.children.each do |child| + if child.visible? && child.is_a?(CyberarmEngine::Element::EditLine) || + child.is_a?(CyberarmEngine::Element::EditBox) || + child.is_a?(CyberarmEngine::Element::CheckBox) || + child.is_a?(CyberarmEngine::Element::ToggleButton) || + child.is_a?(CyberarmEngine::Element::ListBox) + + list << child + elsif child.visible? && child.is_a?(CyberarmEngine::Element::Container) + _deep_dive_interactive_elements(child, list) + end + end + end + def draw @previous_state.draw Gosu.flush @@ -84,6 +116,8 @@ module TAC try_commit when Gosu::KB_ESCAPE close + when Gosu::KB_TAB + focus_next_element end end diff --git a/lib/dialogs/action_dialog.rb b/lib/dialogs/action_dialog.rb index 3290a3c..cbada40 100644 --- a/lib/dialogs/action_dialog.rb +++ b/lib/dialogs/action_dialog.rb @@ -7,7 +7,10 @@ module TAC label "Name", width: 1.0, text_align: :center @name_error = label "Error", color: TAC::Palette::TACNET_CONNECTION_ERROR @name_error.hide - @name = edit_line @options[:action] ? @options[:action].name : "", filter: method(:name_filter), width: 1.0 + @name = edit_line @options[:action] ? @options[:action].name : "", filter: method(:name_filter), width: 1.0, autofocus: true + @name.subscribe(:changed) do |sender, value| + valid? + end label "Comment", width: 1.0, text_align: :center @comment = edit_line @options[:action] ? @options[:action].comment : "", width: 1.0 diff --git a/lib/dialogs/name_prompt_dialog.rb b/lib/dialogs/name_prompt_dialog.rb index 3ebcdc7..4129134 100644 --- a/lib/dialogs/name_prompt_dialog.rb +++ b/lib/dialogs/name_prompt_dialog.rb @@ -8,7 +8,7 @@ module TAC label "Name", width: 1.0, text_align: :center @name_error = label "", color: TAC::Palette::TACNET_CONNECTION_ERROR @name_error.hide - @name = edit_line @options[:renaming] ? @options[:renaming].name : "", filter: method(:name_filter), width: 1.0 + @name = edit_line @options[:renaming] ? @options[:renaming].name : "", filter: method(:name_filter), width: 1.0, autofocus: true @name.subscribe(:changed) do |sender, value| valid? diff --git a/lib/dialogs/variable_dialog.rb b/lib/dialogs/variable_dialog.rb index 0a12d25..640def1 100644 --- a/lib/dialogs/variable_dialog.rb +++ b/lib/dialogs/variable_dialog.rb @@ -9,7 +9,10 @@ module TAC label "Name", width: 1.0, text_align: :center @name_error = label "Error", color: TAC::Palette::TACNET_CONNECTION_ERROR @name_error.hide - @name = edit_line @options[:variable] ? @options[:variable].name : "", filter: method(:name_filter), width: 1.0 + @name = edit_line @options[:variable] ? @options[:variable].name : "", filter: method(:name_filter), width: 1.0, autofocus: true + @name.subscribe(:changed) do |sender, value| + valid? + end label "Type", width: 1.0, text_align: :center @type_error = label "Error", color: TAC::Palette::TACNET_CONNECTION_ERROR @@ -24,6 +27,8 @@ module TAC @value.show @value_boolean.hide end + + valid? end @type ||= @var_type.value.to_sym @@ -35,6 +40,10 @@ module TAC @value = edit_line @options[:variable] ? @options[:variable].value : "", width: 1.0 @value_boolean = check_box "Boolean", checked: @options[:variable] ? @options[:variable].value == "true" : false + @value.subscribe(:changed) do |sender, value| + valid? + end + unless @options[:variable] && @options[:variable].type == :boolean @value_boolean.hide else diff --git a/lib/pages/simulator.rb b/lib/pages/simulator.rb index f5c0370..db5d74e 100644 --- a/lib/pages/simulator.rb +++ b/lib/pages/simulator.rb @@ -7,6 +7,8 @@ module TAC menu_bar.clear do button get_image("#{TAC::ROOT_PATH}/media/icons/right.png"), tip: "Run Simulation", image_height: 1.0 do + save_source + begin @simulation_start_time = Gosu.milliseconds @simulation = TAC::Simulator::Simulation.new(source_code: @source_code.value, field_container: @field_container) @@ -23,8 +25,7 @@ module TAC end button get_image("#{TAC::ROOT_PATH}/media/icons/save.png"), tip: "Save", image_height: 1.0 do - File.open(SOURCE_FILE_PATH, "w") { |f| f.write @source_code.value } - @simulation_status.value = "Saved source to #{SOURCE_FILE_PATH}" + save_source end end @@ -57,8 +58,14 @@ robot.forward 100" end end + def save_source + File.open(SOURCE_FILE_PATH, "w") { |f| f.write @source_code.value } + @simulation_status.value = "Saved source to #{SOURCE_FILE_PATH}" + end + def blur @simulation.robots.each { |robot| robot.queue.clear } if @simulation + save_source end def draw diff --git a/lib/simulator/robot.rb b/lib/simulator/robot.rb index a362482..1c787dd 100644 --- a/lib/simulator/robot.rb +++ b/lib/simulator/robot.rb @@ -75,6 +75,14 @@ module TAC @queue << Move.new(robot: self, distance: -distance, power: power) end + def strafe_right(distance, power = 1.0) + @queue << Strafe.new(robot: self, distance: distance, power: power) + end + + def strafe_left(distance, power = 1.0) + @queue << Strafe.new(robot: self, distance: -distance, power: power) + end + def turn(relative_angle, power = 1.0) @queue << Turn.new(robot: self, relative_angle: relative_angle, power: power) end @@ -143,6 +151,52 @@ class State end end + class Strafe < State + def initialize(robot:, distance:, power:) + @robot = robot + @distance = distance + @power = power.clamp(-1.0, 1.0) + end + + def start + @starting_position = @robot.position.clone + @goal = @starting_position.clone + if @distance.positive? + @goal.x += Math.cos((@robot.angle + 90).gosu_to_radians) * @distance + @goal.y += Math.sin((@robot.angle + 90).gosu_to_radians) * @distance + else + @goal.x += Math.cos((@robot.angle - 90).gosu_to_radians) * @distance + @goal.y += Math.sin((@robot.angle - 90).gosu_to_radians) * @distance + end + + @complete = false + @allowable_error = 1.0 + end + + def draw + Gosu.draw_line( + @robot.position.x + @robot.width / 2, @robot.position.y + @robot.depth / 2, TAC::Palette::TIMECRAFTERS_TERTIARY, + @goal.x + @robot.width / 2, @goal.y + @robot.depth / 2, TAC::Palette::TIMECRAFTERS_TERTIARY + ) + Gosu.draw_rect(@goal.x + (@robot.width / 2 - 1), @goal.y + (@robot.depth / 2 - 1), 2, 2, Gosu::Color::RED) + end + + def update(dt) + speed = (@distance > 0 ? @power * dt : -@power * dt) * @robot.speed + + if @robot.position.distance(@goal) <= @allowable_error + @complete = true + @robot.position = @goal + else + if speed > 0 + @robot.position -= (@robot.position - @goal).normalized * speed + else + @robot.position += (@robot.position - @goal).normalized * speed + end + end + end + end + class Turn < State def initialize(robot:, relative_angle:, power:) @robot = robot