mirror of
https://github.com/cyberarm/cyberarm_engine.git
synced 2025-12-16 05:02:34 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 24bd769a32 | |||
| 2be5733bc1 | |||
| c8734ae98b | |||
| c35d587419 | |||
| 153871e7f3 | |||
| cf91d4a083 | |||
| 35ad687d4c | |||
| 54802e1254 | |||
| 6cf4cd73dd | |||
| 5e5f8ba7ea | |||
| 63a51d9d2f | |||
| 6af384536a | |||
| c1b25d2045 | |||
| a915a25699 | |||
| 0aa9b59316 | |||
| d2bf406d29 | |||
| f82c101728 |
@@ -27,8 +27,8 @@ Gem::Specification.new do |spec|
|
||||
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
||||
spec.require_paths = %w[lib assets]
|
||||
|
||||
spec.add_dependency "clipboard", "~> 1.3.5"
|
||||
spec.add_dependency "excon", "~> 0.78.0"
|
||||
spec.add_dependency "clipboard", "~> 1.3"
|
||||
spec.add_dependency "excon", "~> 0.88"
|
||||
spec.add_dependency "gosu", "~> 1.1"
|
||||
spec.add_dependency "gosu_more_drawables", "~> 0.3"
|
||||
# spec.add_dependency "ffi", :platforms => [:mswin, :mingw] # Required by Clipboard on Windows
|
||||
|
||||
@@ -4,7 +4,7 @@ module CyberarmEngine
|
||||
include Event
|
||||
include Common
|
||||
|
||||
attr_accessor :x, :y, :z, :enabled, :tip
|
||||
attr_accessor :x, :y, :z, :tip, :element_visible
|
||||
attr_reader :parent, :options, :style, :event_handler, :background_canvas, :border_canvas
|
||||
|
||||
def initialize(options = {}, block = nil)
|
||||
@@ -13,9 +13,9 @@ module CyberarmEngine
|
||||
@options = options
|
||||
@block = block
|
||||
|
||||
@focus = @options[:focus].nil? ? false : @options[:focus]
|
||||
@enabled = @options[:enabled].nil? ? true : @options[:enabled]
|
||||
@visible = @options[:visible].nil? ? true : @options[:visible]
|
||||
@focus = !@options.key?(:focus) ? false : @options[:focus]
|
||||
@enabled = !@options.key?(:enabled) ? true : @options[:enabled]
|
||||
@visible = !@options.key?(:visible) ? true : @options[:visible]
|
||||
@tip = @options[:tip] || ""
|
||||
|
||||
@debug_color = @options[:debug_color].nil? ? Gosu::Color::RED : @options[:debug_color]
|
||||
@@ -24,6 +24,7 @@ module CyberarmEngine
|
||||
|
||||
@root ||= nil
|
||||
@gui_state ||= nil
|
||||
@element_visible = true
|
||||
|
||||
@x = @style.x
|
||||
@y = @style.y
|
||||
@@ -51,6 +52,9 @@ module CyberarmEngine
|
||||
def stylize
|
||||
set_static_position
|
||||
|
||||
set_color
|
||||
set_font
|
||||
|
||||
set_padding
|
||||
set_margin
|
||||
|
||||
@@ -70,6 +74,15 @@ module CyberarmEngine
|
||||
@y = @style.y if @style.y != 0
|
||||
end
|
||||
|
||||
def set_color
|
||||
@style.color = safe_style_fetch(:color)
|
||||
@text&.color = @style.color
|
||||
end
|
||||
|
||||
def set_font
|
||||
@text&.swap_font(safe_style_fetch(:text_size), safe_style_fetch(:font))
|
||||
end
|
||||
|
||||
def set_background
|
||||
@style.background = safe_style_fetch(:background)
|
||||
|
||||
@@ -138,14 +151,8 @@ module CyberarmEngine
|
||||
old_width = width
|
||||
old_height = height
|
||||
|
||||
_style = @style.send(event)
|
||||
@style_event = event
|
||||
|
||||
if @text.is_a?(CyberarmEngine::Text)
|
||||
@text.color = _style&.dig(:color) || @style.default[:color]
|
||||
@text.swap_font(_style&.dig(:text_size) || @style.default[:text_size], _style&.dig(:font) || @style.default[:font])
|
||||
end
|
||||
|
||||
return if self.is_a?(ToolTip)
|
||||
|
||||
if old_width != width || old_height != height
|
||||
@@ -238,6 +245,14 @@ module CyberarmEngine
|
||||
:handled
|
||||
end
|
||||
|
||||
def enabled=(boolean)
|
||||
@enabled = boolean
|
||||
|
||||
recalculate
|
||||
|
||||
@enabled
|
||||
end
|
||||
|
||||
def enabled?
|
||||
@enabled
|
||||
end
|
||||
@@ -246,6 +261,10 @@ module CyberarmEngine
|
||||
@visible
|
||||
end
|
||||
|
||||
def element_visible?
|
||||
@element_visible
|
||||
end
|
||||
|
||||
def toggle
|
||||
@visible = !@visible
|
||||
root.gui_state.request_recalculate
|
||||
@@ -265,14 +284,13 @@ module CyberarmEngine
|
||||
|
||||
def draw
|
||||
return unless visible?
|
||||
return unless element_visible?
|
||||
|
||||
@style.background_canvas.draw
|
||||
@style.background_nine_slice_canvas.draw
|
||||
@style.border_canvas.draw
|
||||
|
||||
Gosu.clip_to(@x, @y, width, height) do
|
||||
render
|
||||
end
|
||||
render
|
||||
end
|
||||
|
||||
def debug_draw
|
||||
@@ -370,19 +388,42 @@ module CyberarmEngine
|
||||
end
|
||||
|
||||
def scroll_width
|
||||
@children.sum(&:width) + noncontent_width
|
||||
@children.sum(&:outer_width)
|
||||
end
|
||||
|
||||
def scroll_height
|
||||
@children.sum(&:height) + noncontent_height
|
||||
if is_a?(CyberarmEngine::Element::Flow)
|
||||
return 0 if @children.size.zero?
|
||||
|
||||
pairs_ = []
|
||||
sorted_children_ = @children.sort_by(&:y)
|
||||
a_ = []
|
||||
y_position_ = sorted_children_.first.y
|
||||
|
||||
sorted_children_.each do |child|
|
||||
unless child.y == y_position_
|
||||
y_position_ = child.y
|
||||
pairs_ << a_
|
||||
a_ = []
|
||||
end
|
||||
|
||||
a_ << child
|
||||
end
|
||||
|
||||
pairs_ << a_ unless pairs_.last == a_
|
||||
|
||||
pairs_.sum { |pair| pair.map(&:outer_height).max } + @style.padding_bottom + @style.border_thickness_bottom
|
||||
else
|
||||
@children.sum(&:outer_height) + @style.padding_bottom + @style.border_thickness_bottom
|
||||
end
|
||||
end
|
||||
|
||||
def max_scroll_width
|
||||
scroll_width - width
|
||||
scroll_width - outer_width
|
||||
end
|
||||
|
||||
def max_scroll_height
|
||||
scroll_height - height
|
||||
scroll_height - outer_height
|
||||
end
|
||||
|
||||
def dimensional_size(size, dimension)
|
||||
|
||||
@@ -86,9 +86,12 @@ module CyberarmEngine
|
||||
|
||||
old_width = width
|
||||
old_height = height
|
||||
recalculate
|
||||
|
||||
root.gui_state.request_recalculate if old_width != width || old_height != height
|
||||
if old_width != width || old_height != height
|
||||
root.gui_state.request_recalculate
|
||||
else
|
||||
recalculate
|
||||
end
|
||||
|
||||
publish(:changed, self.value)
|
||||
end
|
||||
|
||||
@@ -45,7 +45,7 @@ module CyberarmEngine
|
||||
root.gui_state.request_recalculate
|
||||
end
|
||||
|
||||
def apend(&block)
|
||||
def append(&block)
|
||||
old_container = $__current_container__
|
||||
|
||||
$__current_container__ = self
|
||||
@@ -57,7 +57,12 @@ module CyberarmEngine
|
||||
end
|
||||
|
||||
def render
|
||||
Gosu.clip_to(@x, @y, width, height) do
|
||||
Gosu.clip_to(
|
||||
@x + @style.border_thickness_left + @style.padding_left,
|
||||
@y + @style.border_thickness_top + @style.padding_top,
|
||||
content_width + 1,
|
||||
content_height + 1
|
||||
) do
|
||||
@children.each(&:draw)
|
||||
end
|
||||
end
|
||||
@@ -103,6 +108,8 @@ module CyberarmEngine
|
||||
|
||||
stylize
|
||||
|
||||
# s = Gosu.milliseconds
|
||||
|
||||
layout
|
||||
|
||||
if is_root?
|
||||
@@ -129,8 +136,13 @@ module CyberarmEngine
|
||||
child.reposition # TODO: Implement top,bottom,left,center, and right positioning
|
||||
|
||||
Stats.increment(:gui_recalculations_last_frame, 1)
|
||||
|
||||
child.element_visible = child.x >= @x - child.width && child.x <= @x + width &&
|
||||
child.y >= @y - child.height && child.y <= @y + height
|
||||
end
|
||||
|
||||
# puts "TOOK: #{Gosu.milliseconds - s}ms to recalculate #{self.class}:0x#{self.object_id.to_s(16)}"
|
||||
|
||||
update_background
|
||||
end
|
||||
|
||||
@@ -194,7 +206,8 @@ module CyberarmEngine
|
||||
if @scroll_position.y < 0
|
||||
@scroll_position.y += @scroll_speed
|
||||
@scroll_position.y = 0 if @scroll_position.y > 0
|
||||
recalculate
|
||||
|
||||
root.gui_state.request_recalculate_for(self)
|
||||
|
||||
return :handled
|
||||
end
|
||||
@@ -208,7 +221,8 @@ module CyberarmEngine
|
||||
if @scroll_position.y.abs < max_scroll_height
|
||||
@scroll_position.y -= @scroll_speed
|
||||
@scroll_position.y = -max_scroll_height if @scroll_position.y.abs > max_scroll_height
|
||||
recalculate
|
||||
|
||||
root.gui_state.request_recalculate_for(self)
|
||||
|
||||
return :handled
|
||||
end
|
||||
|
||||
@@ -46,10 +46,18 @@ module CyberarmEngine
|
||||
:handled
|
||||
end
|
||||
|
||||
def clicked_left_mouse_button(_sender, _x, _y)
|
||||
# @block&.call(self.value) if @enabled
|
||||
|
||||
:handled
|
||||
end
|
||||
|
||||
def show_menu
|
||||
@menu.clear
|
||||
|
||||
@items.each do |item|
|
||||
next if item == self.value
|
||||
|
||||
btn = Button.new(
|
||||
item,
|
||||
{
|
||||
@@ -61,7 +69,7 @@ module CyberarmEngine
|
||||
},
|
||||
proc do
|
||||
self.choose = item
|
||||
@block&.call(item)
|
||||
@block&.call(self.value)
|
||||
end
|
||||
)
|
||||
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
module CyberarmEngine
|
||||
class Element
|
||||
class Progress < Element
|
||||
attr_reader :type
|
||||
|
||||
def initialize(options = {}, block = nil)
|
||||
super(options, block)
|
||||
|
||||
@animation_speed = options[:animation_speed] || 3_000
|
||||
@marquee_width = options[:marquee_width] || 0.25
|
||||
@marquee_offset = 0
|
||||
@marquee_animation_time = Gosu.milliseconds
|
||||
@type = options[:type] || :linear
|
||||
@fraction_background = Background.new(background: @style.fraction_background)
|
||||
self.value = options[:fraction] || 0.0
|
||||
end
|
||||
@@ -24,15 +31,45 @@ module CyberarmEngine
|
||||
def update_background
|
||||
super
|
||||
|
||||
@fraction_background.x = @style.border_thickness_left + @style.padding_left + @x
|
||||
@fraction_background.x = (@style.border_thickness_left + @style.padding_left + @x) + @marquee_offset
|
||||
@fraction_background.y = @style.border_thickness_top + @style.padding_top + @y
|
||||
@fraction_background.z = @z
|
||||
@fraction_background.width = @width * @fraction
|
||||
@fraction_background.width = @width * (@type == :marquee ? @marquee_width : @fraction)
|
||||
@fraction_background.height = @height
|
||||
|
||||
@fraction_background.background = @style.fraction_background
|
||||
end
|
||||
|
||||
def update
|
||||
super
|
||||
|
||||
return unless @type == :marquee
|
||||
|
||||
marquee_width = @width * @marquee_width
|
||||
range = @width + marquee_width
|
||||
|
||||
@marquee_offset = (@width * (Gosu.milliseconds - @marquee_animation_time) / @animation_speed) - marquee_width
|
||||
@marquee_animation_time = Gosu.milliseconds if @marquee_offset > range
|
||||
|
||||
update_background
|
||||
end
|
||||
|
||||
def type=(type)
|
||||
@type = type
|
||||
|
||||
case type
|
||||
when :linear
|
||||
@marquee_offset = 0
|
||||
when :marquee
|
||||
@marquee_offset = 0
|
||||
@marquee_animation_time = Gosu.milliseconds
|
||||
else
|
||||
raise ArgumentError, "Only types :linear and :marquee are supported"
|
||||
end
|
||||
|
||||
update_background
|
||||
end
|
||||
|
||||
def value
|
||||
@fraction
|
||||
end
|
||||
|
||||
@@ -47,8 +47,8 @@ module CyberarmEngine
|
||||
when :left
|
||||
@text.x = @style.border_thickness_left + @style.padding_left + @x
|
||||
when :center
|
||||
@text.x = if @text.width <= outer_width
|
||||
@x + outer_width / 2 - @text.width / 2
|
||||
@text.x = if @text.width <= width
|
||||
@x + width / 2 - @text.width / 2
|
||||
else # Act as left aligned
|
||||
@style.border_thickness_left + @style.padding_left + @x
|
||||
end
|
||||
@@ -61,46 +61,64 @@ module CyberarmEngine
|
||||
end
|
||||
|
||||
def handle_text_wrapping(max_width)
|
||||
max_width ||= @parent&.width
|
||||
max_width ||= @parent&.content_width
|
||||
max_width ||= @x - (window.width + noncontent_width)
|
||||
wrap_behavior = style.text_wrap
|
||||
copy = @raw_text.to_s.dup
|
||||
|
||||
if line_width(copy[0]) <= max_width && line_width(copy) > max_width && wrap_behavior != :none
|
||||
breaks = []
|
||||
# Only perform text wrapping: if it is enabled, is possible to wrap, and text is too long to fit on one line
|
||||
if wrap_behavior != :none && line_width(copy[0]) <= max_width && line_width(copy) > max_width
|
||||
breaks = [] # list of indexes to insert a line break
|
||||
line_start = 0
|
||||
line_end = copy.length
|
||||
line_end = copy.length
|
||||
|
||||
while line_start != copy.length
|
||||
if line_width(copy[line_start...line_end]) > max_width
|
||||
line_end = ((line_end - line_start) / 2.0)
|
||||
line_end = 1.0 if line_end <= 1
|
||||
elsif line_end < copy.length && line_width(copy[line_start...line_end + 1]) < max_width
|
||||
# To small, grow!
|
||||
# TODO: find a more efficient way
|
||||
line_end += 1
|
||||
stalled = false
|
||||
stalled_interations = 0
|
||||
max_stalled_iterations = 10
|
||||
checked_copy_length = line_width(copy[line_start..line_end])
|
||||
|
||||
else # FOUND IT!
|
||||
entering_line_end = line_end.floor
|
||||
max_reach = line_end.floor - line_start < 63 ? line_end.floor - line_start : 63
|
||||
reach = 0
|
||||
# find length of lines
|
||||
while line_width(copy[line_start..line_end]) > max_width && stalled_interations < max_stalled_iterations
|
||||
search_start = line_start
|
||||
search_end = line_end
|
||||
|
||||
if wrap_behavior == :word_wrap
|
||||
max_reach.times do |i|
|
||||
reach = i
|
||||
break if copy[line_end.floor - i].to_s.match(/[[:punct:]]| /)
|
||||
# Perform a binary search to find length of line
|
||||
while search_start < search_end
|
||||
midpoint = ((search_start.to_f + search_end) / 2.0).floor
|
||||
|
||||
if line_width(copy[line_start..midpoint]) > max_width
|
||||
search_end = midpoint
|
||||
else
|
||||
search_start = midpoint + 1
|
||||
end
|
||||
end
|
||||
|
||||
if wrap_behavior == :word_wrap
|
||||
word_search_end = search_end
|
||||
failed = false
|
||||
|
||||
until(copy[word_search_end].to_s.match(/[[:punct:]]| /))
|
||||
word_search_end -= 1
|
||||
|
||||
if word_search_end <= 1 || word_search_end < line_start
|
||||
failed = true
|
||||
break
|
||||
end
|
||||
|
||||
# puts "Max width: #{max_width}/#{line_width(@raw_text)} Reach: {#{reach}/#{max_reach}} Line Start: #{line_start}/#{line_end.floor} (#{copy.length}|#{@raw_text.length}) [#{entering_line_end}] '#{copy}' {#{copy[line_start...line_end]}}"
|
||||
line_end = line_end.floor - reach + 1 if reach != max_reach # Add +1 to walk in front of punctuation
|
||||
end
|
||||
|
||||
breaks << line_end.floor
|
||||
line_start = line_end.floor
|
||||
line_end = copy.length
|
||||
|
||||
break if entering_line_end == copy.length || reach == max_reach
|
||||
line_start = failed ? search_end : word_search_end + 1 # walk in front of punctuation
|
||||
else
|
||||
line_start = search_end
|
||||
end
|
||||
|
||||
breaks << line_start
|
||||
|
||||
# Prevent locking up due to outer while loop text width < max_width check not being satisfied.
|
||||
stalled = checked_copy_length == line_width(copy[line_start..line_end])
|
||||
checked_copy_length = line_width(copy[line_start..line_end])
|
||||
|
||||
stalled_interations += 1 if stalled
|
||||
stalled_interations = 0 unless stalled
|
||||
end
|
||||
|
||||
breaks.each_with_index do |pos, index|
|
||||
@@ -124,9 +142,12 @@ module CyberarmEngine
|
||||
|
||||
old_width = width
|
||||
old_height = height
|
||||
recalculate
|
||||
|
||||
root.gui_state.request_recalculate if old_width != width || old_height != height
|
||||
if old_width != width || old_height != height
|
||||
root.gui_state.request_recalculate
|
||||
else
|
||||
recalculate
|
||||
end
|
||||
|
||||
publish(:changed, self.value)
|
||||
end
|
||||
|
||||
@@ -25,6 +25,7 @@ module CyberarmEngine
|
||||
@last_mouse_pos = nil
|
||||
@dragging_element = nil
|
||||
@pending_recalculate_request = false
|
||||
@pending_element_recalculate_requests = []
|
||||
|
||||
@menu = nil
|
||||
@min_drag_distance = 0
|
||||
@@ -56,6 +57,7 @@ module CyberarmEngine
|
||||
|
||||
if @tip.value.length.positive?
|
||||
Gosu.flush
|
||||
|
||||
@tip.draw
|
||||
end
|
||||
|
||||
@@ -75,6 +77,9 @@ module CyberarmEngine
|
||||
@pending_recalculate_request = false
|
||||
end
|
||||
|
||||
@pending_element_recalculate_requests.each(&:recalculate)
|
||||
@pending_element_recalculate_requests.clear
|
||||
|
||||
if @pending_focus_request
|
||||
@pending_focus_request = false
|
||||
|
||||
@@ -231,6 +236,13 @@ module CyberarmEngine
|
||||
@pending_recalculate_request = true
|
||||
end
|
||||
|
||||
def request_recalculate_for(element)
|
||||
# element is already queued
|
||||
return if @pending_element_recalculate_requests.detect { |e| e == element }
|
||||
|
||||
@pending_element_recalculate_requests << element
|
||||
end
|
||||
|
||||
def request_focus(element)
|
||||
@pending_focus_request = true
|
||||
@pending_focus_element = element
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module CyberarmEngine
|
||||
NAME = "InDev".freeze
|
||||
VERSION = "0.19.0".freeze
|
||||
VERSION = "0.20.0".freeze
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user