diff options
| author | Amir Rajan <[email protected]> | 2021-01-18 12:08:34 -0600 |
|---|---|---|
| committer | Amir Rajan <[email protected]> | 2021-01-18 12:08:34 -0600 |
| commit | a4b9c048a1d751f5226833bb0c527ba1a8ac5d09 (patch) | |
| tree | 3f2535e7a6272e796d50e7f07c906d4c9eb1b14a /dragon | |
| parent | a24a71805b1924ae7f80776c736f94575c171d2c (diff) | |
| download | dragonruby-game-toolkit-contrib-a4b9c048a1d751f5226833bb0c527ba1a8ac5d09.tar.gz dragonruby-game-toolkit-contrib-a4b9c048a1d751f5226833bb0c527ba1a8ac5d09.zip | |
Synced with 2.3.
Diffstat (limited to 'dragon')
| -rw-r--r-- | dragon/args.rb | 4 | ||||
| -rw-r--r-- | dragon/attr_gtk.rb | 4 | ||||
| -rw-r--r-- | dragon/autocomplete.rb | 131 | ||||
| -rw-r--r-- | dragon/console.rb | 4 | ||||
| -rw-r--r-- | dragon/draw.rb | 76 | ||||
| -rw-r--r-- | dragon/easing.rb | 4 | ||||
| -rw-r--r-- | dragon/framerate.rb | 83 | ||||
| -rw-r--r-- | dragon/framerate_diagnostics.rb | 1 | ||||
| -rw-r--r-- | dragon/geometry.rb | 62 | ||||
| -rw-r--r-- | dragon/inputs.rb | 6 | ||||
| -rw-r--r-- | dragon/ios_wizard.rb | 31 | ||||
| -rw-r--r-- | dragon/layout.rb | 7 | ||||
| -rw-r--r-- | dragon/numeric.rb | 22 | ||||
| -rw-r--r-- | dragon/readme_docs.rb | 45 |
14 files changed, 408 insertions, 72 deletions
diff --git a/dragon/args.rb b/dragon/args.rb index 6eb644e..43e6a18 100644 --- a/dragon/args.rb +++ b/dragon/args.rb @@ -222,5 +222,9 @@ module GTK def controller_two @inputs.controller_two end + + def autocomplete_methods + [:inputs, :outputs, :gtk, :state, :geometry, :audio, :grid, :layout] + end end end diff --git a/dragon/attr_gtk.rb b/dragon/attr_gtk.rb index c4e03a8..2f2ccc5 100644 --- a/dragon/attr_gtk.rb +++ b/dragon/attr_gtk.rb @@ -42,4 +42,8 @@ module AttrGTK def geometry args.geometry end + + def layout + args.layout + end end diff --git a/dragon/autocomplete.rb b/dragon/autocomplete.rb new file mode 100644 index 0000000..f5f03b4 --- /dev/null +++ b/dragon/autocomplete.rb @@ -0,0 +1,131 @@ +# Copyright 2019 DragonRuby LLC +# MIT License +# autocomplete.rb has been released under MIT (*only this file*). + +module GTK + class Runtime + module Autocomplete + def autocomplete_parse opts + if opts[:file] && !opts[:text] + opts[:text] = read_file opts[:file] + end + + text = opts[:text] + index = opts[:index] + sum = 0 + lines = text.each_line.to_a.map do |l| + sum += l.length + { line: l, length: l.length, sum: sum } + end + cursor_line = lines.find { |l| l[:sum] >= index } + previous_line = lines.find { |l| l[:sum] < index } + previous_line ||= { sum: 0 } + if cursor_line + sub_index = index - previous_line[:sum] + word = (cursor_line[:line][0..sub_index - 1]).strip + token = (word.split " ")[-1] + dots = (token.split ".") + dot = dots[-1] + end + + { + text: opts[:text], + file: opts[:file], + index: opts[:index], + cursor_line: cursor_line, + previous_line: previous_line, + word: word, + token: token, + dots: dots, + dot: dot + } + end + + def autocomplete_filter_methods keys, *ignores + ignores ||= [] + ignores = [ignores].flatten + keys = keys.map { |k| k.to_s } + others = ["def", "end"] + + [ :entity_keys_by_ref, + :entity_name, + :as_hash, + :clear!, + :created_at_elapsed, + :entity_id, + "entity_id=", + "tick_count=", + :global_created_at_elapsed, + :load_entity_data!, + :meta, + :meta!, + :new?, + :old?, + :original_eq_eq, :set!, + :update_entity_keys_by_ref, + :with_meta] + + ignores + keys.find_all { |k| k.to_s.to_i.to_s == k.to_s } + + final = (keys - (others.map { |m| m.to_s })).uniq + final + end + + def suggest_autocompletion opts + parse_result = autocomplete_parse opts + return [] unless parse_result[:cursor_line] + text = parse_result[:text] + word = parse_result[:word] + token = parse_result[:token] + dots = parse_result[:dots] + dot = parse_result[:dot] + + return [] if word.strip.start_with? "#" + + if word[-1] == "." && token + lookup = { + 'args' => lambda { $gtk.args }, + 'inputs' => lambda { $gtk.args.inputs }, + 'outputs' => lambda { $gtk.args.outputs }, + 'layout' => lambda { $gtk.args.outputs }, + 'keyboard' => lambda { $gtk.args.keyboard }, + 'key_down' => lambda { $gtk.args.keyboard.key_down }, + 'key_up' => lambda { $gtk.args.keyboard.key_up }, + 'state' => lambda { $gtk.args.state }, + '$gtk' => lambda { $gtk } + } + + lookup_result = lookup[dot] + + return autocomplete_filter_methods lookup_result.call.autocomplete_methods if lookup_result + + start_collecting = false + dots_after_state = dots.find_all do |s| + if s == "state" + start_collecting = true + false + else + start_collecting + end + end + + target = $gtk.args.state + dots_after_state.each do |k| + target = target.as_hash[k.to_sym] if target.respond_to? :as_hash + end + + return autocomplete_filter_methods target.as_hash.keys + end + + + text.gsub!("[", " ") + text.gsub!("]", " ") + text.gsub!("(", " ") + text.gsub!(")", " ") + text.gsub!(":", "") + text.gsub!(".", " ") + text.gsub!("=", " ") + return (autocomplete_filter_methods (text.split " "), + :gtk, :false, :true, :args, :suppress_mailbox, :end) + end + end # end Autocomplete + end # end Runtime +end # end GTK diff --git a/dragon/console.rb b/dragon/console.rb index ddf0702..be476bd 100644 --- a/dragon/console.rb +++ b/dragon/console.rb @@ -569,7 +569,7 @@ S end def error_markers - ["exception", "error", "undefined method", "failed", "syntax", "deprecated"] + ["exception:", "error:", "undefined method", "failed", "syntax", "deprecated"] end def include_subdued_markers? text @@ -581,7 +581,7 @@ S end def subdued_markers - ["reloaded", "exported the"] + ["reloaded", "exported the", "~require~"] end def calc args diff --git a/dragon/draw.rb b/dragon/draw.rb index ee91b09..0afea16 100644 --- a/dragon/draw.rb +++ b/dragon/draw.rb @@ -16,115 +16,131 @@ module GTK # pass.solids.each { |s| draw_solid s } # while loops are faster than each with block idx = 0 + length = pass.solids.length while idx < pass.solids.length - draw_solid (pass.solids.value idx) # accessing an array using .value instead of [] is faster + draw_solid (pass.solids.at idx) # accessing an array using .value instead of [] is faster idx += 1 end # pass.static_solids.each { |s| draw_solid s } idx = 0 - while idx < pass.static_solids.length - draw_solid (pass.static_solids.value idx) + length = pass.static_solids.length + while idx < length + draw_solid (pass.static_solids.at idx) idx += 1 end # pass.sprites.each { |s| draw_sprite s } idx = 0 - while idx < pass.sprites.length - draw_sprite (pass.sprites.value idx) + length = pass.sprites.length + while idx < length + draw_sprite (pass.sprites.at idx) idx += 1 end # pass.static_sprites.each { |s| draw_sprite s } idx = 0 - while idx < pass.static_sprites.length - draw_sprite (pass.static_sprites.value idx) + length = pass.static_sprites.length + while idx < length + draw_sprite (pass.static_sprites.at idx) idx += 1 end # pass.primitives.each { |p| draw_primitive p } idx = 0 - while idx < pass.primitives.length - draw_primitive (pass.primitives.value idx) + length = pass.primitives.length + while idx < length + draw_primitive (pass.primitives.at idx) idx += 1 end # pass.static_primitives.each { |p| draw_primitive p } idx = 0 - while idx < pass.static_primitives.length - draw_primitive (pass.static_primitives.value idx) + length = pass.static_primitives.length + while idx < length + draw_primitive (pass.static_primitives.at idx) idx += 1 end # pass.labels.each { |l| draw_label l } idx = 0 - while idx < pass.labels.length - draw_label (pass.labels.value idx) + length = pass.labels.length + while idx < length + draw_label (pass.labels.at idx) idx += 1 end # pass.static_labels.each { |l| draw_label l } idx = 0 - while idx < pass.static_labels.length - draw_label (pass.static_labels.value idx) + length = pass.static_labels.length + while idx < length + draw_label (pass.static_labels.at idx) idx += 1 end # pass.lines.each { |l| draw_line l } idx = 0 - while idx < pass.lines.length - draw_line (pass.lines.value idx) + length = pass.lines.length + while idx < length + draw_line (pass.lines.at idx) idx += 1 end # pass.static_lines.each { |l| draw_line l } idx = 0 + length = pass.static_lines.length while idx < pass.static_lines.length - draw_line (pass.static_lines.value idx) + draw_line (pass.static_lines.at idx) idx += 1 end # pass.borders.each { |b| draw_border b } idx = 0 - while idx < pass.borders.length - draw_border (pass.borders.value idx) + length = pass.borders.length + while idx < length + draw_border (pass.borders.at idx) idx += 1 end # pass.static_borders.each { |b| draw_border b } idx = 0 - while idx < pass.static_borders.length - draw_border (pass.static_borders.value idx) + length = pass.static_borders.length + while idx < length + draw_border (pass.static_borders.at idx) idx += 1 end if !$gtk.production # pass.debug.each { |r| draw_primitive r } idx = 0 - while idx < pass.debug.length - draw_primitive (pass.debug.value idx) + length = pass.debug.length + while idx < length + draw_primitive (pass.debug.at idx) idx += 1 end # pass.static_debug.each { |r| draw_primitive r } idx = 0 - while idx < pass.static_debug.length - draw_primitive (pass.static_debug.value idx) + length = pass.static_debug.length + while idx < length + draw_primitive (pass.static_debug.at idx) idx += 1 end end # pass.reserved.each { |r| draw_primitive r } idx = 0 - while idx < pass.reserved.length - draw_primitive (pass.reserved.value idx) + length = pass.reserved.length + while idx < length + draw_primitive (pass.reserved.at idx) idx += 1 end # pass.static_reserved.each { |r| draw_primitive r } idx = 0 - while idx < pass.static_reserved.length - draw_primitive (pass.static_reserved.value idx) + length = pass.static_reserved.length + while idx < length + draw_primitive (pass.static_reserved.at idx) idx += 1 end rescue Exception => e diff --git a/dragon/easing.rb b/dragon/easing.rb index 310e7ed..f503132 100644 --- a/dragon/easing.rb +++ b/dragon/easing.rb @@ -31,12 +31,12 @@ module GTK def self.initial_value *definitions definitions.flatten! - return Easing.exec_definition (definitions.value(-1) || :identity), 0, 10, 0 + return Easing.exec_definition (definitions.at(-1) || :identity), 0, 10, 0 end def self.final_value *definitions definitions.flatten! - return Easing.exec_definition (definitions.value(-1) || :identity), 0, 10, 1.0 + return Easing.exec_definition (definitions.at(-1) || :identity), 0, 10, 1.0 end def self.exec_definition definition, start_tick, duration, x diff --git a/dragon/framerate.rb b/dragon/framerate.rb new file mode 100644 index 0000000..2550443 --- /dev/null +++ b/dragon/framerate.rb @@ -0,0 +1,83 @@ +# Copyright 2019 DragonRuby LLC +# MIT License +# framerate.rb has been released under MIT (*only this file*). + +module GTK + class Runtime + module Framerate + def framerate_init + @tick_time = Time.new.to_i + end + + def delta_framerate + (current_framerate || 0) - (@previous_framerate || 0) + end + + def reset_framerate_calculation + @tick_speed_sum = 0 + @tick_speed_count = 0 + @previous_framerate = 0 + end + + def check_framerate + if @framerate_diagnostics_requested + log "================================" + log framerate_get_diagnostics + @framerate_diagnostics_requested = false + end + + if !@paused + if @tick_time + @tick_speed_count += 1 + @tick_speed_sum += Time.now.to_i - @tick_time + if @tick_speed_count > 60 * 2 + if framerate_below_threshold? + @last_framerate = current_framerate + if [email protected]? + if !@framerate_important_notification_happened + log_important framerate_warning_message + else + log framerate_warning_message + end + @framerate_important_notification_happened = true + end + end + + @previous_framerate = current_framerate.floor + end + end + + @tick_time = Time.new.to_i + else + reset_framerate_calculation + end + rescue + reset_framerate_calculation + end + + def framerate_diagnostics + # request framerate diagnostics to be printed at the end of tick + @framerate_diagnostics_requested = true + end + + def framerate_below_threshold? + @last_framerate ||= 60 + current_framerate < @last_framerate && + current_framerate < 50 && + @previous_framerate > current_framerate && + Kernel.tick_count > 600 + end + + def current_framerate + return 60 if !@tick_speed_sum || !@tick_speed_sum + r = 100.fdiv(@tick_speed_sum.fdiv(@tick_speed_count) * 100) + if (r.nan? || r.infinite? || r > 58) + r = 60 + end + r || 60 + rescue + 60 + end + end # module Framerate + end # end class Runtime +end # end module GTK diff --git a/dragon/framerate_diagnostics.rb b/dragon/framerate_diagnostics.rb index 7a04efc..4586472 100644 --- a/dragon/framerate_diagnostics.rb +++ b/dragon/framerate_diagnostics.rb @@ -4,7 +4,6 @@ module GTK class Runtime - # @visibility private module FramerateDiagnostics def framerate_get_diagnostics <<-S diff --git a/dragon/geometry.rb b/dragon/geometry.rb index db3ebfc..9385022 100644 --- a/dragon/geometry.rb +++ b/dragon/geometry.rb @@ -76,10 +76,10 @@ module GTK Geometry.point_inside_circle? self, circle_center_point, radius end - def center_inside_rect other_rect - offset_x = (other_rect.w - w).half - offset_y = (other_rect.h - h).half - new_rect = self.shift_rect(0, 0) + def self.center_inside_rect rect, other_rect + offset_x = (other_rect.w - rect.w).half + offset_y = (other_rect.h - rect.h).half + new_rect = rect.shift_rect(0, 0) new_rect.x = other_rect.x + offset_x new_rect.y = other_rect.y + offset_y new_rect @@ -90,30 +90,45 @@ center_inside_rect for self #{self} and other_rect #{other_rect}. Failed with ex S end - def center_inside_rect_y other_rect - offset_y = (other_rect.h - h).half - new_rect = self.shift_rect(0, 0) - new_rect.y = other_rect.y + offset_y + def center_inside_rect other_rect + Geometry.center_inside_rect self, other_rect + end + + def self.center_inside_rect_x rect, other_rect + offset_x = (other_rect.w - rect.w).half + new_rect = rect.shift_rect(0, 0) + new_rect.x = other_rect.x + offset_x + new_rect.y = other_rect.y new_rect rescue Exception => e raise e, <<-S * ERROR: -center_inside_rect_y for self #{self} and other_rect #{other_rect}. Failed with exception #{e}. +center_inside_rect_x for self #{self} and other_rect #{other_rect}. Failed with exception #{e}. S end def center_inside_rect_x other_rect - offset_x = (other_rect.w - w).half - new_rect = self.shift_rect(0, 0) - new_rect.x = other_rect.x + offset_x + Geometry.center_inside_rect_x self, other_rect + end + + def self.center_inside_rect_y rect, other_rect + offset_y = (other_rect.h - rect.h).half + new_rect = rect.shift_rect(0, 0) + new_rect.x = other_rect.x + new_rect.y = other_rect.y + offset_y new_rect rescue Exception => e raise e, <<-S * ERROR: -center_inside_rect_x for self #{self} and other_rect #{other_rect}. Failed with exception #{e}. +center_inside_rect_y for self #{self} and other_rect #{other_rect}. Failed with exception #{e}. S end + def center_inside_rect_y other_rect + Geometry.center_inside_rect_y self, other_rect + end + + # Returns a primitive that is anchored/repositioned based off its retangle. # @gtk def anchor_rect anchor_x, anchor_y @@ -170,10 +185,27 @@ S # @gtk def self.line_slope line, replace_infinity: nil + return replace_infinity if line.x2 == line.x (line.y2 - line.y).fdiv(line.x2 - line.x) .replace_infinity(replace_infinity) end + def self.line_rise_run line + rise = (line.y2 - line.y).to_f + run = (line.x2 - line.x).to_f + if rise.abs > run.abs && rise != 0 + rise = rise.fdiv rise.abs + run = run.fdiv rise.abs + elsif run.abs > rise.abs && run != 0 + rise = rise.fdiv run.abs + run = run.fdiv run.abs + else + rise = rise / rise.abs if rise != 0 + run = run / run.abs if run != 0 + end + return { x: run , y: rise } + end + # @gtk def self.ray_test point, line slope = (line.y2 - line.y).fdiv(line.x2 - line.x) @@ -239,8 +271,8 @@ S return false if rect_one.bottom + tolerance > rect_two.top - tolerance return true rescue Exception => e - context_help_rect_one = (rect_one.help_contract_implementation contract_intersect_rect?)[:not_implemented_methods] - context_help_rect_two = (rect_two.help_contract_implementation contract_intersect_rect?)[:not_implemented_methods] + context_help_rect_one = (rect_one.__help_contract_implementation contract_intersect_rect?)[:not_implemented_methods] + context_help_rect_two = (rect_two.__help_contract_implementation contract_intersect_rect?)[:not_implemented_methods] context_help = "" if context_help_rect_one && context_help_rect_one.length > 0 context_help += <<-S diff --git a/dragon/inputs.rb b/dragon/inputs.rb index 13cfe06..5d1727b 100644 --- a/dragon/inputs.rb +++ b/dragon/inputs.rb @@ -525,6 +525,10 @@ module GTK point.point_inside_circle? center, radius end + def intersect_rect? other_rect + { x: point.x, y: point.y, w: 0, h: 0 }.intersect_rect? other_rect + end + alias_method :position, :point def clear @@ -583,6 +587,7 @@ module GTK :moved_at, :global_moved_at, :touch_order, + :first_tick_down, :x, :y def initialize @@ -590,6 +595,7 @@ module GTK @moved_at = 0 @global_moved_at = 0 @touch_order = 0 + @first_tick_down = true @x = 0 @y = 0 end diff --git a/dragon/ios_wizard.rb b/dragon/ios_wizard.rb index b3f170a..77fd703 100644 --- a/dragon/ios_wizard.rb +++ b/dragon/ios_wizard.rb @@ -85,6 +85,11 @@ class IOSWizard return nil end + def always_fail + return false if $gtk.ivar :rcb_release_mode + return true + end + def check_for_xcode if !cli_app_exist?(xcodebuild_cli_app) raise WizardException.new( @@ -129,6 +134,11 @@ class IOSWizard end end + def restart + init_wizard_status + start + end + def check_for_dev_profile @dev_profile_path = "profiles/development.mobileprovision" if !($gtk.read_file @dev_profile_path) @@ -182,6 +192,21 @@ class IOSWizard log_info "App Identifier is set to : #{@app_id}" end + def set_app_name name + @app_name = name + start + end + + def set_dev_profile path + if !$gtk.read_file path + log_error "I couldn't find a development profile at #{path}." + ask_for_dev_profile + else + @dev_profile_path = path + start + end + end + def blow_away_temp sh "rm -rf #{tmp_directory}" end @@ -192,6 +217,12 @@ class IOSWizard sh "cp -R #{relative_path}/dragonruby-ios.app \"#{tmp_directory}/#{@app_name}.app\"" end + def set_app_id id + log_info = "App Id set to: #{id}" + @app_id = id + start + end + def check_for_device log_info "Looking for device." diff --git a/dragon/layout.rb b/dragon/layout.rb index 915ac37..238193d 100644 --- a/dragon/layout.rb +++ b/dragon/layout.rb @@ -359,6 +359,13 @@ module GTK result[:h] += device.grid_area.gutter * 2 end + result[:x] += opts[:dx] if opts[:dx] + result[:y] += opts[:dy] if opts[:dy] + result[:w] += opts[:dw] if opts[:dw] + result[:h] += opts[:dh] if opts[:dh] + result[:row] = opts[:row] + result[:col] = opts[:col] + result end diff --git a/dragon/numeric.rb b/dragon/numeric.rb index 548e0e2..0ee1457 100644 --- a/dragon/numeric.rb +++ b/dragon/numeric.rb @@ -281,16 +281,18 @@ S vector_y max_value end - # @gtk def mod n self % n end - # @gtk def mod_zero? *ns ns.any? { |n| mod(n) == 0 } end + def zmod? n + (self % n) == 0 + end + def mult n self * n end @@ -592,6 +594,14 @@ class Fixnum def sin Math.sin(self.to_radians) end + + def to_sf + "%.2f" % self + end + + def ifloor int + (self.idiv int.to_i) * int.to_i + end end class Float @@ -638,6 +648,14 @@ class Float return -scalar if self < 0 return scalar if self > 0 end + + def to_sf + "%.2f" % self + end + + def ifloor int + (self.idiv int.to_i) * int.to_i + end end class Integer diff --git a/dragon/readme_docs.rb b/dragon/readme_docs.rb index 6ac336f..0b5e1a1 100644 --- a/dragon/readme_docs.rb +++ b/dragon/readme_docs.rb @@ -509,35 +509,36 @@ specific approach to game development. Collaborate with us. ** Continuity of Design -There is a programming idiom in software called "the pit of -success". The term normalizes up front pain as a necessity in the -(hopes that the investment will yield dividends "when you become -successful"). This results in more "Enterprise TM" code upfront, and -makes it more difficult to get started when you are new to programming. - -DragonRuby's philosophy is to provide a spectrum across the "make it -fast" vs "make it right" spectrum and provide incremental, intuitive -transitions between points on that spectrum. This is captured in how -render primitives can be represented as tuples/arrays, hashes, open -structs/entities, and then finally classes (as opposed to forcing devs -to use classes upfront). - -** Release Often And Soon +There is a programming idiom in software called "The Pit of +Success". The term normalizes upfront pain as a necessity/requirement in the +hopes that the investment will yield dividends "when you become +successful" or "when the code becomes more complicated". This approach to +development is strongly discouraged by us. It leads to over-architected +and unnessary code; creates barriers to rapid prototyping and shipping a game; and +overwhelms beginners who are new to the engine or programming in general. + +DragonRuby's philosophy is to provide multiple options across the "make it +fast" vs "make it right" spectrum, with incremental/intuitive +transitions between the options provided. A concrete example of this philosophy +would be render primitives: the spectrum of options allows renderable constructs take +the form of tuples/arrays (easy to pickup, simple, and fast to code/prototype with), +hashes (a little more work, but gives you the ability to add additional properties), +open and string entities (more work than hashes, but yields cleaner apis), +and finally - if you really need full power/flexibility in rendering - classes +(which take the most amount of code and programming knowledge to create). + +** Release Early and Often The biggest mistake game devs make is spending too much time in isolation building their game. Release something, however small, and -release it quickly. +release it soon. Stop worrying about everything being pixel perfect. Don't wait until your game is 100% complete. Build your game publicly and iterate. Post in the #show-and-tell channel in the community Discord. You'll find a lot of support and encouragement there. -Remember: - -#+begin_quote -Real artists ship. -#+end_quote +Real artists ship. Remember that. ** Sustainable And Ethical Monetization @@ -549,6 +550,10 @@ Charge a fair amount of money for the things you create. It's expected and encouraged within the community. Give what you create away for free to those that can't afford it. +If you are gainfully employed, pay full price for the things you use. If you +do end up getting something at a discount, pay the differnce "forward" to +someone else. + ** Sustainable And Ethical Open Source This goes hand in hand with sustainable and ethical monetization. The |
