gosling 2.3.0 → 2.3.2
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 +5 -5
- data/lib/gosling.rb +4 -4
- data/lib/gosling/actor.rb +328 -328
- data/lib/gosling/circle.rb +65 -65
- data/lib/gosling/collision.rb +499 -499
- data/lib/gosling/image_library.rb +24 -24
- data/lib/gosling/inheritance_error.rb +4 -4
- data/lib/gosling/matrix_cache.rb +23 -21
- data/lib/gosling/object_cache.rb +48 -48
- data/lib/gosling/patches.rb +42 -42
- data/lib/gosling/polygon.rb +122 -122
- data/lib/gosling/rect.rb +41 -41
- data/lib/gosling/sprite.rb +50 -50
- data/lib/gosling/transformable.rb +413 -413
- data/lib/gosling/utils.rb +20 -20
- data/lib/gosling/vector_cache.rb +21 -21
- data/lib/gosling/version.rb +7 -7
- data/spec/actor_spec.rb +627 -627
- data/spec/circle_spec.rb +46 -46
- data/spec/collision_spec.rb +1755 -1755
- data/spec/image_library_spec.rb +19 -19
- data/spec/matrix_cache_spec.rb +25 -25
- data/spec/object_cache_spec.rb +22 -22
- data/spec/polygon_spec.rb +284 -284
- data/spec/rect_spec.rb +86 -86
- data/spec/spec_helper.rb +3 -3
- data/spec/sprite_spec.rb +45 -45
- data/spec/transformable_spec.rb +479 -479
- data/spec/vector_cache_spec.rb +80 -80
- metadata +3 -4
data/lib/gosling/utils.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
##
|
2
|
-
# Raises an ArgumentError unless the object is of the specified type.
|
3
|
-
#
|
4
|
-
def type_check(obj, type)
|
5
|
-
raise ArgumentError.new("Expected #{type}, but received #{obj.inspect}!") unless obj.is_a?(type)
|
6
|
-
end
|
7
|
-
|
8
|
-
##
|
9
|
-
# Raises an ArgumentError unless the object is one of the listed types.
|
10
|
-
#
|
11
|
-
def types_check(obj, *types)
|
12
|
-
raise ArgumentError.new("Expected one of #{types.inspect}, but received #{obj.inspect}!") unless types.any? { |type| obj.is_a?(type) }
|
13
|
-
end
|
14
|
-
|
15
|
-
##
|
16
|
-
# Raises an ArgumentError unless the object is truthy.
|
17
|
-
#
|
18
|
-
def boolean_check(obj)
|
19
|
-
raise ArgumentError.new("Expected true or false, but received #{obj.inspect}!") unless [true, false].include?(obj)
|
20
|
-
end
|
1
|
+
##
|
2
|
+
# Raises an ArgumentError unless the object is of the specified type.
|
3
|
+
#
|
4
|
+
def type_check(obj, type)
|
5
|
+
raise ArgumentError.new("Expected #{type}, but received #{obj.inspect}!") unless obj.is_a?(type)
|
6
|
+
end
|
7
|
+
|
8
|
+
##
|
9
|
+
# Raises an ArgumentError unless the object is one of the listed types.
|
10
|
+
#
|
11
|
+
def types_check(obj, *types)
|
12
|
+
raise ArgumentError.new("Expected one of #{types.inspect}, but received #{obj.inspect}!") unless types.any? { |type| obj.is_a?(type) }
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Raises an ArgumentError unless the object is truthy.
|
17
|
+
#
|
18
|
+
def boolean_check(obj)
|
19
|
+
raise ArgumentError.new("Expected true or false, but received #{obj.inspect}!") unless [true, false].include?(obj)
|
20
|
+
end
|
data/lib/gosling/vector_cache.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
require_relative 'object_cache.rb'
|
2
|
-
|
3
|
-
class VectorCache
|
4
|
-
include Singleton
|
5
|
-
include ObjectCache
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@cache = {}
|
9
|
-
end
|
10
|
-
|
11
|
-
protected
|
12
|
-
|
13
|
-
def create
|
14
|
-
Snow::Vec3.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def reset(vector)
|
18
|
-
type_check(vector, Snow::Vec3)
|
19
|
-
vector.set(0, 0, 0)
|
20
|
-
end
|
21
|
-
end
|
1
|
+
require_relative 'object_cache.rb'
|
2
|
+
|
3
|
+
class VectorCache
|
4
|
+
include Singleton
|
5
|
+
include ObjectCache
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@cache = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def create
|
14
|
+
Snow::Vec3.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def reset(vector)
|
18
|
+
type_check(vector, Snow::Vec3)
|
19
|
+
vector.set(0, 0, 0)
|
20
|
+
end
|
21
|
+
end
|
data/lib/gosling/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
#--
|
2
|
-
# MAJOR version when you make incompatible changes,
|
3
|
-
# MINOR version when you add functionality in a backwards-compatible manner, and
|
4
|
-
# PATCH version when you make backwards-compatible bug fixes.
|
5
|
-
module Gosling
|
6
|
-
VERSION = '2.3.
|
7
|
-
end
|
1
|
+
#--
|
2
|
+
# MAJOR version when you make incompatible changes,
|
3
|
+
# MINOR version when you add functionality in a backwards-compatible manner, and
|
4
|
+
# PATCH version when you make backwards-compatible bug fixes.
|
5
|
+
module Gosling
|
6
|
+
VERSION = '2.3.2'
|
7
|
+
end
|
data/spec/actor_spec.rb
CHANGED
@@ -1,628 +1,628 @@
|
|
1
|
-
module Gosling
|
2
|
-
class Actor
|
3
|
-
public :render
|
4
|
-
end
|
5
|
-
end
|
6
|
-
|
7
|
-
describe Gosling::Actor do
|
8
|
-
before(:all) do
|
9
|
-
@window = Gosu::Window.new(640, 480, false)
|
10
|
-
@read_only_actor = Gosling::Actor.new(@window)
|
11
|
-
@parent = Gosling::Actor.new(@window)
|
12
|
-
@child = Gosling::Actor.new(@window)
|
13
|
-
end
|
14
|
-
|
15
|
-
describe '#new' do
|
16
|
-
it 'requires a Gosu::Window' do
|
17
|
-
expect { Gosling::Actor.new(@window) }.not_to raise_error
|
18
|
-
expect { Gosling::Actor.new() }.to raise_error(ArgumentError)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'has a transform' do
|
23
|
-
expect(@read_only_actor).to be_kind_of(Gosling::Transformable)
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'can have a parent' do
|
27
|
-
expect { @read_only_actor.parent }.not_to raise_error
|
28
|
-
end
|
29
|
-
|
30
|
-
it "does not initialize with a parent" do
|
31
|
-
expect(@read_only_actor.parent).to be == nil
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '#add_child' do
|
35
|
-
it "creates a two-way parent/child link" do
|
36
|
-
@parent.add_child(@child)
|
37
|
-
expect(@parent.has_child?(@child)).to be true
|
38
|
-
expect(@child.parent).to be == @parent
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe '#remove_child' do
|
43
|
-
it "severs the two-way parent/child link" do
|
44
|
-
@parent.add_child(@child)
|
45
|
-
@parent.remove_child(@child)
|
46
|
-
expect(@parent.has_child?(@child)).to be false
|
47
|
-
expect(@child.parent).to be == nil
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'has a list of children' do
|
52
|
-
expect(@read_only_actor.children).to be_instance_of(Array)
|
53
|
-
end
|
54
|
-
|
55
|
-
it "starts with no children" do
|
56
|
-
expect(@read_only_actor.children.empty?).to be true
|
57
|
-
end
|
58
|
-
|
59
|
-
it "knows if it has a particular child or not" do
|
60
|
-
expect(@read_only_actor.has_child?(Gosling::Actor.new(@window))).to be false
|
61
|
-
end
|
62
|
-
|
63
|
-
it "will never add any of its ancestors as children" do
|
64
|
-
@parent.add_child(@child)
|
65
|
-
expect { @child.add_child(@parent) }.to raise_error(Gosling::InheritanceError)
|
66
|
-
end
|
67
|
-
|
68
|
-
it "will not add itself as its own child" do
|
69
|
-
expect { @child.add_child(@child) }.to raise_error(Gosling::InheritanceError)
|
70
|
-
end
|
71
|
-
|
72
|
-
context "when given a child" do
|
73
|
-
before do
|
74
|
-
@parent.add_child(@child)
|
75
|
-
end
|
76
|
-
|
77
|
-
it "it forms a two-way link with that child" do
|
78
|
-
expect(@parent.has_child?(@child)).to be true
|
79
|
-
expect(@child.parent).to be == @parent
|
80
|
-
end
|
81
|
-
|
82
|
-
it "cannot be given the same child more than once" do
|
83
|
-
@parent.add_child(@child)
|
84
|
-
expect(@parent.children.length).to be == 1
|
85
|
-
end
|
86
|
-
|
87
|
-
context "and then the child is removed" do
|
88
|
-
before do
|
89
|
-
@parent.remove_child(@child)
|
90
|
-
end
|
91
|
-
|
92
|
-
it "the parent/child link is broken" do
|
93
|
-
expect(@parent.has_child?(@child)).to be false
|
94
|
-
expect(@child.parent).to be == nil
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
context 'and then adopted by another actor' do
|
99
|
-
it 'automatically breaks the old child/parent link' do
|
100
|
-
parent2 = Gosling::Actor.new(@window)
|
101
|
-
parent2.add_child(@child)
|
102
|
-
expect(@parent.has_child?(@child)).to be false
|
103
|
-
expect(@child.parent).to be == parent2
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'has a visibility flag' do
|
109
|
-
actor = Gosling::Actor.new(@window)
|
110
|
-
actor.is_visible = true
|
111
|
-
expect(actor.is_visible).to be true
|
112
|
-
actor.is_visible = false
|
113
|
-
expect(actor.is_visible).to be false
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'has a children visibility flag' do
|
117
|
-
actor = Gosling::Actor.new(@window)
|
118
|
-
actor.are_children_visible = true
|
119
|
-
expect(actor.are_children_visible).to be true
|
120
|
-
actor.are_children_visible = false
|
121
|
-
expect(actor.are_children_visible).to be false
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'has a tangible flag' do
|
125
|
-
actor = Gosling::Actor.new(@window)
|
126
|
-
actor.is_tangible = true
|
127
|
-
expect(actor.is_tangible).to be true
|
128
|
-
actor.is_tangible = false
|
129
|
-
expect(actor.is_tangible).to be false
|
130
|
-
end
|
131
|
-
|
132
|
-
it 'has a children tangibile flag' do
|
133
|
-
actor = Gosling::Actor.new(@window)
|
134
|
-
actor.are_children_tangible = true
|
135
|
-
expect(actor.are_children_tangible).to be true
|
136
|
-
actor.are_children_tangible = false
|
137
|
-
expect(actor.are_children_tangible).to be false
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'has a mask flag' do
|
141
|
-
actor = Gosling::Actor.new(@window)
|
142
|
-
actor.is_mask = true
|
143
|
-
expect(actor.is_mask).to be true
|
144
|
-
actor.is_mask = false
|
145
|
-
expect(actor.is_mask).to be false
|
146
|
-
end
|
147
|
-
|
148
|
-
describe '#render' do
|
149
|
-
it 'the method exists' do
|
150
|
-
expect { @read_only_actor.render(Snow::Mat3.new) }.not_to raise_error
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
describe '#draw' do
|
155
|
-
before(:all) do
|
156
|
-
@draw_actor = Gosling::Actor.new(@window)
|
157
|
-
@mat = Snow::Mat3.new
|
158
|
-
end
|
159
|
-
|
160
|
-
context 'when visible' do
|
161
|
-
it 'calls render on itself' do
|
162
|
-
@draw_actor.is_visible = true
|
163
|
-
expect(@draw_actor).to receive(:render).with(@mat).once
|
164
|
-
@draw_actor.draw(@mat)
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
context 'when not visible' do
|
169
|
-
it 'does not call render on itself' do
|
170
|
-
@draw_actor.is_visible = false
|
171
|
-
expect(@draw_actor).not_to receive(:render)
|
172
|
-
@draw_actor.draw(@mat)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
context 'with children' do
|
177
|
-
before(:all) do
|
178
|
-
@child1 = Gosling::Actor.new(@window)
|
179
|
-
@child2 = Gosling::Actor.new(@window)
|
180
|
-
@draw_actor.add_child(@child1)
|
181
|
-
@draw_actor.add_child(@child2)
|
182
|
-
end
|
183
|
-
|
184
|
-
context 'when are_children_visible is false' do
|
185
|
-
it 'draws itself, but not its children' do
|
186
|
-
@draw_actor.are_children_visible = false
|
187
|
-
expect(@child1).not_to receive(:draw)
|
188
|
-
expect(@child2).not_to receive(:draw)
|
189
|
-
@draw_actor.draw(@mat)
|
190
|
-
@draw_actor.are_children_visible = true
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
it 'calls draw on each of its children' do
|
195
|
-
expect(@child1).to receive(:draw).with(@mat).once
|
196
|
-
expect(@child2).to receive(:draw).with(@mat).once
|
197
|
-
@draw_actor.draw(@mat)
|
198
|
-
end
|
199
|
-
|
200
|
-
it 'passes its children a comprehensive transformation matrix' do
|
201
|
-
parameter_mat = Snow::Mat3[
|
202
|
-
1, 0, 10,
|
203
|
-
0, 1, 20,
|
204
|
-
0, 0, 1
|
205
|
-
]
|
206
|
-
self_mat = Snow::Mat3[
|
207
|
-
2, 0, 0,
|
208
|
-
0, 3, 0,
|
209
|
-
0, 0, 1
|
210
|
-
]
|
211
|
-
result_mat = self_mat * parameter_mat
|
212
|
-
|
213
|
-
allow(@draw_actor).to receive(:to_matrix).and_return(self_mat)
|
214
|
-
|
215
|
-
expect(@child1).to receive(:draw).with(result_mat).once
|
216
|
-
expect(@child2).to receive(:draw).with(result_mat).once
|
217
|
-
@draw_actor.draw(parameter_mat)
|
218
|
-
end
|
219
|
-
|
220
|
-
after(:all) do
|
221
|
-
@draw_actor.children.each { |child| @draw_actor.remove_child(@child) }
|
222
|
-
end
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
describe '#is_point_in_bounds' do
|
227
|
-
it 'returns false' do
|
228
|
-
expect(@read_only_actor.is_point_in_bounds(Snow::Vec3[0,0,1])).to be false
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
describe '#get_actor_at' do
|
233
|
-
before(:all) do
|
234
|
-
@parent = Gosling::Actor.new(@window)
|
235
|
-
end
|
236
|
-
|
237
|
-
context 'when tangible is false' do
|
238
|
-
it 'returns nil even if hit' do
|
239
|
-
@parent.is_tangible = false
|
240
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
241
|
-
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
|
242
|
-
@parent.is_tangible = true
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
context 'with no children' do
|
247
|
-
it 'returns itself if the point is within its bounds' do
|
248
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
249
|
-
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
|
250
|
-
end
|
251
|
-
|
252
|
-
it 'returns nil if point is not within its bounds' do
|
253
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
254
|
-
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
context 'with two children' do
|
259
|
-
before(:all) do
|
260
|
-
@child1 = Gosling::Actor.new(@window)
|
261
|
-
@child2 = Gosling::Actor.new(@window)
|
262
|
-
@parent.add_child(@child1)
|
263
|
-
@parent.add_child(@child2)
|
264
|
-
end
|
265
|
-
|
266
|
-
context 'when the children are not tangible' do
|
267
|
-
it 'does not hit test any children' do
|
268
|
-
@parent.are_children_tangible = false
|
269
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
|
270
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
271
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(true)
|
272
|
-
|
273
|
-
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
|
274
|
-
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
|
275
|
-
@parent.are_children_tangible = true
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
it "returns the second child if such is hit" do
|
280
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true, false, true)
|
281
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(false, false, true, true)
|
282
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(true)
|
283
|
-
|
284
|
-
4.times { expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @child2 }
|
285
|
-
end
|
286
|
-
|
287
|
-
it "returns the first child if the second was not hit" do
|
288
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
|
289
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
290
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
291
|
-
|
292
|
-
2.times { expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @child1 }
|
293
|
-
end
|
294
|
-
|
295
|
-
it "returns itself if neither child was hit" do
|
296
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
297
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(false)
|
298
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
299
|
-
|
300
|
-
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
|
301
|
-
end
|
302
|
-
|
303
|
-
it 'returns nil if point is not within it or its children' do
|
304
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
305
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(false)
|
306
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
307
|
-
|
308
|
-
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
|
309
|
-
end
|
310
|
-
|
311
|
-
context 'with a mask child' do
|
312
|
-
it 'returns the parent if the child is hit' do
|
313
|
-
@child1.is_mask = true
|
314
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
315
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
316
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
317
|
-
|
318
|
-
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
|
319
|
-
@child1.is_mask = false
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
after(:all) do
|
324
|
-
@parent.children.each { |child| @parent.remove_child(child) }
|
325
|
-
end
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
describe '#get_actors_at' do
|
330
|
-
before(:all) do
|
331
|
-
@parent = Gosling::Actor.new(@window)
|
332
|
-
end
|
333
|
-
|
334
|
-
context 'when tangible is false' do
|
335
|
-
it 'returns an empty array even if hit' do
|
336
|
-
@parent.is_tangible = false
|
337
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
338
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be_empty
|
339
|
-
@parent.is_tangible = true
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
343
|
-
context 'with no children' do
|
344
|
-
it 'returns an array containing itself if the point is within its bounds' do
|
345
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
346
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
347
|
-
end
|
348
|
-
|
349
|
-
it 'returns an empty array if point is not within its bounds' do
|
350
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
351
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be_empty
|
352
|
-
end
|
353
|
-
end
|
354
|
-
|
355
|
-
context 'with two children' do
|
356
|
-
before(:all) do
|
357
|
-
@child1 = Gosling::Actor.new(@window)
|
358
|
-
@child2 = Gosling::Actor.new(@window)
|
359
|
-
@parent.add_child(@child1)
|
360
|
-
@parent.add_child(@child2)
|
361
|
-
end
|
362
|
-
|
363
|
-
context 'when the children are not tangible' do
|
364
|
-
it 'ignores the children' do
|
365
|
-
@parent.are_children_tangible = false
|
366
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
|
367
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
368
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(true, false)
|
369
|
-
|
370
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == []
|
371
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
372
|
-
@parent.are_children_tangible = true
|
373
|
-
end
|
374
|
-
end
|
375
|
-
|
376
|
-
it "returns an array containing all actors hit" do
|
377
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true, false, true, false, true, false, true)
|
378
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(false, false, true, true, false, false, true, true)
|
379
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(false, false, false, false, true, true, true, true)
|
380
|
-
|
381
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == []
|
382
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
383
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child1]
|
384
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child1, @parent]
|
385
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2]
|
386
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @parent]
|
387
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @child1]
|
388
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @child1, @parent]
|
389
|
-
end
|
390
|
-
|
391
|
-
context 'with a mask child' do
|
392
|
-
before(:all) do
|
393
|
-
@child1.is_mask = true
|
394
|
-
end
|
395
|
-
|
396
|
-
it 'returns the parent if the child is hit' do
|
397
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
398
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
399
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
400
|
-
|
401
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
402
|
-
end
|
403
|
-
|
404
|
-
it 'returns the parent only once if both children are masks and are hit' do
|
405
|
-
@child2.is_mask = true
|
406
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
407
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
408
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(true)
|
409
|
-
|
410
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
411
|
-
@child2.is_mask = false
|
412
|
-
end
|
413
|
-
|
414
|
-
it 'returns the parent only once if both parent and child are hit' do
|
415
|
-
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
416
|
-
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
417
|
-
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
418
|
-
|
419
|
-
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
420
|
-
end
|
421
|
-
|
422
|
-
after(:all) do
|
423
|
-
@child1.is_mask = false
|
424
|
-
end
|
425
|
-
end
|
426
|
-
|
427
|
-
after(:all) do
|
428
|
-
@parent.children.each { |child| @parent.remove_child(child) }
|
429
|
-
end
|
430
|
-
end
|
431
|
-
end
|
432
|
-
|
433
|
-
describe '#get_global_transform' do
|
434
|
-
it 'returns a 3x3 matrix' do
|
435
|
-
result = @parent.get_global_transform
|
436
|
-
expect(result).to be_instance_of(Snow::Mat3)
|
437
|
-
end
|
438
|
-
|
439
|
-
it 'is a composite of its own transform plus all of its ancestors' do
|
440
|
-
centered_view = Gosling::Actor.new(@window)
|
441
|
-
centered_view.center_x = 10
|
442
|
-
centered_view.center_y = 2
|
443
|
-
|
444
|
-
scaled_view = Gosling::Actor.new(@window)
|
445
|
-
scaled_view.scale_x = 3
|
446
|
-
scaled_view.scale_y = 2
|
447
|
-
|
448
|
-
rotated_view = Gosling::Actor.new(@window)
|
449
|
-
rotated_view.rotation = Math::PI / 4
|
450
|
-
|
451
|
-
translated_view = Gosling::Actor.new(@window)
|
452
|
-
translated_view.x = -50
|
453
|
-
translated_view.y = 10
|
454
|
-
|
455
|
-
centered_view.add_child(scaled_view)
|
456
|
-
scaled_view.add_child(rotated_view)
|
457
|
-
rotated_view.add_child(translated_view)
|
458
|
-
translated_view.add_child(@parent)
|
459
|
-
|
460
|
-
expected = @parent.to_matrix * translated_view.to_matrix * rotated_view.to_matrix * scaled_view.to_matrix * centered_view.to_matrix
|
461
|
-
|
462
|
-
result = @parent.get_global_transform
|
463
|
-
expect(result).to be == expected
|
464
|
-
|
465
|
-
translated_view.remove_child(@parent)
|
466
|
-
end
|
467
|
-
end
|
468
|
-
|
469
|
-
describe '#get_global_position' do
|
470
|
-
it 'returns a 3d vector' do
|
471
|
-
result = @parent.get_global_position
|
472
|
-
expect(result).to be_instance_of(Snow::Vec3)
|
473
|
-
end
|
474
|
-
|
475
|
-
context 'with a long ancestry' do
|
476
|
-
before do
|
477
|
-
@parent.x = 0
|
478
|
-
@parent.y = 0
|
479
|
-
@parent.center_x = 0
|
480
|
-
@parent.center_y = 0
|
481
|
-
@parent.scale_x = 1
|
482
|
-
@parent.scale_y = 1
|
483
|
-
@parent.rotation = 0
|
484
|
-
|
485
|
-
centered_view = Gosling::Actor.new(@window)
|
486
|
-
centered_view.center_x = 10
|
487
|
-
centered_view.center_y = 2
|
488
|
-
|
489
|
-
scaled_view = Gosling::Actor.new(@window)
|
490
|
-
scaled_view.scale_x = 3
|
491
|
-
scaled_view.scale_y = 2
|
492
|
-
|
493
|
-
rotated_view = Gosling::Actor.new(@window)
|
494
|
-
rotated_view.rotation = Math::PI / 2
|
495
|
-
|
496
|
-
translated_view = Gosling::Actor.new(@window)
|
497
|
-
translated_view.x = -50
|
498
|
-
translated_view.y = 10
|
499
|
-
|
500
|
-
centered_view.add_child(scaled_view)
|
501
|
-
scaled_view.add_child(rotated_view)
|
502
|
-
rotated_view.add_child(translated_view)
|
503
|
-
translated_view.add_child(@parent)
|
504
|
-
|
505
|
-
@ancestry = [
|
506
|
-
centered_view,
|
507
|
-
scaled_view,
|
508
|
-
rotated_view,
|
509
|
-
translated_view,
|
510
|
-
@parent
|
511
|
-
]
|
512
|
-
end
|
513
|
-
|
514
|
-
it 'respects all ancestors' do
|
515
|
-
result = @parent.get_global_position
|
516
|
-
expect(result).to be == Snow::Vec3[(0 + 10) * 3 - 10, (0 - 50) * -2 - 2, 0]
|
517
|
-
end
|
518
|
-
|
519
|
-
after do
|
520
|
-
@ancestry.each { |actor| actor.parent.remove_child(actor) if actor.parent }
|
521
|
-
end
|
522
|
-
end
|
523
|
-
end
|
524
|
-
|
525
|
-
describe '#alpha' do
|
526
|
-
it 'returns the alpha (transparency) value' do
|
527
|
-
expect(@parent.alpha).to be_kind_of(Numeric)
|
528
|
-
end
|
529
|
-
|
530
|
-
it 'sets the alpha (transparency) value' do
|
531
|
-
actor = Gosling::Actor.new(@window)
|
532
|
-
|
533
|
-
actor.alpha = 128
|
534
|
-
expect(actor.alpha).to be == 128
|
535
|
-
end
|
536
|
-
|
537
|
-
it 'forces numeric values to be between 0 and 255' do
|
538
|
-
actor = Gosling::Actor.new(@window)
|
539
|
-
|
540
|
-
actor.alpha = -128
|
541
|
-
expect(actor.alpha).to be == 0
|
542
|
-
actor.alpha = -1
|
543
|
-
expect(actor.alpha).to be == 0
|
544
|
-
actor.alpha = 256
|
545
|
-
expect(actor.alpha).to be == 255
|
546
|
-
actor.alpha = 1024
|
547
|
-
expect(actor.alpha).to be == 255
|
548
|
-
end
|
549
|
-
end
|
550
|
-
|
551
|
-
describe '#red' do
|
552
|
-
it 'returns the red value' do
|
553
|
-
expect(@parent.red).to be_kind_of(Numeric)
|
554
|
-
end
|
555
|
-
|
556
|
-
it 'sets the red value' do
|
557
|
-
actor = Gosling::Actor.new(@window)
|
558
|
-
|
559
|
-
actor.red = 128
|
560
|
-
expect(actor.red).to be == 128
|
561
|
-
end
|
562
|
-
|
563
|
-
it 'forces numeric values to be between 0 and 255' do
|
564
|
-
actor = Gosling::Actor.new(@window)
|
565
|
-
|
566
|
-
actor.red = -128
|
567
|
-
expect(actor.red).to be == 0
|
568
|
-
actor.red = -1
|
569
|
-
expect(actor.red).to be == 0
|
570
|
-
actor.red = 256
|
571
|
-
expect(actor.red).to be == 255
|
572
|
-
actor.red = 1024
|
573
|
-
expect(actor.red).to be == 255
|
574
|
-
end
|
575
|
-
end
|
576
|
-
|
577
|
-
describe '#green' do
|
578
|
-
it 'returns the green value' do
|
579
|
-
expect(@parent.green).to be_kind_of(Numeric)
|
580
|
-
end
|
581
|
-
|
582
|
-
it 'sets the green value' do
|
583
|
-
actor = Gosling::Actor.new(@window)
|
584
|
-
|
585
|
-
actor.green = 128
|
586
|
-
expect(actor.green).to be == 128
|
587
|
-
end
|
588
|
-
|
589
|
-
it 'forces numeric values to be between 0 and 255' do
|
590
|
-
actor = Gosling::Actor.new(@window)
|
591
|
-
|
592
|
-
actor.green = -128
|
593
|
-
expect(actor.green).to be == 0
|
594
|
-
actor.green = -1
|
595
|
-
expect(actor.green).to be == 0
|
596
|
-
actor.green = 256
|
597
|
-
expect(actor.green).to be == 255
|
598
|
-
actor.green = 1024
|
599
|
-
expect(actor.green).to be == 255
|
600
|
-
end
|
601
|
-
end
|
602
|
-
|
603
|
-
describe '#blue' do
|
604
|
-
it 'returns the blue value' do
|
605
|
-
expect(@parent.blue).to be_kind_of(Numeric)
|
606
|
-
end
|
607
|
-
|
608
|
-
it 'sets the blue value' do
|
609
|
-
actor = Gosling::Actor.new(@window)
|
610
|
-
|
611
|
-
actor.blue = 128
|
612
|
-
expect(actor.blue).to be == 128
|
613
|
-
end
|
614
|
-
|
615
|
-
it 'forces numeric values to be between 0 and 255' do
|
616
|
-
actor = Gosling::Actor.new(@window)
|
617
|
-
|
618
|
-
actor.blue = -128
|
619
|
-
expect(actor.blue).to be == 0
|
620
|
-
actor.blue = -1
|
621
|
-
expect(actor.blue).to be == 0
|
622
|
-
actor.blue = 256
|
623
|
-
expect(actor.blue).to be == 255
|
624
|
-
actor.blue = 1024
|
625
|
-
expect(actor.blue).to be == 255
|
626
|
-
end
|
627
|
-
end
|
1
|
+
module Gosling
|
2
|
+
class Actor
|
3
|
+
public :render
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Gosling::Actor do
|
8
|
+
before(:all) do
|
9
|
+
@window = Gosu::Window.new(640, 480, false)
|
10
|
+
@read_only_actor = Gosling::Actor.new(@window)
|
11
|
+
@parent = Gosling::Actor.new(@window)
|
12
|
+
@child = Gosling::Actor.new(@window)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#new' do
|
16
|
+
it 'requires a Gosu::Window' do
|
17
|
+
expect { Gosling::Actor.new(@window) }.not_to raise_error
|
18
|
+
expect { Gosling::Actor.new() }.to raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'has a transform' do
|
23
|
+
expect(@read_only_actor).to be_kind_of(Gosling::Transformable)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'can have a parent' do
|
27
|
+
expect { @read_only_actor.parent }.not_to raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it "does not initialize with a parent" do
|
31
|
+
expect(@read_only_actor.parent).to be == nil
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#add_child' do
|
35
|
+
it "creates a two-way parent/child link" do
|
36
|
+
@parent.add_child(@child)
|
37
|
+
expect(@parent.has_child?(@child)).to be true
|
38
|
+
expect(@child.parent).to be == @parent
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#remove_child' do
|
43
|
+
it "severs the two-way parent/child link" do
|
44
|
+
@parent.add_child(@child)
|
45
|
+
@parent.remove_child(@child)
|
46
|
+
expect(@parent.has_child?(@child)).to be false
|
47
|
+
expect(@child.parent).to be == nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'has a list of children' do
|
52
|
+
expect(@read_only_actor.children).to be_instance_of(Array)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "starts with no children" do
|
56
|
+
expect(@read_only_actor.children.empty?).to be true
|
57
|
+
end
|
58
|
+
|
59
|
+
it "knows if it has a particular child or not" do
|
60
|
+
expect(@read_only_actor.has_child?(Gosling::Actor.new(@window))).to be false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "will never add any of its ancestors as children" do
|
64
|
+
@parent.add_child(@child)
|
65
|
+
expect { @child.add_child(@parent) }.to raise_error(Gosling::InheritanceError)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "will not add itself as its own child" do
|
69
|
+
expect { @child.add_child(@child) }.to raise_error(Gosling::InheritanceError)
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when given a child" do
|
73
|
+
before do
|
74
|
+
@parent.add_child(@child)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "it forms a two-way link with that child" do
|
78
|
+
expect(@parent.has_child?(@child)).to be true
|
79
|
+
expect(@child.parent).to be == @parent
|
80
|
+
end
|
81
|
+
|
82
|
+
it "cannot be given the same child more than once" do
|
83
|
+
@parent.add_child(@child)
|
84
|
+
expect(@parent.children.length).to be == 1
|
85
|
+
end
|
86
|
+
|
87
|
+
context "and then the child is removed" do
|
88
|
+
before do
|
89
|
+
@parent.remove_child(@child)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "the parent/child link is broken" do
|
93
|
+
expect(@parent.has_child?(@child)).to be false
|
94
|
+
expect(@child.parent).to be == nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'and then adopted by another actor' do
|
99
|
+
it 'automatically breaks the old child/parent link' do
|
100
|
+
parent2 = Gosling::Actor.new(@window)
|
101
|
+
parent2.add_child(@child)
|
102
|
+
expect(@parent.has_child?(@child)).to be false
|
103
|
+
expect(@child.parent).to be == parent2
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'has a visibility flag' do
|
109
|
+
actor = Gosling::Actor.new(@window)
|
110
|
+
actor.is_visible = true
|
111
|
+
expect(actor.is_visible).to be true
|
112
|
+
actor.is_visible = false
|
113
|
+
expect(actor.is_visible).to be false
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'has a children visibility flag' do
|
117
|
+
actor = Gosling::Actor.new(@window)
|
118
|
+
actor.are_children_visible = true
|
119
|
+
expect(actor.are_children_visible).to be true
|
120
|
+
actor.are_children_visible = false
|
121
|
+
expect(actor.are_children_visible).to be false
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'has a tangible flag' do
|
125
|
+
actor = Gosling::Actor.new(@window)
|
126
|
+
actor.is_tangible = true
|
127
|
+
expect(actor.is_tangible).to be true
|
128
|
+
actor.is_tangible = false
|
129
|
+
expect(actor.is_tangible).to be false
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'has a children tangibile flag' do
|
133
|
+
actor = Gosling::Actor.new(@window)
|
134
|
+
actor.are_children_tangible = true
|
135
|
+
expect(actor.are_children_tangible).to be true
|
136
|
+
actor.are_children_tangible = false
|
137
|
+
expect(actor.are_children_tangible).to be false
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'has a mask flag' do
|
141
|
+
actor = Gosling::Actor.new(@window)
|
142
|
+
actor.is_mask = true
|
143
|
+
expect(actor.is_mask).to be true
|
144
|
+
actor.is_mask = false
|
145
|
+
expect(actor.is_mask).to be false
|
146
|
+
end
|
147
|
+
|
148
|
+
describe '#render' do
|
149
|
+
it 'the method exists' do
|
150
|
+
expect { @read_only_actor.render(Snow::Mat3.new) }.not_to raise_error
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#draw' do
|
155
|
+
before(:all) do
|
156
|
+
@draw_actor = Gosling::Actor.new(@window)
|
157
|
+
@mat = Snow::Mat3.new
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'when visible' do
|
161
|
+
it 'calls render on itself' do
|
162
|
+
@draw_actor.is_visible = true
|
163
|
+
expect(@draw_actor).to receive(:render).with(@mat).once
|
164
|
+
@draw_actor.draw(@mat)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'when not visible' do
|
169
|
+
it 'does not call render on itself' do
|
170
|
+
@draw_actor.is_visible = false
|
171
|
+
expect(@draw_actor).not_to receive(:render)
|
172
|
+
@draw_actor.draw(@mat)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context 'with children' do
|
177
|
+
before(:all) do
|
178
|
+
@child1 = Gosling::Actor.new(@window)
|
179
|
+
@child2 = Gosling::Actor.new(@window)
|
180
|
+
@draw_actor.add_child(@child1)
|
181
|
+
@draw_actor.add_child(@child2)
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'when are_children_visible is false' do
|
185
|
+
it 'draws itself, but not its children' do
|
186
|
+
@draw_actor.are_children_visible = false
|
187
|
+
expect(@child1).not_to receive(:draw)
|
188
|
+
expect(@child2).not_to receive(:draw)
|
189
|
+
@draw_actor.draw(@mat)
|
190
|
+
@draw_actor.are_children_visible = true
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'calls draw on each of its children' do
|
195
|
+
expect(@child1).to receive(:draw).with(@mat).once
|
196
|
+
expect(@child2).to receive(:draw).with(@mat).once
|
197
|
+
@draw_actor.draw(@mat)
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'passes its children a comprehensive transformation matrix' do
|
201
|
+
parameter_mat = Snow::Mat3[
|
202
|
+
1, 0, 10,
|
203
|
+
0, 1, 20,
|
204
|
+
0, 0, 1
|
205
|
+
]
|
206
|
+
self_mat = Snow::Mat3[
|
207
|
+
2, 0, 0,
|
208
|
+
0, 3, 0,
|
209
|
+
0, 0, 1
|
210
|
+
]
|
211
|
+
result_mat = self_mat * parameter_mat
|
212
|
+
|
213
|
+
allow(@draw_actor).to receive(:to_matrix).and_return(self_mat)
|
214
|
+
|
215
|
+
expect(@child1).to receive(:draw).with(result_mat).once
|
216
|
+
expect(@child2).to receive(:draw).with(result_mat).once
|
217
|
+
@draw_actor.draw(parameter_mat)
|
218
|
+
end
|
219
|
+
|
220
|
+
after(:all) do
|
221
|
+
@draw_actor.children.each { |child| @draw_actor.remove_child(@child) }
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
describe '#is_point_in_bounds' do
|
227
|
+
it 'returns false' do
|
228
|
+
expect(@read_only_actor.is_point_in_bounds(Snow::Vec3[0,0,1])).to be false
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe '#get_actor_at' do
|
233
|
+
before(:all) do
|
234
|
+
@parent = Gosling::Actor.new(@window)
|
235
|
+
end
|
236
|
+
|
237
|
+
context 'when tangible is false' do
|
238
|
+
it 'returns nil even if hit' do
|
239
|
+
@parent.is_tangible = false
|
240
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
241
|
+
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
|
242
|
+
@parent.is_tangible = true
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context 'with no children' do
|
247
|
+
it 'returns itself if the point is within its bounds' do
|
248
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
249
|
+
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
|
250
|
+
end
|
251
|
+
|
252
|
+
it 'returns nil if point is not within its bounds' do
|
253
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
254
|
+
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context 'with two children' do
|
259
|
+
before(:all) do
|
260
|
+
@child1 = Gosling::Actor.new(@window)
|
261
|
+
@child2 = Gosling::Actor.new(@window)
|
262
|
+
@parent.add_child(@child1)
|
263
|
+
@parent.add_child(@child2)
|
264
|
+
end
|
265
|
+
|
266
|
+
context 'when the children are not tangible' do
|
267
|
+
it 'does not hit test any children' do
|
268
|
+
@parent.are_children_tangible = false
|
269
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
|
270
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
271
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(true)
|
272
|
+
|
273
|
+
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
|
274
|
+
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
|
275
|
+
@parent.are_children_tangible = true
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
it "returns the second child if such is hit" do
|
280
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true, false, true)
|
281
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(false, false, true, true)
|
282
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(true)
|
283
|
+
|
284
|
+
4.times { expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @child2 }
|
285
|
+
end
|
286
|
+
|
287
|
+
it "returns the first child if the second was not hit" do
|
288
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
|
289
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
290
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
291
|
+
|
292
|
+
2.times { expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @child1 }
|
293
|
+
end
|
294
|
+
|
295
|
+
it "returns itself if neither child was hit" do
|
296
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
297
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(false)
|
298
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
299
|
+
|
300
|
+
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'returns nil if point is not within it or its children' do
|
304
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
305
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(false)
|
306
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
307
|
+
|
308
|
+
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == nil
|
309
|
+
end
|
310
|
+
|
311
|
+
context 'with a mask child' do
|
312
|
+
it 'returns the parent if the child is hit' do
|
313
|
+
@child1.is_mask = true
|
314
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
315
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
316
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
317
|
+
|
318
|
+
expect(@parent.get_actor_at(Snow::Vec3[0,0,1])).to be == @parent
|
319
|
+
@child1.is_mask = false
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
after(:all) do
|
324
|
+
@parent.children.each { |child| @parent.remove_child(child) }
|
325
|
+
end
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
describe '#get_actors_at' do
|
330
|
+
before(:all) do
|
331
|
+
@parent = Gosling::Actor.new(@window)
|
332
|
+
end
|
333
|
+
|
334
|
+
context 'when tangible is false' do
|
335
|
+
it 'returns an empty array even if hit' do
|
336
|
+
@parent.is_tangible = false
|
337
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
338
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be_empty
|
339
|
+
@parent.is_tangible = true
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
context 'with no children' do
|
344
|
+
it 'returns an array containing itself if the point is within its bounds' do
|
345
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
346
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
347
|
+
end
|
348
|
+
|
349
|
+
it 'returns an empty array if point is not within its bounds' do
|
350
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
351
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be_empty
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
context 'with two children' do
|
356
|
+
before(:all) do
|
357
|
+
@child1 = Gosling::Actor.new(@window)
|
358
|
+
@child2 = Gosling::Actor.new(@window)
|
359
|
+
@parent.add_child(@child1)
|
360
|
+
@parent.add_child(@child2)
|
361
|
+
end
|
362
|
+
|
363
|
+
context 'when the children are not tangible' do
|
364
|
+
it 'ignores the children' do
|
365
|
+
@parent.are_children_tangible = false
|
366
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true)
|
367
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
368
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(true, false)
|
369
|
+
|
370
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == []
|
371
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
372
|
+
@parent.are_children_tangible = true
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
it "returns an array containing all actors hit" do
|
377
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false, true, false, true, false, true, false, true)
|
378
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(false, false, true, true, false, false, true, true)
|
379
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(false, false, false, false, true, true, true, true)
|
380
|
+
|
381
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == []
|
382
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
383
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child1]
|
384
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child1, @parent]
|
385
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2]
|
386
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @parent]
|
387
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @child1]
|
388
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@child2, @child1, @parent]
|
389
|
+
end
|
390
|
+
|
391
|
+
context 'with a mask child' do
|
392
|
+
before(:all) do
|
393
|
+
@child1.is_mask = true
|
394
|
+
end
|
395
|
+
|
396
|
+
it 'returns the parent if the child is hit' do
|
397
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
398
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
399
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
400
|
+
|
401
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
402
|
+
end
|
403
|
+
|
404
|
+
it 'returns the parent only once if both children are masks and are hit' do
|
405
|
+
@child2.is_mask = true
|
406
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(false)
|
407
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
408
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(true)
|
409
|
+
|
410
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
411
|
+
@child2.is_mask = false
|
412
|
+
end
|
413
|
+
|
414
|
+
it 'returns the parent only once if both parent and child are hit' do
|
415
|
+
allow(@parent).to receive(:is_point_in_bounds).and_return(true)
|
416
|
+
allow(@child1).to receive(:is_point_in_bounds).and_return(true)
|
417
|
+
allow(@child2).to receive(:is_point_in_bounds).and_return(false)
|
418
|
+
|
419
|
+
expect(@parent.get_actors_at(Snow::Vec3[0,0,1])).to be == [@parent]
|
420
|
+
end
|
421
|
+
|
422
|
+
after(:all) do
|
423
|
+
@child1.is_mask = false
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
after(:all) do
|
428
|
+
@parent.children.each { |child| @parent.remove_child(child) }
|
429
|
+
end
|
430
|
+
end
|
431
|
+
end
|
432
|
+
|
433
|
+
describe '#get_global_transform' do
|
434
|
+
it 'returns a 3x3 matrix' do
|
435
|
+
result = @parent.get_global_transform
|
436
|
+
expect(result).to be_instance_of(Snow::Mat3)
|
437
|
+
end
|
438
|
+
|
439
|
+
it 'is a composite of its own transform plus all of its ancestors' do
|
440
|
+
centered_view = Gosling::Actor.new(@window)
|
441
|
+
centered_view.center_x = 10
|
442
|
+
centered_view.center_y = 2
|
443
|
+
|
444
|
+
scaled_view = Gosling::Actor.new(@window)
|
445
|
+
scaled_view.scale_x = 3
|
446
|
+
scaled_view.scale_y = 2
|
447
|
+
|
448
|
+
rotated_view = Gosling::Actor.new(@window)
|
449
|
+
rotated_view.rotation = Math::PI / 4
|
450
|
+
|
451
|
+
translated_view = Gosling::Actor.new(@window)
|
452
|
+
translated_view.x = -50
|
453
|
+
translated_view.y = 10
|
454
|
+
|
455
|
+
centered_view.add_child(scaled_view)
|
456
|
+
scaled_view.add_child(rotated_view)
|
457
|
+
rotated_view.add_child(translated_view)
|
458
|
+
translated_view.add_child(@parent)
|
459
|
+
|
460
|
+
expected = @parent.to_matrix * translated_view.to_matrix * rotated_view.to_matrix * scaled_view.to_matrix * centered_view.to_matrix
|
461
|
+
|
462
|
+
result = @parent.get_global_transform
|
463
|
+
expect(result).to be == expected
|
464
|
+
|
465
|
+
translated_view.remove_child(@parent)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
describe '#get_global_position' do
|
470
|
+
it 'returns a 3d vector' do
|
471
|
+
result = @parent.get_global_position
|
472
|
+
expect(result).to be_instance_of(Snow::Vec3)
|
473
|
+
end
|
474
|
+
|
475
|
+
context 'with a long ancestry' do
|
476
|
+
before do
|
477
|
+
@parent.x = 0
|
478
|
+
@parent.y = 0
|
479
|
+
@parent.center_x = 0
|
480
|
+
@parent.center_y = 0
|
481
|
+
@parent.scale_x = 1
|
482
|
+
@parent.scale_y = 1
|
483
|
+
@parent.rotation = 0
|
484
|
+
|
485
|
+
centered_view = Gosling::Actor.new(@window)
|
486
|
+
centered_view.center_x = 10
|
487
|
+
centered_view.center_y = 2
|
488
|
+
|
489
|
+
scaled_view = Gosling::Actor.new(@window)
|
490
|
+
scaled_view.scale_x = 3
|
491
|
+
scaled_view.scale_y = 2
|
492
|
+
|
493
|
+
rotated_view = Gosling::Actor.new(@window)
|
494
|
+
rotated_view.rotation = Math::PI / 2
|
495
|
+
|
496
|
+
translated_view = Gosling::Actor.new(@window)
|
497
|
+
translated_view.x = -50
|
498
|
+
translated_view.y = 10
|
499
|
+
|
500
|
+
centered_view.add_child(scaled_view)
|
501
|
+
scaled_view.add_child(rotated_view)
|
502
|
+
rotated_view.add_child(translated_view)
|
503
|
+
translated_view.add_child(@parent)
|
504
|
+
|
505
|
+
@ancestry = [
|
506
|
+
centered_view,
|
507
|
+
scaled_view,
|
508
|
+
rotated_view,
|
509
|
+
translated_view,
|
510
|
+
@parent
|
511
|
+
]
|
512
|
+
end
|
513
|
+
|
514
|
+
it 'respects all ancestors' do
|
515
|
+
result = @parent.get_global_position
|
516
|
+
expect(result).to be == Snow::Vec3[(0 + 10) * 3 - 10, (0 - 50) * -2 - 2, 0]
|
517
|
+
end
|
518
|
+
|
519
|
+
after do
|
520
|
+
@ancestry.each { |actor| actor.parent.remove_child(actor) if actor.parent }
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
describe '#alpha' do
|
526
|
+
it 'returns the alpha (transparency) value' do
|
527
|
+
expect(@parent.alpha).to be_kind_of(Numeric)
|
528
|
+
end
|
529
|
+
|
530
|
+
it 'sets the alpha (transparency) value' do
|
531
|
+
actor = Gosling::Actor.new(@window)
|
532
|
+
|
533
|
+
actor.alpha = 128
|
534
|
+
expect(actor.alpha).to be == 128
|
535
|
+
end
|
536
|
+
|
537
|
+
it 'forces numeric values to be between 0 and 255' do
|
538
|
+
actor = Gosling::Actor.new(@window)
|
539
|
+
|
540
|
+
actor.alpha = -128
|
541
|
+
expect(actor.alpha).to be == 0
|
542
|
+
actor.alpha = -1
|
543
|
+
expect(actor.alpha).to be == 0
|
544
|
+
actor.alpha = 256
|
545
|
+
expect(actor.alpha).to be == 255
|
546
|
+
actor.alpha = 1024
|
547
|
+
expect(actor.alpha).to be == 255
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
describe '#red' do
|
552
|
+
it 'returns the red value' do
|
553
|
+
expect(@parent.red).to be_kind_of(Numeric)
|
554
|
+
end
|
555
|
+
|
556
|
+
it 'sets the red value' do
|
557
|
+
actor = Gosling::Actor.new(@window)
|
558
|
+
|
559
|
+
actor.red = 128
|
560
|
+
expect(actor.red).to be == 128
|
561
|
+
end
|
562
|
+
|
563
|
+
it 'forces numeric values to be between 0 and 255' do
|
564
|
+
actor = Gosling::Actor.new(@window)
|
565
|
+
|
566
|
+
actor.red = -128
|
567
|
+
expect(actor.red).to be == 0
|
568
|
+
actor.red = -1
|
569
|
+
expect(actor.red).to be == 0
|
570
|
+
actor.red = 256
|
571
|
+
expect(actor.red).to be == 255
|
572
|
+
actor.red = 1024
|
573
|
+
expect(actor.red).to be == 255
|
574
|
+
end
|
575
|
+
end
|
576
|
+
|
577
|
+
describe '#green' do
|
578
|
+
it 'returns the green value' do
|
579
|
+
expect(@parent.green).to be_kind_of(Numeric)
|
580
|
+
end
|
581
|
+
|
582
|
+
it 'sets the green value' do
|
583
|
+
actor = Gosling::Actor.new(@window)
|
584
|
+
|
585
|
+
actor.green = 128
|
586
|
+
expect(actor.green).to be == 128
|
587
|
+
end
|
588
|
+
|
589
|
+
it 'forces numeric values to be between 0 and 255' do
|
590
|
+
actor = Gosling::Actor.new(@window)
|
591
|
+
|
592
|
+
actor.green = -128
|
593
|
+
expect(actor.green).to be == 0
|
594
|
+
actor.green = -1
|
595
|
+
expect(actor.green).to be == 0
|
596
|
+
actor.green = 256
|
597
|
+
expect(actor.green).to be == 255
|
598
|
+
actor.green = 1024
|
599
|
+
expect(actor.green).to be == 255
|
600
|
+
end
|
601
|
+
end
|
602
|
+
|
603
|
+
describe '#blue' do
|
604
|
+
it 'returns the blue value' do
|
605
|
+
expect(@parent.blue).to be_kind_of(Numeric)
|
606
|
+
end
|
607
|
+
|
608
|
+
it 'sets the blue value' do
|
609
|
+
actor = Gosling::Actor.new(@window)
|
610
|
+
|
611
|
+
actor.blue = 128
|
612
|
+
expect(actor.blue).to be == 128
|
613
|
+
end
|
614
|
+
|
615
|
+
it 'forces numeric values to be between 0 and 255' do
|
616
|
+
actor = Gosling::Actor.new(@window)
|
617
|
+
|
618
|
+
actor.blue = -128
|
619
|
+
expect(actor.blue).to be == 0
|
620
|
+
actor.blue = -1
|
621
|
+
expect(actor.blue).to be == 0
|
622
|
+
actor.blue = 256
|
623
|
+
expect(actor.blue).to be == 255
|
624
|
+
actor.blue = 1024
|
625
|
+
expect(actor.blue).to be == 255
|
626
|
+
end
|
627
|
+
end
|
628
628
|
end
|