gosling 2.3.0 → 2.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f40ad4e1b06a4aeb3653172b748bb6b9cff0aaec
4
- data.tar.gz: '0249b7dbe396d152de3791ad3e5548ffad9c8ece'
2
+ SHA256:
3
+ metadata.gz: ac651ebce37fb5da3aacc1ced63789b6d9651c5ce8c0c112e9380e6d1ecdafd3
4
+ data.tar.gz: f3dada919c44fe16a49811bbb8e823257713e6042b858727737220f5d59f647e
5
5
  SHA512:
6
- metadata.gz: 05a6efbacdee880176e86660408c0d005d0e32e86e1eca91a213e1552dfdbccfe40edf43d167669e0684690d2280299ce49448d2f3719b7604bb037c683e6a49
7
- data.tar.gz: b5670a5dace288c80bb8ba339cbba83b171d1e0ec8d104b2ba327792e550dc4957783ec0ee710940bc45c115af4f40d958bf77563b7711b6a248fd31ed5a933b
6
+ metadata.gz: d31bf801d211beef278199b322efeda3286cebb3951cc1f23f64e063b0b87367f82bd345d1fe6bb4aaca5415afc4b315eb39d89b706261cd8cf49a42c7032283
7
+ data.tar.gz: fe40452705018052c180a3c9dd1f0b2a961347d83361ee83c0fa9c8c173043b747c632f89d12f152b10e97b28c5e155ef87ac832685477c39bc823ffe1eb7abc
data/lib/gosling.rb CHANGED
@@ -1,4 +1,4 @@
1
- Dir.glob(File.join(File.dirname(__FILE__), 'gosling/*.rb')).each { |file| require_relative file }
2
-
3
- module Gosling
4
- end
1
+ Dir.glob(File.join(File.dirname(__FILE__), 'gosling/*.rb')).each { |file| require_relative file }
2
+
3
+ module Gosling
4
+ end
data/lib/gosling/actor.rb CHANGED
@@ -1,328 +1,328 @@
1
- require_relative 'transformable.rb'
2
-
3
- require 'gosu'
4
-
5
- module Gosling
6
- ##
7
- # Actors are fundamental elements of a rendering and worldspace hierarchy. They represent the things that exist
8
- # inside of the game world or parts of our application's user interface.
9
- #
10
- # A key difference between an Actor and any of its subclasses - Circle, Polygon, Sprite, and the like - is that an
11
- # Actor is inherently intangible. By itself, it has no shape or appearance and takes up no space. If it's something you
12
- # can see or interact with, it should probably be an instance of one of Actor's subclasses.
13
- #
14
- # The inheritance model is what makes an Actor by itself useful. Actors can have one or more children, which can be
15
- # any type of Actor. Those Actors can in turn have any number of child Actors, and so on, creating a sort of tree
16
- # structure. A parent Actor's transform is inherited by its children, so moving or rotating a parent Actor moves or
17
- # rotates all of its children relative to its parent. And when a parent is drawn, all of its children are drawn as well
18
- # (see #draw for exceptions).
19
- #
20
- # One common application of this is to use a plain Actor as a root object to which all other elements visible in the
21
- # game world are added. As the player moves through the game world, rather than move the position of each game
22
- # element across the screen to simulate travel, you need only move the root Actor and all other Actors will be moved
23
- # similarly. This root actor then acts like a "stage" or "camera". For this reason, one could think of a plain Actor as
24
- # sort of a "container" for other Actors, a way to keep them all organized and related.
25
- #
26
- # The behavior of inheritance can modified by setting various properties. Read on for more details.
27
- #
28
- class Actor
29
- include Transformable
30
-
31
- attr_reader :parent, :children, :window
32
-
33
- ##
34
- # If set to true, this Actor will be drawn to screen. If false, it will be skipped. The default is true.
35
- #
36
- attr_accessor :is_visible
37
-
38
- ##
39
- # If set to true, this Actor will respond to "point-in-shape" tests. If false, such tests will skip this Actor. The default
40
- # is true.
41
- #
42
- attr_accessor :is_tangible
43
-
44
- ##
45
- # If set to true, all of this Actor's children will be drawn to screen. If false, they and their descendants will be
46
- # skipped. The default is true.
47
- #
48
- attr_accessor :are_children_visible
49
-
50
- ##
51
- # If set to true, this Actor's children will respond to "point-in-shape" tests. If false, such tests will skip them and
52
- # their descendants. The default is true.
53
- #
54
- attr_accessor :are_children_tangible
55
-
56
- ##
57
- # If set to true, this Actor will be treated as a "mask" for its parent regarding "point-in-shape" tests. If the point is
58
- # in this Actor's bounds, it will act as though the point is in its parent's bounds instead of its own. The default is
59
- # false.
60
- #
61
- attr_accessor :is_mask
62
-
63
- ##
64
- # The Gosu::Color to use when rendering this Actor.
65
- #
66
- attr_accessor :color
67
-
68
- ##
69
- # Creates a new Actor, setting all inheritance properties to their defaults and assigning a random color. Requires
70
- # a Gosu::Window to be used when rendering.
71
- #
72
- def initialize(window)
73
- super()
74
- @window = window
75
- @parent = nil
76
- @children = []
77
- @is_visible = true
78
- @is_tangible = true
79
- @are_children_visible = true
80
- @are_children_tangible = true
81
- @is_mask = false
82
- @color = Gosu::Color.from_hsv(rand(360), rand(), rand())
83
- end
84
-
85
- def inspect
86
- "#<#{self.class}:#{self.object_id}>"
87
- end
88
-
89
- ##
90
- # Establishes a parent/child relationship between this actor and the one passed, respectively. The child Actor will
91
- # appear relative to its parent, move as the parent moves, and draw when the parent draws.
92
- #
93
- # An Actor cannot be made a child of itself. Similarly, a child cannot be added to a parent if doing so would create
94
- # a circular reference (e.g. a.add_child(b) followed by b.add_child(a)).
95
- #
96
- # If the child Actor already had a parent, the Actor is disassociated from its former parent before becoming
97
- # associated with this one. An Actor can have only one parent at a time.
98
- #
99
- def add_child(child)
100
- return if @children.include?(child)
101
- raise Gosling::InheritanceError.new("An Actor cannot be made a child of itself.") if child == self
102
- ancestor = parent
103
- until ancestor.nil?
104
- raise Gosling::InheritanceError.new("Adding a child's ancestor as a child would create a circular reference.") if child == ancestor
105
- ancestor = ancestor.parent
106
- end
107
-
108
- child.parent.remove_child(child) if child.parent
109
- @children.push(child)
110
- child.parent = self
111
- end
112
-
113
- ##
114
- # If the given Actor is a child of this Actor, it is disassociated from this Actor. In any case, the child Actor is
115
- # immediately orphaned.
116
- #
117
- def remove_child(child)
118
- return unless @children.include?(child)
119
-
120
- @children.delete(child)
121
- child.parent = nil
122
- end
123
-
124
- ##
125
- # Returns true if this Actor has the given Actor as a child.
126
- #
127
- def has_child?(child)
128
- @children.include?(child)
129
- end
130
-
131
- ##
132
- # Calls #render on this Actor, drawing it to the screen if #is_visible is set to true (the default).
133
- #
134
- # The Actor's transforms, if any, will be applied prior to rendering. If an optional Snow::Mat3 matrix transform is
135
- # given, the Actor will be transformed by a combination of that matrix transform and its own.
136
- #
137
- # If the #are_children_visible flag is set to true (the default), then this method will recursively call draw on each
138
- # of the Actor's children, passing them the combined matrix used to render the parent. Otherwise, children will
139
- # be skipped and not drawn.
140
- #
141
- def draw(matrix = nil)
142
- transform = MatrixCache.instance.get
143
- if matrix
144
- to_matrix.multiply(matrix, transform)
145
- else
146
- transform.set(to_matrix)
147
- end
148
-
149
- render(transform) if @is_visible
150
- if @are_children_visible
151
- @children.each { |child| child.draw(transform) }
152
- end
153
- ensure
154
- MatrixCache.instance.recycle(transform)
155
- end
156
-
157
- ##
158
- # Returns false. Actors have no shape, and so no point is in their bounds. Subclasses override this method with
159
- # shape-specific behavior.
160
- #
161
- def is_point_in_bounds(point)
162
- false
163
- end
164
-
165
- ##
166
- # Given a point in global space, tests this Actor and each of its children, returning the first Actor for whom this
167
- # point is inside its shape. Respects each Actor's transforms as well as any it may inherit from its ancestors.
168
- # Useful for determining which Actor the user may have clicked on.
169
- #
170
- # If the #is_tangible flag is set to false, this Actor will not be tested. The default is true.
171
- #
172
- # If the #are_children_tangible flag is set to false, this Actor's children will not be tested. The default is true.
173
- #
174
- # If the #is_mask flag is set to true, a positive test from this Actor instead returns its parent Actor, if any. The
175
- # default is false.
176
- #
177
- # If the point is not inside this Actor or any of its children (excluding any skipped Actors), nil is returned.
178
- #
179
- def get_actor_at(point)
180
- hit = nil
181
- if @are_children_tangible
182
- @children.reverse_each do |child|
183
- hit = child.get_actor_at(point)
184
- if hit
185
- break if @is_mask
186
- return hit
187
- end
188
- end
189
- end
190
- hit = self if hit == nil && @is_tangible && is_point_in_bounds(point)
191
- hit = @parent if @is_mask && hit == self
192
- hit
193
- end
194
-
195
- ##
196
- # Functions similarly to #get_actor_at, but returns a list of +all+ Actors for whom the point is inside their shape.
197
- #
198
- def get_actors_at(point)
199
- actors = []
200
- if @are_children_tangible
201
- @children.reverse_each do |child|
202
- actors |= child.get_actors_at(point)
203
- end
204
- end
205
- actors.push(self) if @is_tangible && is_point_in_bounds(point)
206
- actors.uniq!
207
- if @is_mask
208
- actors.map! { |actor| (actor == self) ? @parent : actor }
209
- end
210
- actors
211
- end
212
-
213
- ##
214
- # Returns a Snow::Mat3 transformation matrix combining this Actor's transforms as well as all of its ancestors.
215
- # This matrix can be used to transform a point in this Actor's local space to its global equivalent (the geometric
216
- # space of its root ancestor).
217
- #
218
- def get_global_transform(out = nil)
219
- out ||= Snow::Mat3.new
220
- if parent
221
- to_matrix.multiply(parent.get_global_transform, out)
222
- else
223
- out.set(to_matrix)
224
- end
225
- end
226
-
227
- ##
228
- # Returns the global x/y position of this actor (where it is relative to its root ancestor). This value is calculated
229
- # using the Actor's center (see Transformable#center).
230
- #
231
- def get_global_position(out = nil)
232
- tf = MatrixCache.instance.get
233
- get_global_transform(tf)
234
- out ||= Snow::Vec3.new
235
- Transformable.transform_point(tf, center, out)
236
- ensure
237
- MatrixCache.instance.recycle(tf)
238
- end
239
-
240
- ##
241
- # Wrapper method. Returns this Actor's alpha value (0-255).
242
- #
243
- def alpha
244
- @color.alpha
245
- end
246
-
247
- ##
248
- # Wrapper method. Sets this Actor's alpha value (0-255).
249
- #
250
- def alpha=(val)
251
- @color.alpha = val
252
- end
253
-
254
- ##
255
- # Wrapper method. Returns this Actor's red value (0-255).
256
- #
257
- def red
258
- @color.red
259
- end
260
-
261
- ##
262
- # Wrapper method. Sets this Actor's red value (0-255).
263
- #
264
- def red=(val)
265
- @color.red = val
266
- end
267
-
268
- ##
269
- # Wrapper method. Returns this Actor's green value (0-255).
270
- #
271
- def green
272
- @color.green
273
- end
274
-
275
- ##
276
- # Wrapper method. Sets this Actor's green value (0-255).
277
- #
278
- def green=(val)
279
- @color.green = val
280
- end
281
-
282
- ##
283
- # Wrapper method. Returns this Actor's blue value (0-255).
284
- #
285
- def blue
286
- @color.blue
287
- end
288
-
289
- ##
290
- # Wrapper method. Sets this Actor's blue value (0-255).
291
- #
292
- def blue=(val)
293
- @color.blue = val
294
- end
295
-
296
- protected
297
-
298
- def render(matrix)
299
- end
300
-
301
- def fill_polygon(vertices)
302
- (2...vertices.length).each do |i|
303
- v0 = vertices[0]
304
- v1 = vertices[i - 1]
305
- v2 = vertices[i]
306
- @window.draw_triangle(
307
- v0[0].to_f, v0[1].to_f, @color,
308
- v1[0].to_f, v1[1].to_f, @color,
309
- v2[0].to_f, v2[1].to_f, @color,
310
- )
311
- end
312
- end
313
-
314
- ##
315
- # Internal use only. See #add_child and #remove_child.
316
- #
317
- def parent=(parent)
318
- return if parent == @parent
319
- unless parent
320
- raise Gosling::InheritanceError.new("You should use Actor.remove_child() instead of setting the parent directly.") if @parent.has_child?(self)
321
- end
322
- @parent = parent
323
- if @parent
324
- raise Gosling::InheritanceError.new("You should use Actor.add_child() instead of setting the parent directly.") unless @parent.has_child?(self)
325
- end
326
- end
327
- end
328
- end
1
+ require_relative 'transformable.rb'
2
+
3
+ require 'gosu'
4
+
5
+ module Gosling
6
+ ##
7
+ # Actors are fundamental elements of a rendering and worldspace hierarchy. They represent the things that exist
8
+ # inside of the game world or parts of our application's user interface.
9
+ #
10
+ # A key difference between an Actor and any of its subclasses - Circle, Polygon, Sprite, and the like - is that an
11
+ # Actor is inherently intangible. By itself, it has no shape or appearance and takes up no space. If it's something you
12
+ # can see or interact with, it should probably be an instance of one of Actor's subclasses.
13
+ #
14
+ # The inheritance model is what makes an Actor by itself useful. Actors can have one or more children, which can be
15
+ # any type of Actor. Those Actors can in turn have any number of child Actors, and so on, creating a sort of tree
16
+ # structure. A parent Actor's transform is inherited by its children, so moving or rotating a parent Actor moves or
17
+ # rotates all of its children relative to its parent. And when a parent is drawn, all of its children are drawn as well
18
+ # (see #draw for exceptions).
19
+ #
20
+ # One common application of this is to use a plain Actor as a root object to which all other elements visible in the
21
+ # game world are added. As the player moves through the game world, rather than move the position of each game
22
+ # element across the screen to simulate travel, you need only move the root Actor and all other Actors will be moved
23
+ # similarly. This root actor then acts like a "stage" or "camera". For this reason, one could think of a plain Actor as
24
+ # sort of a "container" for other Actors, a way to keep them all organized and related.
25
+ #
26
+ # The behavior of inheritance can modified by setting various properties. Read on for more details.
27
+ #
28
+ class Actor
29
+ include Transformable
30
+
31
+ attr_reader :parent, :children, :window
32
+
33
+ ##
34
+ # If set to true, this Actor will be drawn to screen. If false, it will be skipped. The default is true.
35
+ #
36
+ attr_accessor :is_visible
37
+
38
+ ##
39
+ # If set to true, this Actor will respond to "point-in-shape" tests. If false, such tests will skip this Actor. The default
40
+ # is true.
41
+ #
42
+ attr_accessor :is_tangible
43
+
44
+ ##
45
+ # If set to true, all of this Actor's children will be drawn to screen. If false, they and their descendants will be
46
+ # skipped. The default is true.
47
+ #
48
+ attr_accessor :are_children_visible
49
+
50
+ ##
51
+ # If set to true, this Actor's children will respond to "point-in-shape" tests. If false, such tests will skip them and
52
+ # their descendants. The default is true.
53
+ #
54
+ attr_accessor :are_children_tangible
55
+
56
+ ##
57
+ # If set to true, this Actor will be treated as a "mask" for its parent regarding "point-in-shape" tests. If the point is
58
+ # in this Actor's bounds, it will act as though the point is in its parent's bounds instead of its own. The default is
59
+ # false.
60
+ #
61
+ attr_accessor :is_mask
62
+
63
+ ##
64
+ # The Gosu::Color to use when rendering this Actor.
65
+ #
66
+ attr_accessor :color
67
+
68
+ ##
69
+ # Creates a new Actor, setting all inheritance properties to their defaults and assigning a random color. Requires
70
+ # a Gosu::Window to be used when rendering.
71
+ #
72
+ def initialize(window)
73
+ super()
74
+ @window = window
75
+ @parent = nil
76
+ @children = []
77
+ @is_visible = true
78
+ @is_tangible = true
79
+ @are_children_visible = true
80
+ @are_children_tangible = true
81
+ @is_mask = false
82
+ @color = Gosu::Color.from_hsv(rand(360), rand(), rand())
83
+ end
84
+
85
+ def inspect
86
+ "#<#{self.class}:#{self.object_id}>"
87
+ end
88
+
89
+ ##
90
+ # Establishes a parent/child relationship between this actor and the one passed, respectively. The child Actor will
91
+ # appear relative to its parent, move as the parent moves, and draw when the parent draws.
92
+ #
93
+ # An Actor cannot be made a child of itself. Similarly, a child cannot be added to a parent if doing so would create
94
+ # a circular reference (e.g. a.add_child(b) followed by b.add_child(a)).
95
+ #
96
+ # If the child Actor already had a parent, the Actor is disassociated from its former parent before becoming
97
+ # associated with this one. An Actor can have only one parent at a time.
98
+ #
99
+ def add_child(child)
100
+ return if @children.include?(child)
101
+ raise Gosling::InheritanceError.new("An Actor cannot be made a child of itself.") if child == self
102
+ ancestor = parent
103
+ until ancestor.nil?
104
+ raise Gosling::InheritanceError.new("Adding a child's ancestor as a child would create a circular reference.") if child == ancestor
105
+ ancestor = ancestor.parent
106
+ end
107
+
108
+ child.parent.remove_child(child) if child.parent
109
+ @children.push(child)
110
+ child.parent = self
111
+ end
112
+
113
+ ##
114
+ # If the given Actor is a child of this Actor, it is disassociated from this Actor. In any case, the child Actor is
115
+ # immediately orphaned.
116
+ #
117
+ def remove_child(child)
118
+ return unless @children.include?(child)
119
+
120
+ @children.delete(child)
121
+ child.parent = nil
122
+ end
123
+
124
+ ##
125
+ # Returns true if this Actor has the given Actor as a child.
126
+ #
127
+ def has_child?(child)
128
+ @children.include?(child)
129
+ end
130
+
131
+ ##
132
+ # Calls #render on this Actor, drawing it to the screen if #is_visible is set to true (the default).
133
+ #
134
+ # The Actor's transforms, if any, will be applied prior to rendering. If an optional Snow::Mat3 matrix transform is
135
+ # given, the Actor will be transformed by a combination of that matrix transform and its own.
136
+ #
137
+ # If the #are_children_visible flag is set to true (the default), then this method will recursively call draw on each
138
+ # of the Actor's children, passing them the combined matrix used to render the parent. Otherwise, children will
139
+ # be skipped and not drawn.
140
+ #
141
+ def draw(matrix = nil)
142
+ transform = MatrixCache.instance.get
143
+ if matrix
144
+ to_matrix.multiply(matrix, transform)
145
+ else
146
+ transform.set(to_matrix)
147
+ end
148
+
149
+ render(transform) if @is_visible
150
+ if @are_children_visible
151
+ @children.each { |child| child.draw(transform) }
152
+ end
153
+ ensure
154
+ MatrixCache.instance.recycle(transform)
155
+ end
156
+
157
+ ##
158
+ # Returns false. Actors have no shape, and so no point is in their bounds. Subclasses override this method with
159
+ # shape-specific behavior.
160
+ #
161
+ def is_point_in_bounds(point)
162
+ false
163
+ end
164
+
165
+ ##
166
+ # Given a point in global space, tests this Actor and each of its children, returning the first Actor for whom this
167
+ # point is inside its shape. Respects each Actor's transforms as well as any it may inherit from its ancestors.
168
+ # Useful for determining which Actor the user may have clicked on.
169
+ #
170
+ # If the #is_tangible flag is set to false, this Actor will not be tested. The default is true.
171
+ #
172
+ # If the #are_children_tangible flag is set to false, this Actor's children will not be tested. The default is true.
173
+ #
174
+ # If the #is_mask flag is set to true, a positive test from this Actor instead returns its parent Actor, if any. The
175
+ # default is false.
176
+ #
177
+ # If the point is not inside this Actor or any of its children (excluding any skipped Actors), nil is returned.
178
+ #
179
+ def get_actor_at(point)
180
+ hit = nil
181
+ if @are_children_tangible
182
+ @children.reverse_each do |child|
183
+ hit = child.get_actor_at(point)
184
+ if hit
185
+ break if @is_mask
186
+ return hit
187
+ end
188
+ end
189
+ end
190
+ hit = self if hit == nil && @is_tangible && is_point_in_bounds(point)
191
+ hit = @parent if @is_mask && hit == self
192
+ hit
193
+ end
194
+
195
+ ##
196
+ # Functions similarly to #get_actor_at, but returns a list of +all+ Actors for whom the point is inside their shape.
197
+ #
198
+ def get_actors_at(point)
199
+ actors = []
200
+ if @are_children_tangible
201
+ @children.reverse_each do |child|
202
+ actors |= child.get_actors_at(point)
203
+ end
204
+ end
205
+ actors.push(self) if @is_tangible && is_point_in_bounds(point)
206
+ actors.uniq!
207
+ if @is_mask
208
+ actors.map! { |actor| (actor == self) ? @parent : actor }
209
+ end
210
+ actors
211
+ end
212
+
213
+ ##
214
+ # Returns a Snow::Mat3 transformation matrix combining this Actor's transforms as well as all of its ancestors.
215
+ # This matrix can be used to transform a point in this Actor's local space to its global equivalent (the geometric
216
+ # space of its root ancestor).
217
+ #
218
+ def get_global_transform(out = nil)
219
+ out ||= Snow::Mat3.new
220
+ if parent
221
+ to_matrix.multiply(parent.get_global_transform, out)
222
+ else
223
+ out.set(to_matrix)
224
+ end
225
+ end
226
+
227
+ ##
228
+ # Returns the global x/y position of this actor (where it is relative to its root ancestor). This value is calculated
229
+ # using the Actor's center (see Transformable#center).
230
+ #
231
+ def get_global_position(out = nil)
232
+ tf = MatrixCache.instance.get
233
+ get_global_transform(tf)
234
+ out ||= Snow::Vec3.new
235
+ Transformable.transform_point(tf, center, out)
236
+ ensure
237
+ MatrixCache.instance.recycle(tf)
238
+ end
239
+
240
+ ##
241
+ # Wrapper method. Returns this Actor's alpha value (0-255).
242
+ #
243
+ def alpha
244
+ @color.alpha
245
+ end
246
+
247
+ ##
248
+ # Wrapper method. Sets this Actor's alpha value (0-255).
249
+ #
250
+ def alpha=(val)
251
+ @color.alpha = val
252
+ end
253
+
254
+ ##
255
+ # Wrapper method. Returns this Actor's red value (0-255).
256
+ #
257
+ def red
258
+ @color.red
259
+ end
260
+
261
+ ##
262
+ # Wrapper method. Sets this Actor's red value (0-255).
263
+ #
264
+ def red=(val)
265
+ @color.red = val
266
+ end
267
+
268
+ ##
269
+ # Wrapper method. Returns this Actor's green value (0-255).
270
+ #
271
+ def green
272
+ @color.green
273
+ end
274
+
275
+ ##
276
+ # Wrapper method. Sets this Actor's green value (0-255).
277
+ #
278
+ def green=(val)
279
+ @color.green = val
280
+ end
281
+
282
+ ##
283
+ # Wrapper method. Returns this Actor's blue value (0-255).
284
+ #
285
+ def blue
286
+ @color.blue
287
+ end
288
+
289
+ ##
290
+ # Wrapper method. Sets this Actor's blue value (0-255).
291
+ #
292
+ def blue=(val)
293
+ @color.blue = val
294
+ end
295
+
296
+ protected
297
+
298
+ def render(matrix)
299
+ end
300
+
301
+ def fill_polygon(vertices)
302
+ (2...vertices.length).each do |i|
303
+ v0 = vertices[0]
304
+ v1 = vertices[i - 1]
305
+ v2 = vertices[i]
306
+ @window.draw_triangle(
307
+ v0[0].to_f, v0[1].to_f, @color,
308
+ v1[0].to_f, v1[1].to_f, @color,
309
+ v2[0].to_f, v2[1].to_f, @color,
310
+ )
311
+ end
312
+ end
313
+
314
+ ##
315
+ # Internal use only. See #add_child and #remove_child.
316
+ #
317
+ def parent=(parent)
318
+ return if parent == @parent
319
+ unless parent
320
+ raise Gosling::InheritanceError.new("You should use Actor.remove_child() instead of setting the parent directly.") if @parent.has_child?(self)
321
+ end
322
+ @parent = parent
323
+ if @parent
324
+ raise Gosling::InheritanceError.new("You should use Actor.add_child() instead of setting the parent directly.") unless @parent.has_child?(self)
325
+ end
326
+ end
327
+ end
328
+ end