cyberarm_engine 0.19.0 → 0.19.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -8
  3. data/.rubocop.yml +7 -7
  4. data/.travis.yml +5 -5
  5. data/Gemfile +6 -6
  6. data/LICENSE.txt +21 -21
  7. data/README.md +74 -74
  8. data/Rakefile +10 -10
  9. data/bin/console +14 -14
  10. data/bin/setup +8 -8
  11. data/cyberarm_engine.gemspec +39 -39
  12. data/lib/cyberarm_engine/animator.rb +219 -219
  13. data/lib/cyberarm_engine/background.rb +179 -179
  14. data/lib/cyberarm_engine/background_nine_slice.rb +142 -142
  15. data/lib/cyberarm_engine/bounding_box.rb +150 -150
  16. data/lib/cyberarm_engine/builtin/intro_state.rb +130 -130
  17. data/lib/cyberarm_engine/cache/download_manager.rb +121 -121
  18. data/lib/cyberarm_engine/cache.rb +4 -4
  19. data/lib/cyberarm_engine/common.rb +113 -113
  20. data/lib/cyberarm_engine/config_file.rb +46 -46
  21. data/lib/cyberarm_engine/console/command.rb +157 -157
  22. data/lib/cyberarm_engine/console/commands/help_command.rb +43 -43
  23. data/lib/cyberarm_engine/console/subcommand.rb +99 -99
  24. data/lib/cyberarm_engine/console.rb +248 -248
  25. data/lib/cyberarm_engine/game_object.rb +248 -248
  26. data/lib/cyberarm_engine/game_state.rb +97 -97
  27. data/lib/cyberarm_engine/model/material.rb +21 -21
  28. data/lib/cyberarm_engine/model/model_object.rb +131 -131
  29. data/lib/cyberarm_engine/model/parser.rb +74 -74
  30. data/lib/cyberarm_engine/model/parsers/collada_parser.rb +138 -138
  31. data/lib/cyberarm_engine/model/parsers/wavefront_parser.rb +154 -154
  32. data/lib/cyberarm_engine/model.rb +212 -212
  33. data/lib/cyberarm_engine/model_cache.rb +31 -31
  34. data/lib/cyberarm_engine/opengl/light.rb +50 -50
  35. data/lib/cyberarm_engine/opengl/orthographic_camera.rb +46 -46
  36. data/lib/cyberarm_engine/opengl/perspective_camera.rb +38 -38
  37. data/lib/cyberarm_engine/opengl/renderer/bounding_box_renderer.rb +249 -249
  38. data/lib/cyberarm_engine/opengl/renderer/g_buffer.rb +164 -164
  39. data/lib/cyberarm_engine/opengl/renderer/opengl_renderer.rb +298 -298
  40. data/lib/cyberarm_engine/opengl/renderer/renderer.rb +22 -22
  41. data/lib/cyberarm_engine/opengl/shader.rb +406 -406
  42. data/lib/cyberarm_engine/opengl/texture.rb +69 -69
  43. data/lib/cyberarm_engine/opengl.rb +28 -28
  44. data/lib/cyberarm_engine/ray.rb +56 -56
  45. data/lib/cyberarm_engine/stats.rb +21 -21
  46. data/lib/cyberarm_engine/text.rb +197 -197
  47. data/lib/cyberarm_engine/timer.rb +23 -23
  48. data/lib/cyberarm_engine/transform.rb +296 -296
  49. data/lib/cyberarm_engine/ui/border_canvas.rb +102 -102
  50. data/lib/cyberarm_engine/ui/dsl.rb +139 -139
  51. data/lib/cyberarm_engine/ui/element.rb +488 -488
  52. data/lib/cyberarm_engine/ui/elements/button.rb +97 -97
  53. data/lib/cyberarm_engine/ui/elements/check_box.rb +54 -54
  54. data/lib/cyberarm_engine/ui/elements/container.rb +256 -256
  55. data/lib/cyberarm_engine/ui/elements/edit_box.rb +179 -179
  56. data/lib/cyberarm_engine/ui/elements/edit_line.rb +263 -263
  57. data/lib/cyberarm_engine/ui/elements/flow.rb +15 -15
  58. data/lib/cyberarm_engine/ui/elements/image.rb +72 -72
  59. data/lib/cyberarm_engine/ui/elements/list_box.rb +88 -82
  60. data/lib/cyberarm_engine/ui/elements/progress.rb +51 -51
  61. data/lib/cyberarm_engine/ui/elements/radio.rb +6 -6
  62. data/lib/cyberarm_engine/ui/elements/slider.rb +104 -104
  63. data/lib/cyberarm_engine/ui/elements/stack.rb +11 -11
  64. data/lib/cyberarm_engine/ui/elements/text_block.rb +162 -162
  65. data/lib/cyberarm_engine/ui/elements/toggle_button.rb +65 -65
  66. data/lib/cyberarm_engine/ui/event.rb +54 -54
  67. data/lib/cyberarm_engine/ui/gui_state.rb +256 -256
  68. data/lib/cyberarm_engine/ui/style.rb +49 -49
  69. data/lib/cyberarm_engine/ui/theme.rb +207 -207
  70. data/lib/cyberarm_engine/vector.rb +293 -293
  71. data/lib/cyberarm_engine/version.rb +4 -4
  72. data/lib/cyberarm_engine/window.rb +120 -120
  73. data/lib/cyberarm_engine.rb +71 -71
  74. metadata +3 -3
@@ -1,256 +1,256 @@
1
- module CyberarmEngine
2
- class GuiState < GameState
3
- include Common
4
- include DSL
5
-
6
- def initialize(options = {})
7
- @options = options
8
- @game_objects = []
9
- @global_pause = false
10
-
11
- @down_keys = {}
12
-
13
- @root_container = Element::Stack.new(gui_state: self)
14
- @game_objects << @root_container
15
- $__current_container__ = @root_container
16
-
17
- @active_width = window.width
18
- @active_height = window.height
19
-
20
- @menu = nil
21
- @focus = nil
22
- @mouse_over = nil
23
- @mouse_down_on = {}
24
- @mouse_down_position = {}
25
- @last_mouse_pos = nil
26
- @dragging_element = nil
27
- @pending_recalculate_request = false
28
-
29
- @menu = nil
30
- @min_drag_distance = 0
31
- @mouse_pos = Vector.new
32
- end
33
-
34
- def post_setup
35
- @tip = Element::ToolTip.new("", parent: @root_container, z: Float::INFINITY, theme: current_theme)
36
- end
37
-
38
- # throws :blur event to focused element and sets GuiState focused element
39
- # Does NOT throw :focus event at element or set element as focused
40
- def focus=(element)
41
- @focus.publish(:blur) if @focus && element && @focus != element
42
- @focus = element
43
- end
44
-
45
- def focused
46
- @focus
47
- end
48
-
49
- def draw
50
- super
51
-
52
- if @menu
53
- Gosu.flush
54
- @menu.draw
55
- end
56
-
57
- if @tip.value.length.positive?
58
- Gosu.flush
59
- @tip.draw
60
- end
61
-
62
- if defined?(GUI_DEBUG)
63
- Gosu.flush
64
-
65
- @root_container.debug_draw
66
- end
67
- end
68
-
69
- def update
70
- if @pending_recalculate_request
71
- @root_container.recalculate
72
- @root_container.recalculate
73
- @root_container.recalculate
74
-
75
- @pending_recalculate_request = false
76
- end
77
-
78
- if @pending_focus_request
79
- @pending_focus_request = false
80
-
81
- self.focus = @pending_focus_element
82
- @pending_focus_element.publish(:focus)
83
- end
84
-
85
- @menu&.update
86
- super
87
-
88
- new_mouse_over = @menu.hit_element?(window.mouse_x, window.mouse_y) if @menu
89
- new_mouse_over ||= @root_container.hit_element?(window.mouse_x, window.mouse_y)
90
-
91
- if new_mouse_over
92
- new_mouse_over.publish(:enter) if new_mouse_over != @mouse_over
93
- new_mouse_over.publish(:hover)
94
- # puts "#{new_mouse_over.class}[#{new_mouse_over.value}]: #{new_mouse_over.x}:#{new_mouse_over.y} #{new_mouse_over.width}:#{new_mouse_over.height}" if new_mouse_over != @mouse_over
95
- end
96
- @mouse_over.publish(:leave) if @mouse_over && new_mouse_over != @mouse_over
97
- @mouse_over = new_mouse_over
98
-
99
- redirect_holding_mouse_button(:left) if @mouse_over && Gosu.button_down?(Gosu::MsLeft)
100
- redirect_holding_mouse_button(:middle) if @mouse_over && Gosu.button_down?(Gosu::MsMiddle)
101
- redirect_holding_mouse_button(:right) if @mouse_over && Gosu.button_down?(Gosu::MsRight)
102
-
103
- if Vector.new(window.mouse_x, window.mouse_y) == @last_mouse_pos
104
- if @mouse_over && (Gosu.milliseconds - @mouse_moved_at) > tool_tip_delay
105
- @tip.value = @mouse_over.tip if @mouse_over
106
- @tip.x = window.mouse_x
107
- @tip.x = 0 if @tip.x < 0
108
- @tip.x = window.width - @tip.width if @tip.x + @tip.width > window.width
109
- @tip.y = window.mouse_y - (@tip.height + 5)
110
- @tip.y = 0 if @tip.y < 0
111
- @tip.y = window.height - @tip.height if @tip.y + @tip.height > window.height
112
- @tip.update
113
- @tip.recalculate
114
- else
115
- @tip.value = ""
116
- end
117
- else
118
- @mouse_moved_at = Gosu.milliseconds
119
- end
120
-
121
- @last_mouse_pos = Vector.new(window.mouse_x, window.mouse_y)
122
- @mouse_pos = @last_mouse_pos.clone
123
-
124
- if @active_width != window.width || @active_height != window.height
125
- request_recalculate
126
- @root_container.publish(:window_size_changed)
127
- end
128
-
129
- @active_width = window.width
130
- @active_height = window.height
131
- end
132
-
133
- def tool_tip_delay
134
- 250 # ms
135
- end
136
-
137
- def button_down(id)
138
- super
139
-
140
- case id
141
- when Gosu::MsLeft
142
- redirect_mouse_button(:left)
143
- when Gosu::MsMiddle
144
- redirect_mouse_button(:middle)
145
- when Gosu::MsRight
146
- redirect_mouse_button(:right)
147
- when Gosu::KbF5
148
- request_recalculate
149
- end
150
-
151
- @focus.button_down(id) if @focus.respond_to?(:button_down)
152
- end
153
-
154
- def button_up(id)
155
- super
156
-
157
- case id
158
- when Gosu::MsLeft
159
- redirect_released_mouse_button(:left)
160
- when Gosu::MsMiddle
161
- redirect_released_mouse_button(:middle)
162
- when Gosu::MsRight
163
- redirect_released_mouse_button(:right)
164
- when Gosu::MsWheelUp
165
- redirect_mouse_wheel(:up)
166
- when Gosu::MsWheelDown
167
- redirect_mouse_wheel(:down)
168
- end
169
-
170
- @focus.button_up(id) if @focus.respond_to?(:button_up)
171
- end
172
-
173
- def redirect_mouse_button(button)
174
- hide_menu unless @menu && (@menu == @mouse_over) || (@mouse_over&.parent == @menu)
175
-
176
- if @focus && @mouse_over != @focus
177
- @focus.publish(:blur)
178
- @focus = nil
179
- end
180
-
181
- if @mouse_over
182
- @mouse_down_position[button] = Vector.new(window.mouse_x, window.mouse_y)
183
- @mouse_down_on[button] = @mouse_over
184
-
185
- @mouse_over.publish(:"#{button}_mouse_button", window.mouse_x, window.mouse_y)
186
- else
187
- @mouse_down_position[button] = nil
188
- @mouse_down_on[button] = nil
189
- end
190
- end
191
-
192
- def redirect_released_mouse_button(button)
193
- hide_menu if @menu && (@menu == @mouse_over) || (@mouse_over&.parent == @menu)
194
-
195
- if @mouse_over
196
- @mouse_over.publish(:"released_#{button}_mouse_button", window.mouse_x, window.mouse_y)
197
- if @mouse_over == @mouse_down_on[button]
198
- @mouse_over.publish(:"clicked_#{button}_mouse_button", window.mouse_x,
199
- window.mouse_y)
200
- end
201
- end
202
-
203
- if @dragging_element
204
- @dragging_element.publish(:end_drag, window.mouse_x, window.mouse_y, button)
205
- @dragging_element = nil
206
- end
207
-
208
- @mouse_down_position[button] = nil
209
- @mouse_down_on[button] = nil
210
- end
211
-
212
- def redirect_holding_mouse_button(button)
213
- if !@dragging_element && @mouse_down_on[button] && @mouse_down_on[button].draggable?(button) && @mouse_pos.distance(@mouse_down_position[button]) > @min_drag_distance
214
- @dragging_element = @mouse_down_on[button]
215
- @dragging_element.publish(:begin_drag, window.mouse_x, window.mouse_y, button)
216
- end
217
-
218
- if @dragging_element
219
- @dragging_element.publish(:drag_update, window.mouse_x, window.mouse_y, button) if @dragging_element
220
- elsif @mouse_over
221
- @mouse_over.publish(:"holding_#{button}_mouse_button", window.mouse_x, window.mouse_y)
222
- end
223
- end
224
-
225
- def redirect_mouse_wheel(button)
226
- @mouse_over.publish(:"mouse_wheel_#{button}", window.mouse_x, window.mouse_y) if @mouse_over
227
- end
228
-
229
- # Schedule a full GUI recalculation on next update
230
- def request_recalculate
231
- @pending_recalculate_request = true
232
- end
233
-
234
- def request_focus(element)
235
- @pending_focus_request = true
236
- @pending_focus_element = element
237
- end
238
-
239
- def show_menu(list_box)
240
- @menu = list_box
241
- end
242
-
243
- def hide_menu
244
- @menu = nil
245
- end
246
-
247
- def to_s
248
- # "#{self.class} children=#{@children.map { |c| c.to_s }}"
249
- @root_container.to_s
250
- end
251
-
252
- def inspect
253
- to_s
254
- end
255
- end
256
- end
1
+ module CyberarmEngine
2
+ class GuiState < GameState
3
+ include Common
4
+ include DSL
5
+
6
+ def initialize(options = {})
7
+ @options = options
8
+ @game_objects = []
9
+ @global_pause = false
10
+
11
+ @down_keys = {}
12
+
13
+ @root_container = Element::Stack.new(gui_state: self)
14
+ @game_objects << @root_container
15
+ $__current_container__ = @root_container
16
+
17
+ @active_width = window.width
18
+ @active_height = window.height
19
+
20
+ @menu = nil
21
+ @focus = nil
22
+ @mouse_over = nil
23
+ @mouse_down_on = {}
24
+ @mouse_down_position = {}
25
+ @last_mouse_pos = nil
26
+ @dragging_element = nil
27
+ @pending_recalculate_request = false
28
+
29
+ @menu = nil
30
+ @min_drag_distance = 0
31
+ @mouse_pos = Vector.new
32
+ end
33
+
34
+ def post_setup
35
+ @tip = Element::ToolTip.new("", parent: @root_container, z: Float::INFINITY, theme: current_theme)
36
+ end
37
+
38
+ # throws :blur event to focused element and sets GuiState focused element
39
+ # Does NOT throw :focus event at element or set element as focused
40
+ def focus=(element)
41
+ @focus.publish(:blur) if @focus && element && @focus != element
42
+ @focus = element
43
+ end
44
+
45
+ def focused
46
+ @focus
47
+ end
48
+
49
+ def draw
50
+ super
51
+
52
+ if @menu
53
+ Gosu.flush
54
+ @menu.draw
55
+ end
56
+
57
+ if @tip.value.length.positive?
58
+ Gosu.flush
59
+ @tip.draw
60
+ end
61
+
62
+ if defined?(GUI_DEBUG)
63
+ Gosu.flush
64
+
65
+ @root_container.debug_draw
66
+ end
67
+ end
68
+
69
+ def update
70
+ if @pending_recalculate_request
71
+ @root_container.recalculate
72
+ @root_container.recalculate
73
+ @root_container.recalculate
74
+
75
+ @pending_recalculate_request = false
76
+ end
77
+
78
+ if @pending_focus_request
79
+ @pending_focus_request = false
80
+
81
+ self.focus = @pending_focus_element
82
+ @pending_focus_element.publish(:focus)
83
+ end
84
+
85
+ @menu&.update
86
+ super
87
+
88
+ new_mouse_over = @menu.hit_element?(window.mouse_x, window.mouse_y) if @menu
89
+ new_mouse_over ||= @root_container.hit_element?(window.mouse_x, window.mouse_y)
90
+
91
+ if new_mouse_over
92
+ new_mouse_over.publish(:enter) if new_mouse_over != @mouse_over
93
+ new_mouse_over.publish(:hover)
94
+ # puts "#{new_mouse_over.class}[#{new_mouse_over.value}]: #{new_mouse_over.x}:#{new_mouse_over.y} #{new_mouse_over.width}:#{new_mouse_over.height}" if new_mouse_over != @mouse_over
95
+ end
96
+ @mouse_over.publish(:leave) if @mouse_over && new_mouse_over != @mouse_over
97
+ @mouse_over = new_mouse_over
98
+
99
+ redirect_holding_mouse_button(:left) if @mouse_over && Gosu.button_down?(Gosu::MsLeft)
100
+ redirect_holding_mouse_button(:middle) if @mouse_over && Gosu.button_down?(Gosu::MsMiddle)
101
+ redirect_holding_mouse_button(:right) if @mouse_over && Gosu.button_down?(Gosu::MsRight)
102
+
103
+ if Vector.new(window.mouse_x, window.mouse_y) == @last_mouse_pos
104
+ if @mouse_over && (Gosu.milliseconds - @mouse_moved_at) > tool_tip_delay
105
+ @tip.value = @mouse_over.tip if @mouse_over
106
+ @tip.x = window.mouse_x
107
+ @tip.x = 0 if @tip.x < 0
108
+ @tip.x = window.width - @tip.width if @tip.x + @tip.width > window.width
109
+ @tip.y = window.mouse_y - (@tip.height + 5)
110
+ @tip.y = 0 if @tip.y < 0
111
+ @tip.y = window.height - @tip.height if @tip.y + @tip.height > window.height
112
+ @tip.update
113
+ @tip.recalculate
114
+ else
115
+ @tip.value = ""
116
+ end
117
+ else
118
+ @mouse_moved_at = Gosu.milliseconds
119
+ end
120
+
121
+ @last_mouse_pos = Vector.new(window.mouse_x, window.mouse_y)
122
+ @mouse_pos = @last_mouse_pos.clone
123
+
124
+ if @active_width != window.width || @active_height != window.height
125
+ request_recalculate
126
+ @root_container.publish(:window_size_changed)
127
+ end
128
+
129
+ @active_width = window.width
130
+ @active_height = window.height
131
+ end
132
+
133
+ def tool_tip_delay
134
+ 250 # ms
135
+ end
136
+
137
+ def button_down(id)
138
+ super
139
+
140
+ case id
141
+ when Gosu::MsLeft
142
+ redirect_mouse_button(:left)
143
+ when Gosu::MsMiddle
144
+ redirect_mouse_button(:middle)
145
+ when Gosu::MsRight
146
+ redirect_mouse_button(:right)
147
+ when Gosu::KbF5
148
+ request_recalculate
149
+ end
150
+
151
+ @focus.button_down(id) if @focus.respond_to?(:button_down)
152
+ end
153
+
154
+ def button_up(id)
155
+ super
156
+
157
+ case id
158
+ when Gosu::MsLeft
159
+ redirect_released_mouse_button(:left)
160
+ when Gosu::MsMiddle
161
+ redirect_released_mouse_button(:middle)
162
+ when Gosu::MsRight
163
+ redirect_released_mouse_button(:right)
164
+ when Gosu::MsWheelUp
165
+ redirect_mouse_wheel(:up)
166
+ when Gosu::MsWheelDown
167
+ redirect_mouse_wheel(:down)
168
+ end
169
+
170
+ @focus.button_up(id) if @focus.respond_to?(:button_up)
171
+ end
172
+
173
+ def redirect_mouse_button(button)
174
+ hide_menu unless @menu && (@menu == @mouse_over) || (@mouse_over&.parent == @menu)
175
+
176
+ if @focus && @mouse_over != @focus
177
+ @focus.publish(:blur)
178
+ @focus = nil
179
+ end
180
+
181
+ if @mouse_over
182
+ @mouse_down_position[button] = Vector.new(window.mouse_x, window.mouse_y)
183
+ @mouse_down_on[button] = @mouse_over
184
+
185
+ @mouse_over.publish(:"#{button}_mouse_button", window.mouse_x, window.mouse_y)
186
+ else
187
+ @mouse_down_position[button] = nil
188
+ @mouse_down_on[button] = nil
189
+ end
190
+ end
191
+
192
+ def redirect_released_mouse_button(button)
193
+ hide_menu if @menu && (@menu == @mouse_over) || (@mouse_over&.parent == @menu)
194
+
195
+ if @mouse_over
196
+ @mouse_over.publish(:"released_#{button}_mouse_button", window.mouse_x, window.mouse_y)
197
+ if @mouse_over == @mouse_down_on[button]
198
+ @mouse_over.publish(:"clicked_#{button}_mouse_button", window.mouse_x,
199
+ window.mouse_y)
200
+ end
201
+ end
202
+
203
+ if @dragging_element
204
+ @dragging_element.publish(:end_drag, window.mouse_x, window.mouse_y, button)
205
+ @dragging_element = nil
206
+ end
207
+
208
+ @mouse_down_position[button] = nil
209
+ @mouse_down_on[button] = nil
210
+ end
211
+
212
+ def redirect_holding_mouse_button(button)
213
+ if !@dragging_element && @mouse_down_on[button] && @mouse_down_on[button].draggable?(button) && @mouse_pos.distance(@mouse_down_position[button]) > @min_drag_distance
214
+ @dragging_element = @mouse_down_on[button]
215
+ @dragging_element.publish(:begin_drag, window.mouse_x, window.mouse_y, button)
216
+ end
217
+
218
+ if @dragging_element
219
+ @dragging_element.publish(:drag_update, window.mouse_x, window.mouse_y, button) if @dragging_element
220
+ elsif @mouse_over
221
+ @mouse_over.publish(:"holding_#{button}_mouse_button", window.mouse_x, window.mouse_y)
222
+ end
223
+ end
224
+
225
+ def redirect_mouse_wheel(button)
226
+ @mouse_over.publish(:"mouse_wheel_#{button}", window.mouse_x, window.mouse_y) if @mouse_over
227
+ end
228
+
229
+ # Schedule a full GUI recalculation on next update
230
+ def request_recalculate
231
+ @pending_recalculate_request = true
232
+ end
233
+
234
+ def request_focus(element)
235
+ @pending_focus_request = true
236
+ @pending_focus_element = element
237
+ end
238
+
239
+ def show_menu(list_box)
240
+ @menu = list_box
241
+ end
242
+
243
+ def hide_menu
244
+ @menu = nil
245
+ end
246
+
247
+ def to_s
248
+ # "#{self.class} children=#{@children.map { |c| c.to_s }}"
249
+ @root_container.to_s
250
+ end
251
+
252
+ def inspect
253
+ to_s
254
+ end
255
+ end
256
+ end
@@ -1,49 +1,49 @@
1
- module Gosu
2
- class Color
3
- def _dump(_level)
4
- [
5
- "%02X" % alpha,
6
- "%02X" % red,
7
- "%02X" % green,
8
- "%02X" % blue
9
- ].join
10
- end
11
-
12
- def self._load(hex)
13
- argb(hex.to_i(16))
14
- end
15
- end
16
- end
17
-
18
- module CyberarmEngine
19
- class Style
20
- attr_reader :hash
21
-
22
- def initialize(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
34
- end
35
-
36
- def method_missing(method, *args)
37
- if method.to_s.end_with?("=")
38
- raise "Did not expect more than 1 argument" if args.size > 1
39
-
40
- @hash[method.to_s.sub("=", "").to_sym] = args.first
41
-
42
- elsif args.empty?
43
- @hash[method]
44
- else
45
- raise ArgumentError, "Did not expect arguments"
46
- end
47
- end
48
- end
49
- end
1
+ module Gosu
2
+ class Color
3
+ def _dump(_level)
4
+ [
5
+ "%02X" % alpha,
6
+ "%02X" % red,
7
+ "%02X" % green,
8
+ "%02X" % blue
9
+ ].join
10
+ end
11
+
12
+ def self._load(hex)
13
+ argb(hex.to_i(16))
14
+ end
15
+ end
16
+ end
17
+
18
+ module CyberarmEngine
19
+ class Style
20
+ attr_reader :hash
21
+
22
+ def initialize(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
34
+ end
35
+
36
+ def method_missing(method, *args)
37
+ if method.to_s.end_with?("=")
38
+ raise "Did not expect more than 1 argument" if args.size > 1
39
+
40
+ @hash[method.to_s.sub("=", "").to_sym] = args.first
41
+
42
+ elsif args.empty?
43
+ @hash[method]
44
+ else
45
+ raise ArgumentError, "Did not expect arguments"
46
+ end
47
+ end
48
+ end
49
+ end