cyberarm_engine 0.17.1 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa05052d75e7e9660d600f07d014eba3a118584eaea601540efe3e8d0681494a
4
- data.tar.gz: 6695ea5a245aa63518ffd8070859de10a70e04e25f7da154f9186540aa1e8d41
3
+ metadata.gz: f24458d4ec27a35ff7877afa6e4acdc06d153b8cd161c53063a26282dc14802b
4
+ data.tar.gz: baf54b9e08f2f78a75e6db02dfdc6e7ad749f73afb9dfad6260f666f75447fe8
5
5
  SHA512:
6
- metadata.gz: cdeb1da5ae89e67cf2ee02cea28313da1c657509c0b41fd517f4dd112aafd28d41f8987b5c8a47a95d8c92cd20d132461f87c1764dc74e7c54d560749c38f205
7
- data.tar.gz: 4a26c1468e381323bfd2daa503c686f98b30b2918c0d5795aea43bf9209388a2fa13e9f6d9786e454692a2834f676528645647a1f723c417ed2dc7cf1a1f59fb
6
+ metadata.gz: 6296128b5384912865a96a0e80e176cdc92d853838874507c7eebe5ad86089062ea14fd5a12f0e848fa176047064f4ecf2f68aa1ddddfcc35830e01e688fa164
7
+ data.tar.gz: '07386961b8796e2e4d73155c8e44c6c2df6906888609f8424a3cb94f947328356851dc6e72dc2cf26ba3952415c6696cca3c8524963359c6f2b5463c81d5cc18'
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # CyberarmEngine
1
+ ![CyberarmEngine](https://raw.githubusercontent.com/cyberarm/cyberarm_engine/master/assets/textures/logo.png)
2
2
 
3
3
  Yet Another Game Engine On Top Of Gosu
4
4
 
@@ -32,6 +32,8 @@ require "cyberarm_engine"
32
32
 
33
33
  class Hello < CyberarmEngine::GuiState
34
34
  def setup
35
+ background Gosu::Color::GRAY
36
+
35
37
  stack do
36
38
  label "Hello World!"
37
39
 
@@ -43,15 +45,14 @@ class Hello < CyberarmEngine::GuiState
43
45
  end
44
46
 
45
47
  class Window < CyberarmEngine::Window
46
- def initialize
47
- super
48
+ def setup
48
49
  self.show_cursor = true
49
50
 
50
51
  push_state(Hello)
51
52
  end
52
53
  end
53
54
 
54
- Window.new.show
55
+ Window.new(width: 800, height: 600, fullscreen: false, resizable: true).show
55
56
  ```
56
57
 
57
58
  ## Development
Binary file
@@ -1,9 +1,8 @@
1
1
  CYBERARM_ENGINE_ROOT_PATH = File.expand_path("..", __dir__)
2
2
 
3
- begin
4
- require File.expand_path("../../ffi-gosu/lib/gosu", File.dirname(__FILE__))
5
- rescue LoadError => e
6
- pp e
3
+ if ARGV.join.include?("--ffi-gosu")
4
+ require File.expand_path("../../ffi-gosu/lib/gosu", __dir__)
5
+ else
7
6
  require "gosu"
8
7
  end
9
8
  require "json"
@@ -62,3 +61,5 @@ require_relative "cyberarm_engine/model/model_object"
62
61
  require_relative "cyberarm_engine/model/parser"
63
62
  require_relative "cyberarm_engine/model/parsers/wavefront_parser"
64
63
  require_relative "cyberarm_engine/model/parsers/collada_parser" if defined?(Nokogiri)
64
+
65
+ require_relative "cyberarm_engine/builtin/intro_state"
@@ -1,11 +1,11 @@
1
1
  module CyberarmEngine
2
2
  class Animator
3
- DEFAULT_TWEEN = :linear
4
- def initialize(start_time:, duration:, from:, to:, &block)
3
+ def initialize(start_time:, duration:, from:, to:, tween: :linear, &block)
5
4
  @start_time = start_time
6
5
  @duration = duration
7
6
  @from = from.dup
8
7
  @to = to.dup
8
+ @tween = tween
9
9
  @block = block
10
10
  end
11
11
 
@@ -14,18 +14,18 @@ module CyberarmEngine
14
14
  end
15
15
 
16
16
  def progress
17
- (@start_time.to_f + (Gosu.milliseconds - @start_time)) / (@start_time + @duration.to_f)
17
+ ((Gosu.milliseconds - @start_time) / @duration.to_f).clamp(0.0, 1.0)
18
18
  end
19
19
 
20
20
  def complete?
21
21
  progress >= 1.0
22
22
  end
23
23
 
24
- def transition(from, to, tween = DEFAULT_TWEEN)
24
+ def transition(from = @from, to = @to, tween = @tween)
25
25
  from + (to - from) * send("tween_#{tween}", progress)
26
26
  end
27
27
 
28
- def color_transition(from, to, _tween = DEFAULT_TWEEN)
28
+ def color_transition(from = @from, to = @to, _tween = @tween)
29
29
  r = transition(from.red, to.red)
30
30
  g = transition(from.green, to.green)
31
31
  b = transition(from.blue, to.blue)
@@ -34,7 +34,7 @@ module CyberarmEngine
34
34
  Gosu::Color.rgba(r, g, b, a)
35
35
  end
36
36
 
37
- def color_hsv_transition(from, to, tween = DEFAULT_TWEEN)
37
+ def color_hsv_transition(from = @from, to = @to, tween = @tween)
38
38
  hue = transition(from.hue, to.hue, tween)
39
39
  saturation = transition(from.saturation, to.saturation, tween)
40
40
  value = transition(from.value, to.value, tween)
@@ -49,8 +49,8 @@ module CyberarmEngine
49
49
  t
50
50
  end
51
51
 
52
- def tween_sine(t)
53
- Math.sin(t) * t
52
+ def tween_ease_in_out(t)
53
+ (-0.5 * (Math.cos(Math::PI * t) - 1))
54
54
  end
55
55
  end
56
56
  end
@@ -0,0 +1,128 @@
1
+ module CyberarmEngine
2
+ class IntroState < CyberarmEngine::GameState
3
+ def setup
4
+ @display_width = 800
5
+ @display_height = 600
6
+
7
+ @title_size = 56
8
+ @caption_size = 24
9
+
10
+ @title = CyberarmEngine::Text.new("", size: @title_size, shadow_color: 0xaa_222222)
11
+ @caption = CyberarmEngine::Text.new("", size: @caption_size, shadow_color: 0xaa_222222)
12
+
13
+ @spacer_width = 256
14
+ @spacer_height = 6
15
+ @padding = 6
16
+
17
+ @cyberarm_engine_logo = get_image "#{CYBERARM_ENGINE_ROOT_PATH}/assets/textures/logo.png"
18
+
19
+ @gosu_logo = generate_proxy("Gosu", "Game Library", 0xff_111111)
20
+ @ruby_logo = generate_proxy("Ruby", "Programming Language", 0xff_880000)
21
+ @opengl_logo = generate_proxy("OpenGL", "Graphics API", 0xff_5586a4) if defined?(OpenGL)
22
+
23
+ base_time = Gosu.milliseconds
24
+
25
+ @animators = [
26
+ Animator.new(start_time: base_time += 1000, duration: 100, from: 0.0, to: 1.0, tween: :ease_in_out),
27
+ Animator.new(start_time: base_time += -500, duration: 1_000, from: 0.0, to: 1.0, tween: :ease_in_out),
28
+ Animator.new(start_time: base_time += 500, duration: 1_000, from: 0.0, to: 1.0, tween: :ease_in_out),
29
+ Animator.new(start_time: base_time += 500, duration: 1_000, from: 0.0, to: 1.0, tween: :ease_in_out),
30
+ Animator.new(start_time: base_time + 500, duration: 1_000, from: 0.0, to: 1.0, tween: :ease_in_out),
31
+
32
+ Animator.new(start_time: Gosu.milliseconds + 250, duration: 500, from: 0.0, to: 1.0, tween: :ease_in_out) # CyberarmEngine LOGO
33
+ ]
34
+
35
+ @born_time = Gosu.milliseconds
36
+ @continue_after = 5_000
37
+ end
38
+
39
+ def draw
40
+ Gosu.draw_rect(0, 0, window.width, window.height, 0xff_222222)
41
+
42
+ scale = (@display_width - @padding * 2).to_f / @cyberarm_engine_logo.width * @animators.last.transition
43
+
44
+ @cyberarm_engine_logo.draw_rot(
45
+ window.width / 2,
46
+ (window.height) / 2 - @cyberarm_engine_logo.height / 2 - @padding * 2,
47
+ 2,
48
+ 0,
49
+ 0.5,
50
+ 0.5,
51
+ scale,
52
+ scale
53
+ )
54
+
55
+ Gosu.draw_rect(
56
+ window.width / 2 - (@display_width / 2 + @padding),
57
+ window.height / 2 - @spacer_height / 2,
58
+ @display_width + @padding,
59
+ @spacer_height * @animators[0].transition,
60
+ Gosu::Color::WHITE
61
+ )
62
+
63
+ @title.x = window.width / 2 - @title.width / 2
64
+ @title.y = (window.height / 2 + (@spacer_height / 2) + @padding) * @animators[1].transition
65
+ @title.text = "Powered By"
66
+
67
+ Gosu.clip_to(0, window.height / 2 + (@spacer_height / 2), window.width, @title.height) do
68
+ @title.draw
69
+ end
70
+
71
+ y = @title.y + @title.height * 2
72
+
73
+ Gosu.clip_to(0, y, window.width, @gosu_logo.height) do
74
+ Gosu.translate(@opengl_logo.nil? ? @ruby_logo.width / 2 : 0, 0) do
75
+ @gosu_logo.draw(
76
+ window.width.to_f / 2 - @ruby_logo.width / 2 - (@ruby_logo.width - @padding),
77
+ y * @animators[2].transition,
78
+ 2
79
+ )
80
+ @ruby_logo.draw(
81
+ window.width.to_f / 2 - @ruby_logo.width / 2,
82
+ y * @animators[3].transition,
83
+ 2
84
+ )
85
+ @opengl_logo&.draw(
86
+ window.width.to_f / 2 - @ruby_logo.width / 2 + (@ruby_logo.width - @padding),
87
+ y * @animators[4].transition,
88
+ 2
89
+ )
90
+ end
91
+ end
92
+ end
93
+
94
+ def update
95
+ @animators.each(&:update)
96
+
97
+ return unless Gosu.milliseconds - @born_time >= @continue_after
98
+
99
+ pop_state
100
+ push_state(@options[:forward], @options[:forward_options] || {}) if @options[:forward]
101
+ end
102
+
103
+ def button_down(_id)
104
+ @continue_after = 0
105
+ end
106
+
107
+ def generate_proxy(title, caption, color_hint)
108
+ @title.text = title
109
+ @caption.text = caption
110
+
111
+ width = @spacer_width + 2 * @padding
112
+ height = @title_size + @caption_size + @spacer_height + 2 * @padding + @spacer_height
113
+
114
+ Gosu.record(width.ceil, height.ceil) do
115
+ @title.x = (width - @padding * 2) / 2 - @title.width / 2
116
+ @title.y = @padding
117
+ @title.draw
118
+
119
+ Gosu.draw_rect(0, @padding + @title_size + @padding, @spacer_width, @spacer_height, Gosu::Color::WHITE)
120
+ Gosu.draw_rect(1, @padding + @title_size + @padding + 1, @spacer_width - 2, @spacer_height - 2, color_hint)
121
+
122
+ @caption.x = (width - @padding * 2) / 2 - @caption.width / 2
123
+ @caption.y = @padding + @title_size + @padding + @spacer_height + @padding
124
+ @caption.draw
125
+ end
126
+ end
127
+ end
128
+ end
@@ -16,6 +16,10 @@ module CyberarmEngine
16
16
  window.pop_state
17
17
  end
18
18
 
19
+ def shift_state
20
+ window.shift_state
21
+ end
22
+
19
23
  def show_cursor
20
24
  window.show_cursor
21
25
  end
@@ -70,6 +74,7 @@ module CyberarmEngine
70
74
  else
71
75
  klass.new(path)
72
76
  end
77
+
73
78
  hash[path] = instance
74
79
  asset = instance
75
80
  end
@@ -17,6 +17,11 @@ module CyberarmEngine
17
17
  def setup
18
18
  end
19
19
 
20
+ # Called immediately after setup returns.
21
+ # GuiState uses this to set current_theme for ToolTip
22
+ def post_setup
23
+ end
24
+
20
25
  def draw
21
26
  @game_objects.each(&:draw)
22
27
  end
@@ -54,7 +54,7 @@ module CyberarmEngine
54
54
  texture_id = tex_names_buf.unpack1("L2")
55
55
 
56
56
  glBindTexture(GL_TEXTURE_2D, texture_id)
57
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, array_of_pixels)
57
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA, image.width, image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, array_of_pixels)
58
58
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
59
59
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
60
60
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) if @retro
@@ -65,6 +65,15 @@ module CyberarmEngine
65
65
  font
66
66
  end
67
67
 
68
+ def swap_font(size, font_name = @font)
69
+ if @size != size || @font != font_name
70
+ @size = size
71
+ @font = font_name
72
+
73
+ @textobject = check_cache(size, font_name)
74
+ end
75
+ end
76
+
68
77
  def text=(string)
69
78
  @rendered_shadow = nil
70
79
  @text = string
@@ -140,6 +149,7 @@ module CyberarmEngine
140
149
  @textobject.send(method, @text, _x + @shadow_size, _y, @z, @factor_x, @factor_y, white, :add)
141
150
  @textobject.send(method, @text, _x + @shadow_size, _y + @shadow_size, @z, @factor_x, @factor_y, white, :add)
142
151
  end
152
+
143
153
  @rendered_shadow.draw(@x - @shadow_size, @y - @shadow_size, @z, @factor_x, @factor_y, shadow_color)
144
154
  end
145
155
 
@@ -23,7 +23,8 @@ module CyberarmEngine
23
23
  "Tagline",
24
24
  "Caption",
25
25
  "Para",
26
- "Inscription"
26
+ "Inscription",
27
+ "Link"
27
28
  ].each do |const|
28
29
  define_method(:"#{const.downcase}") do |text, options = {}, &block|
29
30
  options[:parent] = element_parent
@@ -97,7 +98,7 @@ module CyberarmEngine
97
98
  end
98
99
 
99
100
  def background(color = Gosu::Color::NONE)
100
- element_parent.style.background = color
101
+ element_parent.style.default[:background] = color
101
102
  end
102
103
 
103
104
  def theme(theme)
@@ -18,6 +18,8 @@ module CyberarmEngine
18
18
  @visible = @options[:visible].nil? ? true : @options[:visible]
19
19
  @tip = @options[:tip] || ""
20
20
 
21
+ @debug_color = @options[:debug_color].nil? ? Gosu::Color::RED : @options[:debug_color]
22
+
21
23
  @style = Style.new(options)
22
24
 
23
25
  @root ||= nil
@@ -36,6 +38,8 @@ module CyberarmEngine
36
38
  @style.background_canvas = Background.new
37
39
  @style.border_canvas = BorderCanvas.new(element: self)
38
40
 
41
+ @style_event = :default
42
+
39
43
  stylize
40
44
 
41
45
  default_events
@@ -45,14 +49,18 @@ module CyberarmEngine
45
49
 
46
50
  def stylize
47
51
  set_static_position
48
- set_border_thickness(@style.border_thickness)
49
52
 
50
- set_padding(@style.padding)
53
+ set_padding
54
+ set_margin
51
55
 
52
- set_margin(@style.margin)
56
+ set_background
57
+
58
+ set_border_thickness
59
+ set_border_color
60
+ end
53
61
 
54
- set_background(@style.background)
55
- set_border_color(@style.border_color)
62
+ def safe_style_fetch(*args)
63
+ @style.hash.dig(@style_event, *args) || @style.hash.dig(:default, *args) || default(*args)
56
64
  end
57
65
 
58
66
  def set_static_position
@@ -60,47 +68,65 @@ module CyberarmEngine
60
68
  @y = @style.y if @style.y != 0
61
69
  end
62
70
 
63
- def set_background(background)
64
- @style.background = background
65
- @style.background_canvas.background = background
71
+ def set_background
72
+ @style.background = safe_style_fetch(:background)
73
+
74
+ @style.background_canvas.background = @style.background
66
75
  end
67
76
 
68
- def set_border_thickness(border_thickness)
69
- @style.border_thickness = border_thickness
77
+ def set_border_thickness
78
+ @style.border_thickness = safe_style_fetch(:border_thickness)
70
79
 
71
- @style.border_thickness_left = default(:border_thickness_left) || @style.border_thickness
72
- @style.border_thickness_right = default(:border_thickness_right) || @style.border_thickness
73
- @style.border_thickness_top = default(:border_thickness_top) || @style.border_thickness
74
- @style.border_thickness_bottom = default(:border_thickness_bottom) || @style.border_thickness
80
+ @style.border_thickness_left = safe_style_fetch(:border_thickness_left) || @style.border_thickness
81
+ @style.border_thickness_right = safe_style_fetch(:border_thickness_right) || @style.border_thickness
82
+ @style.border_thickness_top = safe_style_fetch(:border_thickness_top) || @style.border_thickness
83
+ @style.border_thickness_bottom = safe_style_fetch(:border_thickness_bottom) || @style.border_thickness
75
84
  end
76
85
 
77
- def set_border_color(color)
78
- @style.border_color = color
86
+ def set_border_color
87
+ @style.border_color = safe_style_fetch(:border_color)
79
88
 
80
- @style.border_color_left = default(:border_color_left) || @style.border_color
81
- @style.border_color_right = default(:border_color_right) || @style.border_color
82
- @style.border_color_top = default(:border_color_top) || @style.border_color
83
- @style.border_color_bottom = default(:border_color_bottom) || @style.border_color
89
+ @style.border_color_left = safe_style_fetch(:border_color_left) || @style.border_color
90
+ @style.border_color_right = safe_style_fetch(:border_color_right) || @style.border_color
91
+ @style.border_color_top = safe_style_fetch(:border_color_top) || @style.border_color
92
+ @style.border_color_bottom = safe_style_fetch(:border_color_bottom) || @style.border_color
84
93
 
85
- @style.border_canvas.color = color
94
+ @style.border_canvas.color = [
95
+ @style.border_color_top,
96
+ @style.border_color_right,
97
+ @style.border_color_bottom,
98
+ @style.border_color_left
99
+ ]
86
100
  end
87
101
 
88
- def set_padding(padding)
89
- @style.padding = padding
102
+ def set_padding
103
+ @style.padding = safe_style_fetch(:padding)
90
104
 
91
- @style.padding_left = default(:padding_left) || @style.padding
92
- @style.padding_right = default(:padding_right) || @style.padding
93
- @style.padding_top = default(:padding_top) || @style.padding
94
- @style.padding_bottom = default(:padding_bottom) || @style.padding
105
+ @style.padding_left = safe_style_fetch(:padding_left) || @style.padding
106
+ @style.padding_right = safe_style_fetch(:padding_right) || @style.padding
107
+ @style.padding_top = safe_style_fetch(:padding_top) || @style.padding
108
+ @style.padding_bottom = safe_style_fetch(:padding_bottom) || @style.padding
95
109
  end
96
110
 
97
- def set_margin(margin)
98
- @style.margin = margin
111
+ def set_margin
112
+ @style.margin = safe_style_fetch(:margin)
99
113
 
100
- @style.margin_left = default(:margin_left) || @style.margin
101
- @style.margin_right = default(:margin_right) || @style.margin
102
- @style.margin_top = default(:margin_top) || @style.margin
103
- @style.margin_bottom = default(:margin_bottom) || @style.margin
114
+ @style.margin_left = safe_style_fetch(:margin_left) || @style.margin
115
+ @style.margin_right = safe_style_fetch(:margin_right) || @style.margin
116
+ @style.margin_top = safe_style_fetch(:margin_top) || @style.margin
117
+ @style.margin_bottom = safe_style_fetch(:margin_bottom) || @style.margin
118
+ end
119
+
120
+ def update_styles(event = :default)
121
+ _style = @style.send(event)
122
+ @style_event = event
123
+
124
+ if @text.is_a?(CyberarmEngine::Text)
125
+ @text.color = _style&.dig(:color) || @style.default[:color]
126
+ @text.swap_font(_style&.dig(:text_size) || @style.default[:text_size], _style&.dig(:font) || @style.default[:font])
127
+ end
128
+
129
+ (root&.gui_state || @gui_state).request_recalculate
104
130
  end
105
131
 
106
132
  def default_events
@@ -124,6 +150,68 @@ module CyberarmEngine
124
150
  event(:changed)
125
151
  end
126
152
 
153
+ def enter(_sender)
154
+ @focus = false unless window.button_down?(Gosu::MsLeft)
155
+
156
+ if !@enabled
157
+ update_styles(:disabled)
158
+ elsif @focus
159
+ update_styles(:active)
160
+ else
161
+ update_styles(:hover)
162
+ end
163
+
164
+ :handled
165
+ end
166
+
167
+ def left_mouse_button(_sender, _x, _y)
168
+ @focus = true
169
+
170
+ unless @enabled
171
+ update_styles(:disabled)
172
+ else
173
+ update_styles(:active)
174
+ end
175
+
176
+ window.current_state.focus = self
177
+
178
+ :handled
179
+ end
180
+
181
+ def released_left_mouse_button(sender, _x, _y)
182
+ enter(sender)
183
+
184
+ :handled
185
+ end
186
+
187
+ def clicked_left_mouse_button(_sender, _x, _y)
188
+ @block&.call(self) if @enabled && !self.is_a?(Container)
189
+
190
+ :handled
191
+ end
192
+
193
+ def leave(_sender)
194
+ if @enabled
195
+ update_styles
196
+ else
197
+ update_styles(:disabled)
198
+ end
199
+
200
+ :handled
201
+ end
202
+
203
+ def blur(_sender)
204
+ @focus = false
205
+
206
+ if @enabled
207
+ update_styles
208
+ else
209
+ update_styles(:disabled)
210
+ end
211
+
212
+ :handled
213
+ end
214
+
127
215
  def enabled?
128
216
  @enabled
129
217
  end
@@ -160,6 +248,31 @@ module CyberarmEngine
160
248
  end
161
249
  end
162
250
 
251
+ def debug_draw
252
+ return if defined?(GUI_DEBUG_ONLY_ELEMENT) && self.class == GUI_DEBUG_ONLY_ELEMENT
253
+
254
+ Gosu.draw_line(
255
+ x, y, @debug_color,
256
+ x + outer_width, y, @debug_color,
257
+ Float::INFINITY
258
+ )
259
+ Gosu.draw_line(
260
+ x + outer_width, y, @debug_color,
261
+ x + outer_width, y + outer_height, @debug_color,
262
+ Float::INFINITY
263
+ )
264
+ Gosu.draw_line(
265
+ x + outer_width, y + outer_height, @debug_color,
266
+ x, y + outer_height, @debug_color,
267
+ Float::INFINITY
268
+ )
269
+ Gosu.draw_line(
270
+ x, outer_height, @debug_color,
271
+ x, y, @debug_color,
272
+ Float::INFINITY
273
+ )
274
+ end
275
+
163
276
  def update
164
277
  end
165
278
 
@@ -258,7 +371,7 @@ module CyberarmEngine
258
371
  end
259
372
 
260
373
  def background=(_background)
261
- @style.background_canvas.background = (_background)
374
+ @style.background_canvas.background = _background
262
375
  update_background
263
376
  end
264
377
 
@@ -281,11 +394,9 @@ module CyberarmEngine
281
394
  @root = parent
282
395
 
283
396
  loop do
284
- if @root.parent.nil?
285
- break
286
- else
287
- @root = @root.parent
288
- end
397
+ break unless @root&.parent
398
+
399
+ @root = @root.parent
289
400
  end
290
401
  end
291
402
 
@@ -34,69 +34,6 @@ module CyberarmEngine
34
34
  @text.draw
35
35
  end
36
36
 
37
- def enter(_sender)
38
- @focus = false unless window.button_down?(Gosu::MsLeft)
39
-
40
- if !@enabled
41
- @style.background_canvas.background = @style.disabled[:background]
42
- @text.color = @style.disabled[:color]
43
- elsif @focus
44
- @style.background_canvas.background = @style.active[:background]
45
- @text.color = @style.active[:color]
46
- else
47
- @style.background_canvas.background = @style.hover[:background]
48
- @text.color = @style.hover[:color]
49
- end
50
-
51
- :handled
52
- end
53
-
54
- def left_mouse_button(_sender, _x, _y)
55
- @focus = true
56
-
57
- unless @enabled
58
- @style.background_canvas.background = @style.disabled[:background]
59
- @text.color = @style.disabled[:color]
60
- else
61
- @style.background_canvas.background = @style.active[:background]
62
- @text.color = @style.active[:color]
63
- end
64
-
65
- window.current_state.focus = self
66
-
67
- :handled
68
- end
69
-
70
- def released_left_mouse_button(sender, _x, _y)
71
- enter(sender)
72
-
73
- :handled
74
- end
75
-
76
- def clicked_left_mouse_button(_sender, _x, _y)
77
- @block.call(self) if @enabled && @block
78
-
79
- :handled
80
- end
81
-
82
- def leave(_sender)
83
- unless @enabled
84
- @style.background_canvas.background = @style.disabled[:background]
85
- @text.color = @style.disabled[:color]
86
- else
87
- @style.background_canvas.background = @style.background
88
- @text.color = @style.color
89
- end
90
-
91
- :handled
92
- end
93
-
94
- def blur(_sender)
95
- @focus = false
96
-
97
- :handled
98
- end
99
-
100
37
  def recalculate
101
38
  unless @enabled
102
39
  @style.background_canvas.background = @style.disabled[:background]
@@ -5,8 +5,11 @@ module CyberarmEngine
5
5
  super(options, block)
6
6
  options[:toggled] = options[:checked]
7
7
 
8
+ options[:parent] = self
8
9
  @toggle_button = ToggleButton.new(options)
9
- @label = TextBlock.new(text, options)
10
+
11
+ options[:parent] = self
12
+ @label = TextBlock.new(text, options)
10
13
 
11
14
  @label.subscribe(:holding_left_mouse_button) do |sender, x, y|
12
15
  @toggle_button.left_mouse_button(sender, x, y)
@@ -60,30 +60,13 @@ module CyberarmEngine
60
60
  Gosu.clip_to(@x, @y, width, height) do
61
61
  @children.each(&:draw)
62
62
  end
63
+ end
64
+
65
+ def debug_draw
66
+ super
63
67
 
64
- if false # DEBUG
65
- Gosu.flush
66
-
67
- Gosu.draw_line(
68
- x, y, Gosu::Color::RED,
69
- x + outer_width, y, Gosu::Color::RED,
70
- Float::INFINITY
71
- )
72
- Gosu.draw_line(
73
- x + outer_width, y, Gosu::Color::RED,
74
- x + outer_width, y + outer_height, Gosu::Color::RED,
75
- Float::INFINITY
76
- )
77
- Gosu.draw_line(
78
- x + outer_width, y + outer_height, Gosu::Color::RED,
79
- x, y + outer_height, Gosu::Color::RED,
80
- Float::INFINITY
81
- )
82
- Gosu.draw_line(
83
- x, outer_height, Gosu::Color::RED,
84
- x, y, Gosu::Color::RED,
85
- Float::INFINITY
86
- )
68
+ @children.each do |child|
69
+ child.debug_draw
87
70
  end
88
71
  end
89
72
 
@@ -205,7 +188,6 @@ module CyberarmEngine
205
188
 
206
189
  def mouse_wheel_up(sender, x, y)
207
190
  return unless @style.scroll
208
- return if height < max_scroll_height
209
191
 
210
192
  if @scroll_position.y < 0
211
193
  @scroll_position.y += @scroll_speed
@@ -218,7 +200,8 @@ module CyberarmEngine
218
200
 
219
201
  def mouse_wheel_down(sender, x, y)
220
202
  return unless @style.scroll
221
- return if height < max_scroll_height
203
+
204
+ return unless height < scroll_height
222
205
 
223
206
  if @scroll_position.y.abs < max_scroll_height
224
207
  @scroll_position.y -= @scroll_speed
@@ -229,6 +212,21 @@ module CyberarmEngine
229
212
  end
230
213
  end
231
214
 
215
+ def scroll_top
216
+ @scroll_position.y
217
+ end
218
+
219
+ def scroll_top=(n)
220
+ n = 0 if n <= 0
221
+ @scroll_position.y = -n
222
+
223
+ if max_scroll_height.positive?
224
+ @scroll_position.y = -max_scroll_height if @scroll_position.y.abs > max_scroll_height
225
+ else
226
+ @scroll_position.y = 0
227
+ end
228
+ end
229
+
232
230
  def value
233
231
  @children.map { |c| c.class }.join(", ")
234
232
  end
@@ -59,6 +59,8 @@ module CyberarmEngine
59
59
  end
60
60
 
61
61
  def update
62
+ @style_event = :active if @focus
63
+
62
64
  @text.text = if @type == :password
63
65
  default(:password_character) * @text_input.text.length
64
66
  else
@@ -194,38 +196,27 @@ module CyberarmEngine
194
196
  :handled
195
197
  end
196
198
 
197
- def enter(_sender)
198
- if @focus
199
- @style.background_canvas.background = default(:active, :background)
200
- @text.color = default(:active, :color)
201
- else
202
- @style.background_canvas.background = default(:hover, :background)
203
- @text.color = default(:hover, :color)
204
- end
199
+ def focus(sender)
200
+ super
201
+
202
+ window.text_input = @text_input
203
+ @text_input.caret_pos = @text_input.selection_start = @text_input.text.length
205
204
 
206
205
  :handled
207
206
  end
208
207
 
209
- def leave(sender)
210
- super unless @focus
208
+ def enter(sender)
209
+ _has_focus = @focus
211
210
 
212
- :handled
213
- end
211
+ super
214
212
 
215
- def focus(sender)
216
- @focus = true
217
- @style.background_canvas.background = default(:active, :background)
218
- @text.color = default(:active, :color)
219
- window.text_input = @text_input
220
- @text_input.caret_pos = @text_input.selection_start = @text_input.text.length
213
+ @focus = _has_focus
221
214
 
222
215
  :handled
223
216
  end
224
217
 
225
218
  def blur(_sender)
226
- @focus = false
227
- @style.background_canvas.background = default(:background)
228
- @text.color = default(:color)
219
+ super
229
220
  window.text_input = nil
230
221
 
231
222
  :handled
@@ -18,12 +18,6 @@ module CyberarmEngine
18
18
  @text.draw
19
19
  end
20
20
 
21
- def clicked_left_mouse_button(_sender, _x, _y)
22
- @block&.call(self) if @enabled
23
-
24
- # return :handled
25
- end
26
-
27
21
  def recalculate
28
22
  @width = 0
29
23
  @height = 0
@@ -152,5 +146,8 @@ module CyberarmEngine
152
146
 
153
147
  class ToolTip < TextBlock
154
148
  end
149
+
150
+ class Link < TextBlock
151
+ end
155
152
  end
156
153
  end
@@ -26,12 +26,15 @@ module CyberarmEngine
26
26
  @dragging_element = nil
27
27
  @pending_recalculate_request = false
28
28
 
29
- @tip = Element::ToolTip.new("", parent: @root_container, z: Float::INFINITY)
30
29
  @menu = nil
31
30
  @min_drag_distance = 0
32
31
  @mouse_pos = Vector.new
33
32
  end
34
33
 
34
+ def post_setup
35
+ @tip = Element::ToolTip.new("", parent: @root_container, z: Float::INFINITY, theme: current_theme)
36
+ end
37
+
35
38
  # throws :blur event to focused element and sets GuiState focused element
36
39
  # Does NOT throw :focus event at element or set element as focused
37
40
  def focus=(element)
@@ -55,6 +58,12 @@ module CyberarmEngine
55
58
  Gosu.flush
56
59
  @tip.draw
57
60
  end
61
+
62
+ if defined?(GUI_DEBUG)
63
+ Gosu.flush
64
+
65
+ @root_container.debug_draw
66
+ end
58
67
  end
59
68
 
60
69
  def update
@@ -97,7 +106,7 @@ module CyberarmEngine
97
106
  @tip.x = window.mouse_x - @tip.width / 2
98
107
  @tip.x = 0 if @tip.x < 0
99
108
  @tip.x = window.width - @tip.width if @tip.x + @tip.width > window.width
100
- @tip.y = window.mouse_y - @tip.height
109
+ @tip.y = window.mouse_y - (@tip.height + 5)
101
110
  @tip.y = 0 if @tip.y < 0
102
111
  @tip.y = window.height - @tip.height if @tip.y + @tip.height > window.height
103
112
  @tip.update
@@ -17,8 +17,20 @@ end
17
17
 
18
18
  module CyberarmEngine
19
19
  class Style
20
+ attr_reader :hash
21
+
20
22
  def initialize(hash = {})
21
- @hash = Marshal.load(Marshal.dump(hash))
23
+ h = Marshal.load(Marshal.dump(hash))
24
+
25
+ h[:default] = {}
26
+
27
+ h.each do |key, value|
28
+ next if value.is_a?(Hash)
29
+
30
+ h[:default][key] = value
31
+ end
32
+
33
+ @hash = h
22
34
  end
23
35
 
24
36
  def method_missing(method, *args)
@@ -27,9 +39,8 @@ module CyberarmEngine
27
39
 
28
40
  @hash[method.to_s.sub("=", "").to_sym] = args.first
29
41
 
30
- elsif args.size == 0
42
+ elsif args.empty?
31
43
  @hash[method]
32
-
33
44
  else
34
45
  raise ArgumentError, "Did not expect arguments"
35
46
  end
@@ -64,6 +64,10 @@ module CyberarmEngine
64
64
  border_radius: 0
65
65
  },
66
66
 
67
+ Container: { # < Element (Base class for Stack and Flow)
68
+ debug_color: Gosu::Color::YELLOW
69
+ },
70
+
67
71
  Button: { # < Label
68
72
  margin: 1,
69
73
  padding: 4,
@@ -155,11 +159,28 @@ module CyberarmEngine
155
159
  border_color: 0xffaaaaaa,
156
160
  background: 0xff404040
157
161
  },
162
+ Link: { # < TextBlock
163
+ color: Gosu::Color::BLUE,
164
+ border_thickness: 1,
165
+ border_bottom_color: Gosu::Color::BLUE,
166
+ hover: {
167
+ color: 0xff_ff00ff,
168
+ border_bottom_color: 0xff_ff00ff
169
+ },
170
+ active: {
171
+ color: 0xff_ff0000,
172
+ border_bottom_color: 0xff_ff0000
173
+ }
174
+ },
158
175
 
159
176
  ToggleButton: { # < Button
160
177
  checkmark: "√"
161
178
  },
162
179
 
180
+ CheckBox: { # < Flow
181
+ text_wrap: :none
182
+ },
183
+
163
184
  Progress: { # < Element
164
185
  width: 250,
165
186
  height: 36,
@@ -1,4 +1,4 @@
1
1
  module CyberarmEngine
2
2
  NAME = "InDev".freeze
3
- VERSION = "0.17.1".freeze
3
+ VERSION = "0.18.0".freeze
4
4
  end
@@ -77,10 +77,12 @@ module CyberarmEngine
77
77
  if klass.instance_of?(klass.class) && defined?(klass.options)
78
78
  @states << klass
79
79
  klass.setup if options[:setup]
80
+ klass.post_setup if options[:setup]
80
81
  else
81
82
  @states << klass.new(options) if child_of?(klass, GameState)
82
83
  @states << klass.new if child_of?(klass, Element::Container)
83
84
  current_state.setup if current_state.instance_of?(klass) && options[:setup]
85
+ current_state.post_setup if current_state.instance_of?(klass) && options[:setup]
84
86
  end
85
87
  end
86
88
 
@@ -93,7 +95,7 @@ module CyberarmEngine
93
95
  end
94
96
 
95
97
  def previous_state
96
- if @states.size > 1 && state = @states[@states.size - 2]
98
+ if @states.size > 1 && (state = @states[@states.size - 2])
97
99
  state
98
100
  end
99
101
  end
@@ -102,6 +104,10 @@ module CyberarmEngine
102
104
  @states.pop
103
105
  end
104
106
 
107
+ def shift_state
108
+ @states.shift
109
+ end
110
+
105
111
  # Sourced from https://gist.github.com/ippa/662583
106
112
  def draw_circle(cx, cy, r, z = 9999, color = Gosu::Color::GREEN, step = 10)
107
113
  0.step(360, step) do |a1|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cyberarm_engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.1
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyberarm
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-11 00:00:00.000000000 Z
11
+ date: 2021-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -123,6 +123,7 @@ files:
123
123
  - README.md
124
124
  - Rakefile
125
125
  - assets/textures/default.png
126
+ - assets/textures/logo.png
126
127
  - bin/console
127
128
  - bin/setup
128
129
  - cyberarm_engine.gemspec
@@ -131,6 +132,7 @@ files:
131
132
  - lib/cyberarm_engine/background.rb
132
133
  - lib/cyberarm_engine/background_nine_slice.rb
133
134
  - lib/cyberarm_engine/bounding_box.rb
135
+ - lib/cyberarm_engine/builtin/intro_state.rb
134
136
  - lib/cyberarm_engine/cache.rb
135
137
  - lib/cyberarm_engine/cache/download_manager.rb
136
138
  - lib/cyberarm_engine/common.rb
@@ -169,7 +171,6 @@ files:
169
171
  - lib/cyberarm_engine/ui/elements/edit_line.rb
170
172
  - lib/cyberarm_engine/ui/elements/flow.rb
171
173
  - lib/cyberarm_engine/ui/elements/image.rb
172
- - lib/cyberarm_engine/ui/elements/label.rb
173
174
  - lib/cyberarm_engine/ui/elements/list_box.rb
174
175
  - lib/cyberarm_engine/ui/elements/progress.rb
175
176
  - lib/cyberarm_engine/ui/elements/radio.rb
@@ -1,156 +0,0 @@
1
- module CyberarmEngine
2
- class Element
3
- class TextBlock < Element
4
- def initialize(text, options = {}, block = nil)
5
- super(options, block)
6
-
7
- @text = Text.new(
8
- text, font: @options[:font], z: @z, color: @options[:color],
9
- size: @options[:text_size], shadow: @options[:text_shadow],
10
- shadow_size: @options[:text_shadow_size],
11
- shadow_color: @options[:text_shadow_color]
12
- )
13
-
14
- @raw_text = text
15
- end
16
-
17
- def render
18
- @text.draw
19
- end
20
-
21
- def clicked_left_mouse_button(_sender, _x, _y)
22
- @block&.call(self) if @enabled
23
-
24
- # return :handled
25
- end
26
-
27
- def recalculate
28
- @width = 0
29
- @height = 0
30
-
31
- _width = dimensional_size(@style.width, :width)
32
- _height = dimensional_size(@style.height, :height)
33
-
34
- handle_text_wrapping(_width)
35
-
36
- @width = _width || @text.width.round
37
- @height = _height || @text.height.round
38
-
39
- @text.y = @style.border_thickness_top + @style.padding_top + @y
40
- @text.z = @z + 3
41
-
42
- if (text_alignment = @options[:text_align])
43
- case text_alignment
44
- when :left
45
- @text.x = @style.border_thickness_left + @style.padding_left + @x
46
- when :center
47
- @text.x = if @text.width <= outer_width
48
- @x + outer_width / 2 - @text.width / 2
49
- else # Act as left aligned
50
- @style.border_thickness_left + @style.padding_left + @x
51
- end
52
- when :right
53
- @text.x = @x + outer_width - (@text.width + @style.border_thickness_right + @style.padding_right)
54
- end
55
- end
56
-
57
- update_background
58
- end
59
-
60
- def handle_text_wrapping(max_width)
61
- max_width ||= @parent&.width
62
- max_width ||= @x - (window.width + noncontent_width)
63
- wrap_behavior = style.text_wrap
64
- copy = @raw_text.to_s.dup
65
-
66
- if max_width >= line_width(copy[0]) && line_width(copy) > max_width && wrap_behavior != :none
67
- breaks = []
68
- line_start = 0
69
- line_end = copy.length
70
-
71
- while line_start != copy.length
72
- if line_width(copy[line_start...line_end]) > max_width
73
- line_end = ((line_end - line_start) / 2.0)
74
- elsif line_end < copy.length && line_width(copy[line_start...line_end + 1]) < max_width
75
- # To small, grow!
76
- # TODO: find a more efficient way
77
- line_end += 1
78
-
79
- else # FOUND IT!
80
- entering_line_end = line_end.floor
81
- max_reach = line_end.floor - line_start < 63 ? line_end.floor - line_start : 63
82
- reach = 0
83
-
84
- if wrap_behavior == :word_wrap
85
- max_reach.times do |i|
86
- reach = i
87
- break if copy[line_end.floor - i].to_s.match(/[[:punct:]]| /)
88
- end
89
-
90
- 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]}}"
91
- line_end = line_end.floor - reach + 1 if reach != max_reach # Add +1 to walk in front of punctuation
92
- end
93
-
94
- breaks << line_end.floor
95
- line_start = line_end.floor
96
- line_end = copy.length
97
-
98
- break if entering_line_end == copy.length || reach == max_reach
99
- end
100
- end
101
-
102
- breaks.each_with_index do |pos, index|
103
- copy.insert(pos + index, "\n") if pos + index >= 0 && pos + index < copy.length
104
- end
105
- end
106
-
107
- @text.text = copy
108
- end
109
-
110
- def line_width(text)
111
- (@x + @text.textobject.markup_width(text) + noncontent_width)
112
- end
113
-
114
- def value
115
- @raw_text
116
- end
117
-
118
- def value=(value)
119
- @raw_text = value.to_s.chomp
120
-
121
- old_width = width
122
- old_height = height
123
- recalculate
124
-
125
- root.gui_state.request_recalculate if old_width != width || old_height != height
126
-
127
- publish(:changed, self.value)
128
- end
129
- end
130
-
131
- class Banner < TextBlock
132
- end
133
-
134
- class Title < TextBlock
135
- end
136
-
137
- class Subtitle < TextBlock
138
- end
139
-
140
- class Tagline < TextBlock
141
- end
142
-
143
- class Caption < TextBlock
144
- end
145
-
146
- class Para < TextBlock
147
- end
148
-
149
- class Inscription < TextBlock
150
- end
151
-
152
- # TODO: Remove in version 0.16.0+
153
- class Label < TextBlock
154
- end
155
- end
156
- end