cyberarm_engine 0.24.4 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d1ca43bcfb5385b9c2666d4917ac44683fcb22c44fa18b918643fab9ec16ef9
4
- data.tar.gz: 62d712e673772e19f74c14d1b6a54318776848d51ac0fbf82e3b4dc581ea58bf
3
+ metadata.gz: fbc09f82118fdefb70fa12a4322beb094d02a6b359c72775bede0d38de911f1a
4
+ data.tar.gz: 31d395c32d72a03867ba493470ba803a80eb209066952e2fbf52c8a0134910ad
5
5
  SHA512:
6
- metadata.gz: '09c5d9c2d88444021f625e35bef5d4eeb06bc5791f76e80d5560b2b347212f01c6be6bee26a782ca4aea1bfdeca535b4b8020cbce08e028980faec9a55b3ce89'
7
- data.tar.gz: 8e2185d8f47e3af2f0fc42106718bd64d722066a38fdfc3cf0777c3dbd4be7239443ac3f0552e26399c9791cf8297ca0ebd0066f6c1181c01553e6b01f3d74be
6
+ metadata.gz: b60db54bf9c4e23842f33d7cbcf867e9c9a3c2e73a135f3af9d38ec71c5a0ac52762869330c57febf1a2ab9b5db49bb0932193a2c3bc580929ccac5d620c9930
7
+ data.tar.gz: 6c50e0b0a9aebba3258d648e5959009367284863f8c30de6e567a0923e0922020c5361ac9194f47f9a8e7af8dc5127a06bda2ed8ec7113dadb4c729b9c1353a0
data/Gemfile.lock ADDED
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cyberarm_engine (0.24.5)
5
+ gosu (~> 1.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ gosu (1.4.6)
11
+ minitest (5.25.5)
12
+ rake (13.2.1)
13
+
14
+ PLATFORMS
15
+ x64-mingw-ucrt
16
+ x86_64-linux
17
+
18
+ DEPENDENCIES
19
+ bundler (~> 2.2)
20
+ cyberarm_engine!
21
+ minitest (~> 5.0)
22
+ rake (~> 13.0)
23
+
24
+ BUNDLED WITH
25
+ 2.6.8
@@ -1,14 +1,15 @@
1
1
  #version 330 core
2
+ @include "light_struct"
3
+
2
4
  out vec4 frag_color;
3
5
 
4
- @include "light_struct"
5
6
  const int DIRECTIONAL = 0;
6
7
  const int POINT = 1;
7
8
  const int SPOT = 2;
8
9
 
9
- flat in Light out_lights[7];
10
10
  in vec2 out_tex_coords;
11
11
  flat in int out_light_count;
12
+ flat in Light out_lights[7];
12
13
 
13
14
  uniform sampler2D diffuse, position, texcoord, normal, depth;
14
15
 
@@ -27,43 +28,88 @@ vec4 directionalLight(Light light) {
27
28
  return vec4(_diffuse + _ambient + _specular, 1.0);
28
29
  }
29
30
 
30
- vec4 pointLight(Light light) {
31
- return vec4(0.25, 0.25, 0.25, 1);
32
- }
31
+ void main() {
32
+ Light light;
33
+ light.type = DIRECTIONAL;
33
34
 
34
- vec4 spotLight(Light light) {
35
- return vec4(0.5, 0.5, 0.5, 1);
36
- }
35
+ light.position = vec3(100, 100, 100);
37
36
 
38
- vec4 calculateLighting(Light light) {
39
- vec4 result;
40
-
41
- // switch(light.type) {
42
- // case DIRECTIONAL: {
43
- // result = directionalLight(light);
44
- // }
45
- // case SPOT: {
46
- // result = spotLight(light);
47
- // }
48
- // default: {
49
- // result = pointLight(light);
50
- // }
51
- // }
52
-
53
- if (light.type == DIRECTIONAL) {
54
- result = directionalLight(light);
55
- } else {
56
- result = pointLight(light);
57
- }
58
-
59
- return result;
60
- }
37
+ light.diffuse = vec3(0.5, 0.5, 0.5);
38
+ light.ambient = vec3(0.8, 0.8, 0.8);
39
+ light.specular = vec3(0.2, 0.2, 0.2);
61
40
 
62
- void main() {
63
- frag_color = vec4(0.0);
41
+ light.intensity = 1.0;
64
42
 
65
- for(int i = 0; i < out_light_count; i++)
66
- {
67
- frag_color += texture(diffuse, out_tex_coords) * calculateLighting(out_lights[i]);
68
- }
43
+ frag_color = texture(diffuse, out_tex_coords) * directionalLight(light);
69
44
  }
45
+
46
+ // #version 330 core
47
+ // @include "light_struct"
48
+
49
+ // out vec4 frag_color;
50
+
51
+ // const int DIRECTIONAL = 0;
52
+ // const int POINT = 1;
53
+ // const int SPOT = 2;
54
+
55
+ // in vec2 out_tex_coords;
56
+ // flat in int out_light_count;
57
+ // flat in Light out_lights[7];
58
+
59
+ // uniform sampler2D diffuse, position, texcoord, normal, depth;
60
+
61
+ // vec4 directionalLight(Light light) {
62
+ // vec3 norm = normalize(texture(normal, out_tex_coords).rgb);
63
+ // vec3 diffuse_color = texture(diffuse, out_tex_coords).rgb;
64
+ // vec3 frag_pos = texture(position, out_tex_coords).rgb;
65
+
66
+ // vec3 lightDir = normalize(light.position - frag_pos);
67
+ // float diff = max(dot(norm, lightDir), 0);
68
+
69
+ // vec3 _ambient = light.ambient;
70
+ // vec3 _diffuse = light.diffuse * diff;
71
+ // vec3 _specular = light.specular;
72
+
73
+ // return vec4(_diffuse + _ambient + _specular, 1.0);
74
+ // }
75
+
76
+ // vec4 pointLight(Light light) {
77
+ // return vec4(0.25, 0.25, 0.25, 1);
78
+ // }
79
+
80
+ // vec4 spotLight(Light light) {
81
+ // return vec4(0.5, 0.5, 0.5, 1);
82
+ // }
83
+
84
+ // vec4 calculateLighting(Light light) {
85
+ // vec4 result;
86
+
87
+ // // switch(light.type) {
88
+ // // case DIRECTIONAL: {
89
+ // // result = directionalLight(light);
90
+ // // }
91
+ // // case SPOT: {
92
+ // // result = spotLight(light);
93
+ // // }
94
+ // // default: {
95
+ // // result = pointLight(light);
96
+ // // }
97
+ // // }
98
+
99
+ // if (light.type == DIRECTIONAL) {
100
+ // result = directionalLight(light);
101
+ // } else {
102
+ // result = pointLight(light);
103
+ // }
104
+
105
+ // return result;
106
+ // }
107
+
108
+ // void main() {
109
+ // frag_color = vec4(0.0);
110
+
111
+ // for(int i = 0; i < out_light_count; i++)
112
+ // {
113
+ // frag_color += texture(diffuse, out_tex_coords) * calculateLighting(out_lights[i]);
114
+ // }
115
+ // }
@@ -1,4 +1,4 @@
1
- # version 330 core
1
+ #version 330 core
2
2
 
3
3
  layout(location = 0) in vec3 in_position;
4
4
  layout(location = 1) in vec3 in_color;
@@ -35,36 +35,14 @@ module CyberarmEngine
35
35
  end
36
36
 
37
37
  def update
38
- origin_x = (@x + (@width / 2))
39
- origin_y = (@y + (@height / 2))
40
-
41
- points = [
42
- @top_left = Vector.new(@x, @y),
43
- @top_right = Vector.new(@x + @width, @y),
44
- @bottom_left = Vector.new(@x, @y + @height),
45
- @bottom_right = Vector.new(@x + @width, @y + @height)
46
- ]
47
-
48
- [@top_left, @top_right, @bottom_left, @bottom_right].each do |vector|
49
- temp_x = vector.x - origin_x
50
- temp_y = vector.y - origin_y
51
-
52
- # 90 is up here, while gosu uses 0 for up.
53
- radians = (@angle + 90).gosu_to_radians
54
- vector.x = (@x + (@width / 2)) + ((temp_x * Math.cos(radians)) - (temp_y * Math.sin(radians)))
55
- vector.y = (@y + (@height / 2)) + ((temp_x * Math.sin(radians)) + (temp_y * Math.cos(radians)))
56
- end
57
-
58
- # [
59
- # [:top, @top_left, @top_right],
60
- # [:right, @top_right, @bottom_right],
61
- # [:bottom, @bottom_right, @bottom_left],
62
- # [:left, @bottom_left, @top_left]
63
- # ].each do |edge|
64
- # points.each do |point|
65
- # puts "#{edge.first} -> #{shortest_distance(point, edge[1], edge[2])}"
66
- # end
67
- # end
38
+ @top_left.x = @x
39
+ @top_left.y = @y
40
+ @top_right.x = @x + @width
41
+ @top_right.y = @y
42
+ @bottom_left.x = @x
43
+ @bottom_left.y = @y + @height
44
+ @bottom_right.x = @x + @width
45
+ @bottom_right.y = @y + @height
68
46
  end
69
47
 
70
48
  def shortest_distance(point, la, lb)
@@ -170,10 +148,11 @@ module CyberarmEngine
170
148
  end
171
149
 
172
150
  # Add <=> method to support Range based gradients
173
- module Gosu
174
- class Color
175
- def <=>(_other)
176
- self
177
- end
178
- end
179
- end
151
+ # NOTE: Disabled, causes stack overflow 🙃
152
+ # module Gosu
153
+ # class Color
154
+ # def <=>(_other)
155
+ # self
156
+ # end
157
+ # end
158
+ # end
@@ -1,5 +1,7 @@
1
1
  module CyberarmEngine
2
2
  module Common
3
+ ImageBlob = Data.define(:to_blob, :columns, :rows)
4
+
3
5
  def push_state(klass, options = {})
4
6
  window.push_state(klass, options)
5
7
  end
@@ -85,7 +87,8 @@ module CyberarmEngine
85
87
  unless asset
86
88
  instance = nil
87
89
  instance = if klass == Gosu::Image
88
- klass.new(path, retro: retro, tileable: tileable)
90
+ path_or_blob = path.is_a?(String) ? path : ImageBlob.new(path.to_blob, path.width, path.height)
91
+ klass.new(path_or_blob, retro: retro, tileable: tileable)
89
92
  else
90
93
  klass.new(path)
91
94
  end
@@ -33,12 +33,23 @@ module Gosu
33
33
  #
34
34
  # @return [void]
35
35
  def self.draw_arc(x, y, radius, percentage = 1.0, segments = 128, thickness = 4, color = Gosu::Color::WHITE, z = 0, mode = :default)
36
- segments = 360.0 / segments
37
-
38
36
  return if percentage == 0.0
39
37
 
40
- 0.step((359 * percentage), percentage > 0 ? segments : -segments) do |angle|
41
- angle2 = angle + segments
38
+ angle_per_segment = 360.0 / segments
39
+ arc_completion = 360 * percentage
40
+ next_segment_angle = angle_per_segment
41
+
42
+ angle = 0
43
+ loop do
44
+ break if angle >= arc_completion
45
+
46
+ if angle + angle_per_segment > arc_completion
47
+ next_segment_angle = arc_completion - angle
48
+ else
49
+ next_segment_angle = angle_per_segment
50
+ end
51
+
52
+ angle2 = angle + next_segment_angle
42
53
 
43
54
  point_a_left_x = x + Gosu.offset_x(angle, radius - thickness)
44
55
  point_a_left_y = y + Gosu.offset_y(angle, radius - thickness)
@@ -93,6 +104,8 @@ module Gosu
93
104
  z, mode
94
105
  )
95
106
  end
107
+
108
+ angle += next_segment_angle
96
109
  end
97
110
  end
98
- end
111
+ end
@@ -1,6 +1,6 @@
1
1
  module CyberarmEngine
2
2
  class Model
3
- class ModelObject
3
+ class Mesh
4
4
  attr_reader :id, :name, :vertices, :uvs, :normals, :materials, :bounding_box, :debug_color
5
5
  attr_accessor :faces, :scale
6
6
 
@@ -48,12 +48,12 @@ module CyberarmEngine
48
48
  if _model
49
49
  @model.current_object = _model
50
50
  else
51
- raise "Couldn't find ModelObject!"
51
+ raise "Couldn't find Mesh!"
52
52
  end
53
53
  end
54
54
 
55
55
  def change_object(id, name)
56
- @model.objects << Model::ModelObject.new(id, name)
56
+ @model.objects << Model::Mesh.new(id, name)
57
57
  @model.current_object = @model.objects.last
58
58
  end
59
59
 
@@ -1,5 +1,8 @@
1
1
  module CyberarmEngine
2
2
  class Model
3
+ include OpenGL
4
+ include CyberarmEngine
5
+
3
6
  attr_accessor :objects, :materials, :vertices, :uvs, :texures, :normals, :faces, :colors, :bones, :material_file,
4
7
  :current_material, :current_object, :vertex_count, :smoothing
5
8
  attr_reader :position, :bounding_box, :textured_material, :file_path, :positions_buffer_id, :colors_buffer_id,
@@ -49,9 +52,9 @@ module CyberarmEngine
49
52
 
50
53
  @objects.each { |o| @vertex_count += o.vertices.size }
51
54
 
52
- # start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
53
- # build_collision_tree
54
- # puts " Building mesh collision tree took #{((Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) - start_time) / 1000.0).round(2)} seconds"
55
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
56
+ build_collision_tree
57
+ puts " Building mesh collision tree took #{((Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond) - start_time) / 1000.0).round(2)} seconds"
55
58
  end
56
59
 
57
60
  def parse(parser)
@@ -178,7 +181,7 @@ module CyberarmEngine
178
181
  end
179
182
 
180
183
  def build_collision_tree
181
- @aabb_tree = IMICFPS::AABBTree.new
184
+ @aabb_tree = AABBTree.new
182
185
 
183
186
  @faces.each do |face|
184
187
  box = BoundingBox.new
@@ -1,5 +1,7 @@
1
1
  module CyberarmEngine
2
2
  class Light
3
+ include OpenGL
4
+
3
5
  DIRECTIONAL = 0
4
6
  POINT = 1
5
7
  SPOT = 2
@@ -1,5 +1,8 @@
1
1
  module CyberarmEngine
2
2
  class PerspectiveCamera
3
+ include OpenGL
4
+ include GLU
5
+
3
6
  attr_accessor :position, :orientation, :aspect_ratio, :field_of_view,
4
7
  :min_view_distance, :max_view_distance
5
8
 
@@ -1,5 +1,7 @@
1
1
  module CyberarmEngine
2
2
  class GBuffer
3
+ include OpenGL
4
+
3
5
  attr_reader :screen_vbo, :vertices, :uvs
4
6
  attr_reader :width, :height
5
7
 
@@ -1,5 +1,8 @@
1
1
  module CyberarmEngine
2
2
  class OpenGLRenderer
3
+ include OpenGL
4
+ include CyberarmEngine
5
+
3
6
  @@immediate_mode_warning = false
4
7
 
5
8
  attr_accessor :show_wireframe
@@ -2,6 +2,7 @@ module CyberarmEngine
2
2
  # Ref: https://github.com/vaiorabbit/ruby-opengl/blob/master/sample/OrangeBook/brick.rb
3
3
  class Shader
4
4
  include OpenGL
5
+
5
6
  @@shaders = {} # Cache for {Shader} instances
6
7
  PREPROCESSOR_CHARACTER = "@".freeze # magic character for preprocessor phase of {Shader} compilation
7
8
 
@@ -298,6 +299,7 @@ module CyberarmEngine
298
299
  # @see Shader.use Shader.use
299
300
  def use(&block)
300
301
  return unless compiled?
302
+
301
303
  raise "Another shader is already in use! #{Shader.active_shader.name.inspect}" if Shader.active_shader
302
304
 
303
305
  Shader.active_shader = self
@@ -1,5 +1,6 @@
1
1
  begin
2
2
  require "opengl"
3
+ require "glu"
3
4
  rescue LoadError
4
5
  puts "Required gem is not installed, please install 'opengl-bindings' and try again."
5
6
  exit(1)
@@ -8,7 +9,7 @@ end
8
9
  module CyberarmEngine
9
10
  def gl_error?
10
11
  e = glGetError
11
- if e != GL_NO_ERROR
12
+ if e != OpenGL::GL_NO_ERROR
12
13
  warn "OpenGL error detected by handler at: #{caller[0]}"
13
14
  warn " #{gluErrorString(e)} (#{e})\n"
14
15
  exit if Window.instance&.exit_on_opengl_error?
@@ -38,3 +39,15 @@ require_relative "opengl/renderer/g_buffer"
38
39
  require_relative "opengl/renderer/bounding_box_renderer"
39
40
  require_relative "opengl/renderer/opengl_renderer"
40
41
  require_relative "opengl/renderer/renderer"
42
+
43
+ require_relative "trees/aabb_tree_debug"
44
+ require_relative "trees/aabb_node"
45
+ require_relative "trees/aabb_tree"
46
+
47
+ require_relative "model"
48
+ require_relative "model_cache"
49
+ require_relative "model/material"
50
+ require_relative "model/mesh"
51
+ require_relative "model/parser"
52
+ require_relative "model/parsers/wavefront_parser"
53
+ require_relative "model/parsers/collada_parser" if RUBY_ENGINE != "mruby" && defined?(Nokogiri)
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CyberarmEngine
4
+ class AABBTree
5
+ class AABBNode
6
+ attr_accessor :bounding_box, :parent, :object
7
+ attr_reader :a, :b
8
+
9
+ def initialize(parent:, object:, bounding_box:)
10
+ @parent = parent
11
+ @object = object
12
+ @bounding_box = bounding_box
13
+
14
+ @a = nil
15
+ @b = nil
16
+ end
17
+
18
+ def a=(leaf)
19
+ @a = leaf
20
+ @a.parent = self
21
+ end
22
+
23
+ def b=(leaf)
24
+ @b = leaf
25
+ @b.parent = self
26
+ end
27
+
28
+ def leaf?
29
+ @object
30
+ end
31
+
32
+ def insert_subtree(leaf)
33
+ if leaf?
34
+ new_node = AABBNode.new(parent: nil, object: nil, bounding_box: @bounding_box.union(leaf.bounding_box))
35
+
36
+ new_node.a = self
37
+ new_node.b = leaf
38
+
39
+ new_node
40
+ else
41
+ cost_a = @a.bounding_box.volume + @b.bounding_box.union(leaf.bounding_box).volume
42
+ cost_b = @b.bounding_box.volume + @a.bounding_box.union(leaf.bounding_box).volume
43
+
44
+ if cost_a == cost_b
45
+ cost_a = @a.proximity(leaf)
46
+ cost_b = @b.proximity(leaf)
47
+ end
48
+
49
+ if cost_b < cost_a
50
+ self.b = @b.insert_subtree(leaf)
51
+ else
52
+ self.a = @a.insert_subtree(leaf)
53
+ end
54
+
55
+ @bounding_box = @bounding_box.union(leaf.bounding_box)
56
+
57
+ self
58
+ end
59
+ end
60
+
61
+ def search_subtree(collider, items = [])
62
+ if @bounding_box.intersect?(collider)
63
+ if leaf?
64
+ items << self
65
+ else
66
+ @a.search_subtree(collider, items)
67
+ @b.search_subtree(collider, items)
68
+ end
69
+ end
70
+
71
+ items
72
+ end
73
+
74
+ def remove_subtree(leaf)
75
+ if leaf
76
+ self
77
+ elsif leaf.parent == self
78
+ other_child = other(leaf)
79
+ other_child.parent = @parent
80
+ other_child
81
+ else
82
+ leaf.parent.disown_child(leaf)
83
+ self
84
+ end
85
+ end
86
+
87
+ def other(leaf)
88
+ @a == leaf ? @b : @a
89
+ end
90
+
91
+ def disown_child(leaf)
92
+ value = other(leaf)
93
+ raise "Can not replace child of a leaf!" if @parent.leaf?
94
+ raise "Node is not a child of parent!" unless leaf.child_of?(@parent)
95
+
96
+ if @parent.a == self
97
+ @parent.a = value
98
+ else
99
+ @parent.b = value
100
+ end
101
+
102
+ @parent.update_bounding_box
103
+ end
104
+
105
+ def child_of?(leaf)
106
+ self == leaf.a || self == leaf.b
107
+ end
108
+
109
+ def proximity(leaf)
110
+ (@bounding_box - leaf.bounding_box).sum.abs
111
+ end
112
+
113
+ def update_bounding_box
114
+ node = self
115
+
116
+ unless node.leaf?
117
+ node.bounding_box = node.a.bounding_box.union(node.b.bounding_box)
118
+
119
+ while (node = node.parent)
120
+ node.bounding_box = node.a.bounding_box.union(node.b.bounding_box)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CyberarmEngine
4
+ class AABBTree
5
+ include AABBTreeDebug
6
+
7
+ attr_reader :root, :objects, :branches, :leaves
8
+
9
+ def initialize
10
+ @objects = {}
11
+ @root = nil
12
+ @branches = 0
13
+ @leaves = 0
14
+ end
15
+
16
+ def insert(object, bounding_box)
17
+ raise "BoundingBox can't be nil!" unless bounding_box
18
+ raise "Object can't be nil!" unless object
19
+ # raise "Object already in tree!" if @objects[object] # FIXME
20
+
21
+ leaf = AABBNode.new(parent: nil, object: object, bounding_box: bounding_box.dup)
22
+ @objects[object] = leaf
23
+
24
+ insert_leaf(leaf)
25
+ end
26
+
27
+ def insert_leaf(leaf)
28
+ @root = @root ? @root.insert_subtree(leaf) : leaf
29
+ end
30
+
31
+ def update(object, bounding_box)
32
+ leaf = remove(object)
33
+ leaf.bounding_box = bounding_box
34
+ insert_leaf(leaf)
35
+ end
36
+
37
+ # Returns a list of all objects that collided with collider
38
+ def search(collider, return_nodes = false)
39
+ items = []
40
+ if @root
41
+ items = @root.search_subtree(collider)
42
+ items.map!(&:object) unless return_nodes
43
+ end
44
+
45
+ items
46
+ end
47
+
48
+ def remove(object)
49
+ leaf = @objects.delete(object)
50
+ @root = @root.remove_subtree(leaf) if leaf
51
+
52
+ leaf
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CyberarmEngine
4
+ # Gets included into AABBTree
5
+ module AABBTreeDebug
6
+ def inspect
7
+ @branches = 0
8
+ @leaves = 0
9
+ if @root
10
+ node = @root
11
+
12
+ debug_search(node.a)
13
+ debug_search(node.b)
14
+ end
15
+
16
+ puts "<#{self.class}:#{object_id}> has #{@branches} branches and #{@leaves} leaves"
17
+ end
18
+
19
+ def debug_search(node)
20
+ if node.leaf?
21
+ @leaves += 1
22
+ else
23
+ @branches += 1
24
+ debug_search(node.a)
25
+ debug_search(node.b)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -7,13 +7,13 @@ module CyberarmEngine
7
7
  attr_reader :children, :gui_state, :scroll_position, :scroll_target_position
8
8
 
9
9
  def self.current_container
10
- @@current_container
10
+ @current_container
11
11
  end
12
12
 
13
13
  def self.current_container=(container)
14
14
  raise ArgumentError, "Expected container to an an instance of CyberarmEngine::Element::Container, got #{container.class}" unless container.is_a?(CyberarmEngine::Element::Container)
15
15
 
16
- @@current_container = container
16
+ @current_container = container
17
17
  end
18
18
 
19
19
  def initialize(options = {}, block = nil)
@@ -26,6 +26,11 @@ module CyberarmEngine
26
26
  @scroll_chunk = 120
27
27
  @scroll_speed = 40
28
28
 
29
+ if @gui_state
30
+ @width = window.width
31
+ @height = window.height
32
+ end
33
+
29
34
  @text_color = options[:color]
30
35
 
31
36
  @children = []
@@ -34,7 +39,7 @@ module CyberarmEngine
34
39
  end
35
40
 
36
41
  def build
37
- @block.call(self) if @block
42
+ @block&.call(self)
38
43
 
39
44
  root.gui_state.request_recalculate_for(self)
40
45
  end
@@ -53,7 +58,7 @@ module CyberarmEngine
53
58
  old_container = CyberarmEngine::Element::Container.current_container
54
59
 
55
60
  CyberarmEngine::Element::Container.current_container = self
56
- block.call(self) if block
61
+ block&.call(self)
57
62
 
58
63
  CyberarmEngine::Element::Container.current_container = old_container
59
64
 
@@ -66,7 +71,7 @@ module CyberarmEngine
66
71
  old_container = CyberarmEngine::Element::Container.current_container
67
72
 
68
73
  CyberarmEngine::Element::Container.current_container = self
69
- block.call(self) if block
74
+ block&.call(self)
70
75
 
71
76
  CyberarmEngine::Element::Container.current_container = old_container
72
77
 
@@ -89,9 +94,7 @@ module CyberarmEngine
89
94
  def debug_draw
90
95
  super
91
96
 
92
- @children.each do |child|
93
- child.debug_draw
94
- end
97
+ @children.each(&:debug_draw)
95
98
  end
96
99
 
97
100
  def update
@@ -111,7 +114,7 @@ module CyberarmEngine
111
114
 
112
115
  case child
113
116
  when Container
114
- if element = child.hit_element?(child_x, child_y)
117
+ if (element = child.hit_element?(child_x, child_y))
115
118
  return element
116
119
  end
117
120
  else
@@ -221,7 +224,7 @@ module CyberarmEngine
221
224
 
222
225
  update_child_element_visibity(child)
223
226
  end
224
- # puts "TOOK: #{Gosu.milliseconds - t}ms to recalculate #{self.class}:0x#{self.object_id.to_s(16)}'s #{@children.count} children"
227
+ # puts "TOOK: #{Gosu.milliseconds - t}ms to recalculate #{self.class}:0x#{object_id.to_s(16)}'s #{@children.count} children" if is_root?
225
228
 
226
229
  update_background
227
230
 
@@ -299,15 +302,15 @@ module CyberarmEngine
299
302
  return unless @style.scroll
300
303
 
301
304
  # Allow overscrolling UP, only if one can scroll DOWN
302
- if height < scroll_height
303
- if @scroll_target_position.y > 0
304
- @scroll_target_position.y = @scroll_chunk
305
- else
306
- @scroll_target_position.y += @scroll_chunk
307
- end
305
+ return unless height < scroll_height
308
306
 
309
- return :handled
307
+ if @scroll_target_position.y.positive?
308
+ @scroll_target_position.y = @scroll_chunk
309
+ else
310
+ @scroll_target_position.y += @scroll_chunk
310
311
  end
312
+
313
+ :handled
311
314
  end
312
315
 
313
316
  def mouse_wheel_down(sender, x, y)
@@ -315,13 +318,13 @@ module CyberarmEngine
315
318
 
316
319
  return unless height < scroll_height
317
320
 
318
- if @scroll_target_position.y > 0
321
+ if @scroll_target_position.y.positive?
319
322
  @scroll_target_position.y = -@scroll_chunk
320
323
  else
321
324
  @scroll_target_position.y -= @scroll_chunk
322
325
  end
323
326
 
324
- return :handled
327
+ :handled
325
328
  end
326
329
 
327
330
  def scroll_jump_to_top(sender, x, y)
@@ -330,7 +333,7 @@ module CyberarmEngine
330
333
  @scroll_position.y = 0
331
334
  @scroll_target_position.y = 0
332
335
 
333
- return :handled
336
+ :handled
334
337
  end
335
338
 
336
339
  def scroll_jump_to_end(sender, x, y)
@@ -339,7 +342,7 @@ module CyberarmEngine
339
342
  @scroll_position.y = -max_scroll_height
340
343
  @scroll_target_position.y = -max_scroll_height
341
344
 
342
- return :handled
345
+ :handled
343
346
  end
344
347
 
345
348
  def scroll_page_up(sender, x, y)
@@ -349,7 +352,7 @@ module CyberarmEngine
349
352
  @scroll_position.y = 0 if @scroll_position.y > 0
350
353
  @scroll_target_position.y = @scroll_position.y
351
354
 
352
- return :handled
355
+ :handled
353
356
  end
354
357
 
355
358
  def scroll_page_down(sender, x, y)
@@ -359,7 +362,7 @@ module CyberarmEngine
359
362
  @scroll_position.y = -max_scroll_height if @scroll_position.y < -max_scroll_height
360
363
  @scroll_target_position.y = @scroll_position.y
361
364
 
362
- return :handled
365
+ :handled
363
366
  end
364
367
 
365
368
  def scroll_top
@@ -168,7 +168,7 @@ module CyberarmEngine
168
168
  @last_text = @text.text
169
169
  @last_pos = caret_pos
170
170
 
171
- if caret_pos.between?(@offset_x, @width + @offset_x)
171
+ if caret_pos.between?(@offset_x + 1, @width + @offset_x)
172
172
  # Do nothing
173
173
 
174
174
  elsif caret_pos < @offset_x
@@ -197,7 +197,7 @@ module CyberarmEngine
197
197
 
198
198
  def text_input_position_for(method)
199
199
  if @type == :password
200
- @text.x + @text.width(default(:password_character) * @text_input.text[0...@text_input.send(method)].length)
200
+ @text.x + @text.width(default(:password_character) * @text_input.text[0...@text_input.send(method)].length) - @style.border_thickness_left
201
201
  else
202
202
  @text.x + @text.width(@text_input.text[0...@text_input.send(method)]) - @style.border_thickness_left
203
203
  end
@@ -16,6 +16,8 @@ module CyberarmEngine
16
16
  )
17
17
 
18
18
  @raw_text = text
19
+ @text_width = @text.width
20
+ @text_height = @text.height
19
21
  end
20
22
 
21
23
  def update
@@ -29,7 +31,7 @@ module CyberarmEngine
29
31
 
30
32
  def render
31
33
  # Gosu.clip_to is too expensive to always use so check if we actually need it.
32
- if @text.width > width || @text.height > height
34
+ if @text_width > width || @text_height > height
33
35
  Gosu.clip_to(@x, @y, width, height) do
34
36
  @text.draw
35
37
  end
@@ -53,8 +55,12 @@ module CyberarmEngine
53
55
 
54
56
  handle_text_wrapping(_width)
55
57
 
56
- @width = _width || @text.width.floor
57
- @height = _height || @text.height.floor
58
+ # Update cached text width and height
59
+ @text_width = @text.width
60
+ @text_height = @text.height
61
+
62
+ @width = _width || @text_width.floor
63
+ @height = _height || @text_height.floor
58
64
 
59
65
  @text.y = @style.border_thickness_top + @style.padding_top + @y
60
66
  @text.z = @z + 3
@@ -64,26 +70,26 @@ module CyberarmEngine
64
70
  when :left
65
71
  @text.x = @style.border_thickness_left + @style.padding_left + @x
66
72
  when :center
67
- @text.x = if @text.width <= width
68
- @x + width / 2 - @text.width / 2
73
+ @text.x = if @text_width <= width
74
+ @x + width / 2 - @text_width / 2
69
75
  else # Act as left aligned
70
76
  @style.border_thickness_left + @style.padding_left + @x
71
77
  end
72
78
  when :right
73
- @text.x = @x + outer_width - (@text.width + @style.border_thickness_right + @style.padding_right)
79
+ @text.x = @x + outer_width - (@text_width + @style.border_thickness_right + @style.padding_right)
74
80
  end
75
81
  end
76
82
 
77
83
  if (vertical_alignment = @options[:text_v_align])
78
84
  case vertical_alignment
79
85
  when :center
80
- @text.y = if @text.height <= height
81
- @y + height / 2 - @text.height / 2
86
+ @text.y = if @text_height <= height
87
+ @y + height / 2 - @text_height / 2
82
88
  else
83
89
  @style.border_thickness_top + @style.padding_top + @y
84
90
  end
85
91
  when :bottom
86
- @text.y = @y + outer_height - (@text.height + @style.border_thickness_bottom + @style.padding_bottom)
92
+ @text.y = @y + outer_height - (@text_height + @style.border_thickness_bottom + @style.padding_bottom)
87
93
  end
88
94
  end
89
95
 
@@ -54,24 +54,29 @@ module CyberarmEngine
54
54
  end
55
55
 
56
56
  def draw
57
+ # t = Gosu.milliseconds
58
+ # report_recalculate_time = @pending_recalculate_request || @pending_element_recalculate_requests.size.positive?
59
+
60
+ StackProf.start(mode: :wall) if RUBY_ENGINE != "mruby" && defined?(StackProf)
57
61
  Stats.frame.start_timing(:gui_element_recalculate_requests)
58
62
 
59
63
  # puts "PENDING REQUESTS: #{@pending_element_recalculate_requests.size}" if @pending_element_recalculate_requests.size.positive?
60
- @pending_element_recalculate_requests.each(&:recalculate)
61
- @pending_element_recalculate_requests.clear
64
+ @pending_element_recalculate_requests.shift(&:recalculate)
62
65
 
63
66
  Stats.frame.end_timing(:gui_element_recalculate_requests)
64
67
 
65
- if @pending_recalculate_request
66
- Stats.frame.start_timing(:gui_recalculate)
67
-
68
- @root_container.recalculate
68
+ Stats.frame.start_timing(:gui_recalculate)
69
69
 
70
+ while(@pending_recalculate_request)
70
71
  @pending_recalculate_request = false
71
72
 
72
- Stats.frame.end_timing(:gui_recalculate)
73
+ @root_container.recalculate
73
74
  end
74
75
 
76
+ StackProf.stop if RUBY_ENGINE != "mruby" && defined?(StackProf)
77
+ Stats.frame.end_timing(:gui_recalculate)
78
+ # puts "TOOK: #{Gosu.milliseconds - t}ms to recalculate #{self.class}:0x#{object_id.to_s(16)}" if report_recalculate_time && Gosu.milliseconds - t > 0
79
+
75
80
  super
76
81
 
77
82
  if @menu
@@ -19,6 +19,30 @@ module CyberarmEngine
19
19
  class Style
20
20
  attr_reader :hash
21
21
 
22
+ %i[
23
+ x y z width height min_width min_height max_width max_height color background
24
+ background_image background_image_mode background_image_color
25
+ background_nine_slice background_nine_slice_mode background_nine_slice_color background_nine_slice_from_edge
26
+ background_nine_slice_left background_nine_slice_top background_nine_slice_right background_nine_slice_bottom
27
+ border_color border_color_left border_color_right border_color_top border_color_bottom
28
+ border_thickness border_thickness_left border_thickness_right border_thickness_top border_thickness_bottom
29
+ padding padding_left padding_right padding_top padding_bottom
30
+ margin margin_left margin_right margin_top margin_bottom
31
+ background_canvas background_nine_slice_canvas background_image_canvas border_canvas
32
+
33
+ fraction_background scroll fill text_wrap v_align h_align delay tag
34
+ image_width image_height
35
+
36
+ default hover active disabled
37
+ ].each do |item|
38
+ define_method(item) do
39
+ @hash[item]
40
+ end
41
+ define_method(:"#{item}=") do |value|
42
+ @hash[item] = value
43
+ end
44
+ end
45
+
22
46
  def initialize(hash = {})
23
47
  h = hash
24
48
  # h = Marshal.load(Marshal.dump(hash))
@@ -33,18 +57,5 @@ module CyberarmEngine
33
57
 
34
58
  @hash = h
35
59
  end
36
-
37
- def method_missing(method, *args)
38
- if method.to_s.end_with?("=")
39
- raise "Did not expect more than 1 argument" if args.size > 1
40
-
41
- @hash[method.to_s.sub("=", "").to_sym] = args.first
42
-
43
- elsif args.empty?
44
- @hash[method]
45
- else
46
- raise ArgumentError, "Did not expect arguments"
47
- end
48
- end
49
60
  end
50
61
  end
@@ -1,4 +1,4 @@
1
1
  module CyberarmEngine
2
2
  NAME = "InDev".freeze
3
- VERSION = "0.24.4".freeze
3
+ VERSION = "0.25.0".freeze
4
4
  end
@@ -67,12 +67,10 @@ require_relative "cyberarm_engine/ui/elements/menu_item"
67
67
  require_relative "cyberarm_engine/game_state"
68
68
  require_relative "cyberarm_engine/ui/gui_state"
69
69
 
70
- require_relative "cyberarm_engine/model"
71
- require_relative "cyberarm_engine/model_cache"
72
- require_relative "cyberarm_engine/model/material"
73
- require_relative "cyberarm_engine/model/model_object"
74
- require_relative "cyberarm_engine/model/parser"
75
- require_relative "cyberarm_engine/model/parsers/wavefront_parser"
76
- require_relative "cyberarm_engine/model/parsers/collada_parser" if RUBY_ENGINE != "mruby" && defined?(Nokogiri)
77
-
78
70
  require_relative "cyberarm_engine/builtin/intro_state"
71
+
72
+ if RUBY_ENGINE != "mruby" && defined?(StackProf)
73
+ at_exit do
74
+ StackProf.results("./_stackprof.dmp")
75
+ end
76
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cyberarm_engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.4
4
+ version: 0.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyberarm
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-03-05 00:00:00.000000000 Z
10
+ date: 2026-01-09 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: gosu
@@ -77,6 +76,7 @@ files:
77
76
  - ".rubocop.yml"
78
77
  - ".travis.yml"
79
78
  - Gemfile
79
+ - Gemfile.lock
80
80
  - LICENSE.txt
81
81
  - README.md
82
82
  - Rakefile
@@ -113,7 +113,7 @@ files:
113
113
  - lib/cyberarm_engine/gosu_ext/draw_path.rb
114
114
  - lib/cyberarm_engine/model.rb
115
115
  - lib/cyberarm_engine/model/material.rb
116
- - lib/cyberarm_engine/model/model_object.rb
116
+ - lib/cyberarm_engine/model/mesh.rb
117
117
  - lib/cyberarm_engine/model/parser.rb
118
118
  - lib/cyberarm_engine/model/parsers/collada_parser.rb
119
119
  - lib/cyberarm_engine/model/parsers/wavefront_parser.rb
@@ -135,6 +135,9 @@ files:
135
135
  - lib/cyberarm_engine/text.rb
136
136
  - lib/cyberarm_engine/timer.rb
137
137
  - lib/cyberarm_engine/transform.rb
138
+ - lib/cyberarm_engine/trees/aabb_node.rb
139
+ - lib/cyberarm_engine/trees/aabb_tree.rb
140
+ - lib/cyberarm_engine/trees/aabb_tree_debug.rb
138
141
  - lib/cyberarm_engine/ui/border_canvas.rb
139
142
  - lib/cyberarm_engine/ui/dsl.rb
140
143
  - lib/cyberarm_engine/ui/element.rb
@@ -167,7 +170,6 @@ licenses:
167
170
  - MIT
168
171
  metadata:
169
172
  allowed_push_host: https://rubygems.org
170
- post_install_message:
171
173
  rdoc_options: []
172
174
  require_paths:
173
175
  - lib
@@ -183,8 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
185
  - !ruby/object:Gem::Version
184
186
  version: '0'
185
187
  requirements: []
186
- rubygems_version: 3.5.3
187
- signing_key:
188
+ rubygems_version: 3.6.2
188
189
  specification_version: 4
189
190
  summary: Make games quickly and easily with gosu
190
191
  test_files: []