glimr 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/glimr.rb +2 -0
- data/lib/glimr/configurable.rb +37 -0
- data/lib/glimr/default_theme/button_bg.png +0 -0
- data/lib/glimr/default_theme/button_bg_down.png +0 -0
- data/lib/glimr/default_theme/button_cover.png +0 -0
- data/lib/glimr/default_theme/button_cover_down.png +0 -0
- data/lib/glimr/default_theme/button_focus.png +0 -0
- data/lib/glimr/default_theme/checkbox_bg.png +0 -0
- data/lib/glimr/default_theme/checkbox_checked_bg.png +0 -0
- data/lib/glimr/default_theme/font.ttf +0 -0
- data/lib/glimr/default_theme/hscroller_bg.png +0 -0
- data/lib/glimr/default_theme/radiobutton_bg.png +0 -0
- data/lib/glimr/default_theme/radiobutton_checked_bg.png +0 -0
- data/lib/glimr/default_theme/resizer_down.png +0 -0
- data/lib/glimr/default_theme/resizer_up.png +0 -0
- data/lib/glimr/default_theme/scroll_down_down.png +0 -0
- data/lib/glimr/default_theme/scroll_down_up.png +0 -0
- data/lib/glimr/default_theme/scroll_hknob_down.png +0 -0
- data/lib/glimr/default_theme/scroll_hknob_up.png +0 -0
- data/lib/glimr/default_theme/scroll_left_down.png +0 -0
- data/lib/glimr/default_theme/scroll_left_up.png +0 -0
- data/lib/glimr/default_theme/scroll_right_down.png +0 -0
- data/lib/glimr/default_theme/scroll_right_up.png +0 -0
- data/lib/glimr/default_theme/scroll_up_down.png +0 -0
- data/lib/glimr/default_theme/scroll_up_up.png +0 -0
- data/lib/glimr/default_theme/scroll_vknob_down.png +0 -0
- data/lib/glimr/default_theme/scroll_vknob_up.png +0 -0
- data/lib/glimr/default_theme/text_cursor.png +0 -0
- data/lib/glimr/default_theme/text_cursor_insert.png +0 -0
- data/lib/glimr/default_theme/text_input_bg.png +0 -0
- data/lib/glimr/default_theme/vscroller_bg.png +0 -0
- data/lib/glimr/event.rb +41 -0
- data/lib/glimr/eventlistener.rb +209 -0
- data/lib/glimr/layoutable.rb +520 -0
- data/lib/glimr/renderer.rb +2 -0
- data/lib/glimr/renderer/camera.rb +63 -0
- data/lib/glimr/renderer/geometry.rb +194 -0
- data/lib/glimr/renderer/glutwindow.rb +387 -0
- data/lib/glimr/renderer/light.rb +43 -0
- data/lib/glimr/renderer/material.rb +66 -0
- data/lib/glimr/renderer/model.rb +103 -0
- data/lib/glimr/renderer/orthoprojection.rb +21 -0
- data/lib/glimr/renderer/raw.rb +34 -0
- data/lib/glimr/renderer/sceneobject.rb +279 -0
- data/lib/glimr/renderer/shader.rb +14 -0
- data/lib/glimr/renderer/texture.rb +280 -0
- data/lib/glimr/renderer/transform.rb +322 -0
- data/lib/glimr/renderer/viewport.rb +349 -0
- data/lib/glimr/renderer_core.rb +10 -0
- data/lib/glimr/util.rb +247 -0
- data/lib/glimr/widget.rb +87 -0
- data/lib/glimr/widgets.rb +37 -0
- data/lib/glimr/widgets/button.rb +277 -0
- data/lib/glimr/widgets/checkbox.rb +82 -0
- data/lib/glimr/widgets/container.rb +84 -0
- data/lib/glimr/widgets/image.rb +82 -0
- data/lib/glimr/widgets/label.rb +91 -0
- data/lib/glimr/widgets/layout.rb +227 -0
- data/lib/glimr/widgets/list.rb +28 -0
- data/lib/glimr/widgets/radiogroup.rb +118 -0
- data/lib/glimr/widgets/resizer.rb +31 -0
- data/lib/glimr/widgets/scrollable_container.rb +67 -0
- data/lib/glimr/widgets/scrollbar.rb +496 -0
- data/lib/glimr/widgets/stretchable_image.rb +135 -0
- data/lib/glimr/widgets/text_editor.rb +349 -0
- data/tests/assets/datatowers_crop.jpg +0 -0
- data/tests/assets/download_progress_meter.png +0 -0
- data/tests/assets/metalwing2.png +0 -0
- data/tests/assets/redhairgreeneyes3.jpg +0 -0
- data/tests/demo_apps/spinning_ruby.rb +37 -0
- data/tests/integration_tests/run_all.rb +8 -0
- data/tests/integration_tests/test_button.rb +22 -0
- data/tests/integration_tests/test_checkbox.rb +21 -0
- data/tests/integration_tests/test_container.rb +22 -0
- data/tests/integration_tests/test_label.rb +12 -0
- data/tests/integration_tests/test_layout.rb +43 -0
- data/tests/integration_tests/test_radiogroup.rb +16 -0
- data/tests/integration_tests/test_renderer.rb +44 -0
- data/tests/integration_tests/test_renderer2.rb +36 -0
- data/tests/integration_tests/test_scrollable_container.rb +34 -0
- data/tests/integration_tests/test_scrollbar.rb +20 -0
- data/tests/integration_tests/test_stretchable_image.rb +34 -0
- data/tests/integration_tests/test_text_input.rb +20 -0
- data/tests/integration_tests/test_zsort.rb +18 -0
- data/tests/unit_tests/test_button.rb +93 -0
- data/tests/unit_tests/test_checkbox.rb +35 -0
- data/tests/unit_tests/test_label.rb +36 -0
- data/tests/unit_tests/test_layout.rb +229 -0
- data/tests/unit_tests/test_widget.rb +3 -0
- metadata +139 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'glimr/renderer/sceneobject'
|
2
|
+
|
3
|
+
|
4
|
+
module GlimR
|
5
|
+
|
6
|
+
|
7
|
+
class Light < SceneObject
|
8
|
+
|
9
|
+
LIGHTS = GL::constants.grep(/^LIGHT[0-9]+/).map{|l| GL.const_get l }
|
10
|
+
|
11
|
+
def self.reserve_light_id
|
12
|
+
@index ||= 0
|
13
|
+
return false if LIGHTS.size <= @index
|
14
|
+
l = LIGHTS[@index]
|
15
|
+
@index += 1
|
16
|
+
l
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.reset_lights
|
20
|
+
@index = 0
|
21
|
+
LIGHTS.each{|l| Disable(l) }
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_accessor :position, :diffuse, :specular, :ambient
|
25
|
+
attr_accessor :constant_attenuation, :linear_attenuation, :quadratic_attenuation
|
26
|
+
|
27
|
+
def setup
|
28
|
+
light_id = self.class.reserve_light_id
|
29
|
+
return unless light_id
|
30
|
+
Enable(light_id)
|
31
|
+
Lightfv(light_id, POSITION, position ) if position
|
32
|
+
Lightfv(light_id, DIFFUSE, diffuse ) if diffuse
|
33
|
+
Lightfv( light_id, SPECULAR, specular ) if specular
|
34
|
+
Lightfv( light_id, AMBIENT, ambient ) if ambient
|
35
|
+
Lightf( light_id, CONSTANT_ATTENUATION, constant_attenuation) if constant_attenuation
|
36
|
+
Lightf( light_id, LINEAR_ATTENUATION, linear_attenuation) if linear_attenuation
|
37
|
+
Lightf( light_id, QUADRATIC_ATTENUATION, quadratic_attenuation) if quadratic_attenuation
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'glimr/renderer/sceneobject'
|
2
|
+
|
3
|
+
|
4
|
+
module GlimR
|
5
|
+
|
6
|
+
|
7
|
+
# A Material node controls OpenGL surface material parameters.
|
8
|
+
# It has accessors for ambient, diffuse, specular, shininess and emission.
|
9
|
+
#
|
10
|
+
# Look up glMaterial and Blinn-Phong shading to find out more.
|
11
|
+
#
|
12
|
+
class Material < SceneObject
|
13
|
+
|
14
|
+
touching_accessor :ambient, :diffuse, :specular, :shininess, :emission
|
15
|
+
|
16
|
+
# The absolute material of a Material is the parent's absolute material
|
17
|
+
# merged with the Material.
|
18
|
+
def absolute_material
|
19
|
+
@__pama ||= (
|
20
|
+
pam = parent.absolute_material
|
21
|
+
pam.ambient = ambient if ambient
|
22
|
+
pam.diffuse = diffuse if diffuse
|
23
|
+
pam.specular = specular if specular
|
24
|
+
pam.shininess = shininess if shininess
|
25
|
+
pam.emission = emission if emission
|
26
|
+
pam
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Applies the material by calling GL::Material to set the material properties.
|
31
|
+
def apply
|
32
|
+
Material(FRONT_AND_BACK, AMBIENT, ambient) if ambient
|
33
|
+
Material(FRONT_AND_BACK, DIFFUSE, diffuse) if diffuse
|
34
|
+
Material(FRONT_AND_BACK, SPECULAR, specular) if specular
|
35
|
+
Material(FRONT_AND_BACK, SHININESS, shininess) if shininess
|
36
|
+
Material(FRONT_AND_BACK, EMISSION, emission) if emission
|
37
|
+
end
|
38
|
+
|
39
|
+
# Pushes the LIGHTING_BIT to attrib stack.
|
40
|
+
def push_state
|
41
|
+
PushAttrib(LIGHTING_BIT)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Pops the attrib stack.
|
45
|
+
def pop_state
|
46
|
+
PopAttrib()
|
47
|
+
end
|
48
|
+
|
49
|
+
# Replaces the instance variables of the Material with
|
50
|
+
# the other's.
|
51
|
+
def replace!(other)
|
52
|
+
@ambient = other.ambient
|
53
|
+
@diffuse = other.diffuse
|
54
|
+
@specular = other.specular
|
55
|
+
@shininess = other.shininess
|
56
|
+
@emission = other.emission
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
touching :touch!, :replace!
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
end
|
66
|
+
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'glimr/renderer/sceneobject'
|
2
|
+
require 'glimr/renderer/transform'
|
3
|
+
require 'glimr/renderer/texture'
|
4
|
+
require 'glimr/renderer/geometry'
|
5
|
+
require 'glimr/renderer/material'
|
6
|
+
require 'glimr/renderer/shader'
|
7
|
+
|
8
|
+
|
9
|
+
module GlimR
|
10
|
+
|
11
|
+
# A Model is a convenience SceneObject that
|
12
|
+
# has its own transform, material, texture, shader, and geometry.
|
13
|
+
#
|
14
|
+
# The state nodes are attached to the Model after super initialization
|
15
|
+
# and form a five-node subtree ordered like this (from top to bottom):
|
16
|
+
# transform - material - texture - shader - geometry.
|
17
|
+
#
|
18
|
+
# Model delegates many accessors to the corresponding state nodes
|
19
|
+
#
|
20
|
+
# Example:
|
21
|
+
# m = Model.new
|
22
|
+
# m.texture.load('foo.jpg')
|
23
|
+
# m.position = [10, 20, 30]
|
24
|
+
# m.texcoords = make texcoords
|
25
|
+
# m.vertices = make vertices
|
26
|
+
#
|
27
|
+
class Model < SceneObject
|
28
|
+
|
29
|
+
attr_reader :texture, :geometry, :transform, :material, :shader
|
30
|
+
|
31
|
+
delegate_accessor :geometry, :type, :vertices, :texcoords, :colors, :normals
|
32
|
+
delegate_accessor :transform, :position, :rotation, :scale, :matrix, :x, :y, :z, :angle
|
33
|
+
delegate_accessor :material, :ambient, :diffuse, :specular, :shininess, :emission
|
34
|
+
|
35
|
+
def initialize(*a,&b)
|
36
|
+
@transform = Transform.new
|
37
|
+
@material = Material.new
|
38
|
+
@texture = Texture.new
|
39
|
+
@shader = Shader.new
|
40
|
+
@geometry = Geometry.new
|
41
|
+
super
|
42
|
+
attach @material
|
43
|
+
@material.attach @texture
|
44
|
+
@texture.attach @shader
|
45
|
+
@shader.attach @geometry
|
46
|
+
end
|
47
|
+
|
48
|
+
def push_state
|
49
|
+
@transform.push_state
|
50
|
+
super
|
51
|
+
end
|
52
|
+
|
53
|
+
def pop_state
|
54
|
+
@transform.pop_state
|
55
|
+
super
|
56
|
+
end
|
57
|
+
|
58
|
+
def apply
|
59
|
+
@transform.apply
|
60
|
+
super
|
61
|
+
end
|
62
|
+
|
63
|
+
def absolute_transform
|
64
|
+
@transform.instance_variable_set :@parent , @parent
|
65
|
+
@transform.absolute_transform
|
66
|
+
end
|
67
|
+
|
68
|
+
# Replaces transform with t using Transform#replace!
|
69
|
+
# If t is a matrix, creates a Transform with t as the collapsed matrix.
|
70
|
+
def transform= t
|
71
|
+
unless t.is_a? Transform
|
72
|
+
t = Transform.new(:collapsed_matrix => t, :position => nil, :rotation => nil, :scale => nil, :matrix => nil)
|
73
|
+
end
|
74
|
+
@transform.replace! t
|
75
|
+
end
|
76
|
+
|
77
|
+
# Replaces texture with t. Uses Texture#replace!
|
78
|
+
def texture= t
|
79
|
+
@texture.replace! t
|
80
|
+
end
|
81
|
+
|
82
|
+
# Replaces geometry with g using Geometry#replace!
|
83
|
+
def geometry= g
|
84
|
+
@geometry.replace! g
|
85
|
+
end
|
86
|
+
|
87
|
+
# Replaces material with m using Material#replace!
|
88
|
+
def material= m
|
89
|
+
@material.replace! m
|
90
|
+
end
|
91
|
+
|
92
|
+
# Replaces shader with s using Shader#replace!
|
93
|
+
def shader= s
|
94
|
+
@shader.replace! s
|
95
|
+
end
|
96
|
+
|
97
|
+
def inspect
|
98
|
+
super[0..-2] + "::#{ [@transform, @material, @texture, @shader, @geometry].map{|i|i.inspect[9..-2]}.join("::") }>"
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'glimr/renderer/sceneobject'
|
2
|
+
|
3
|
+
|
4
|
+
module GlimR
|
5
|
+
|
6
|
+
class OrthoProjection < SceneObject
|
7
|
+
|
8
|
+
attr_accessor :width, :height, :x, :y, :near, :far
|
9
|
+
|
10
|
+
def apply(x=x, y=y, width=width, height=height)
|
11
|
+
MatrixMode(PROJECTION)
|
12
|
+
LoadIdentity()
|
13
|
+
Ortho(x,width, y,height, near,far)
|
14
|
+
MatrixMode(MODELVIEW)
|
15
|
+
LoadIdentity()
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'glimr/renderer/sceneobject'
|
2
|
+
|
3
|
+
|
4
|
+
module GlimR
|
5
|
+
|
6
|
+
|
7
|
+
# Raw is a SceneObject that calls its #renderer
|
8
|
+
# when applied.
|
9
|
+
#
|
10
|
+
# Use for doing custom OpenGL calls and such.
|
11
|
+
#
|
12
|
+
# Raw doesn't work with the Viewport's collapsing #render,
|
13
|
+
# so is pretty much useless at the moment.
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
#
|
17
|
+
# r = Raw.new
|
18
|
+
# r.renderer = lambda do
|
19
|
+
# puts 'Hi, I was just applied!'
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
class Raw < SceneObject
|
23
|
+
|
24
|
+
attr_accessor :renderer
|
25
|
+
|
26
|
+
# Calls #renderer if renderer is set.
|
27
|
+
def apply
|
28
|
+
renderer.call if renderer
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,279 @@
|
|
1
|
+
require 'glimr/eventlistener'
|
2
|
+
require 'glimr/util'
|
3
|
+
require 'opengl'
|
4
|
+
require 'set'
|
5
|
+
|
6
|
+
|
7
|
+
module GlimR
|
8
|
+
|
9
|
+
|
10
|
+
# The SceneObject is the root class of the GlimR scene graph class hierarchy.
|
11
|
+
#
|
12
|
+
# A SceneObject may have a parent and children, and usually will.
|
13
|
+
# All actual OpenGL state manipulation should be done with its
|
14
|
+
# specific subclasses like Transform, Geometry and Texture.
|
15
|
+
#
|
16
|
+
# The SceneObject is an EventListener, and as such you can tell
|
17
|
+
# it to listen and respond to events.
|
18
|
+
#
|
19
|
+
# SceneObjects also maintain a list of drawable objects underneath them.
|
20
|
+
# This is mainly used to speed up rendering by removing the need to traverse
|
21
|
+
# the whole scene graph to draw the scene.
|
22
|
+
#
|
23
|
+
# Example:
|
24
|
+
# s = SceneObject.new
|
25
|
+
# t = Texture.new
|
26
|
+
# s.attach t
|
27
|
+
# s.detach t
|
28
|
+
#
|
29
|
+
class SceneObject
|
30
|
+
include GL
|
31
|
+
include EventListener
|
32
|
+
include Configurable
|
33
|
+
|
34
|
+
attr_accessor :parent, :children, :viewport, :drawables
|
35
|
+
attr_reader :mtime
|
36
|
+
touching_accessor :visible
|
37
|
+
|
38
|
+
def default_config
|
39
|
+
super.merge(
|
40
|
+
:visible => true,
|
41
|
+
:mtime => Time.now.to_f
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Configurable initialize.
|
46
|
+
def initialize(*arg_hash, &config_block)
|
47
|
+
@children = []
|
48
|
+
@drawables = Set.new
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the viewport or possible parent's viewport.
|
53
|
+
def viewport
|
54
|
+
@viewport ||= (parent and parent.viewport)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the scene root.
|
58
|
+
# This is either the viewport,
|
59
|
+
# the parent's scene root if there is no viewport,
|
60
|
+
# or self if there is no parent.
|
61
|
+
#
|
62
|
+
def root
|
63
|
+
(viewport || (parent ? parent.root : self))
|
64
|
+
end
|
65
|
+
|
66
|
+
# Sets viewport to vp.
|
67
|
+
# Passes viewport change to children.
|
68
|
+
#
|
69
|
+
def viewport= vp
|
70
|
+
if vp != @viewport
|
71
|
+
@viewport = vp
|
72
|
+
children.each{|c| c.viewport = vp}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Attaches new_children to the scene graph below self.
|
77
|
+
def attach(*new_children)
|
78
|
+
new_children.each{|c|
|
79
|
+
adopt(c)
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
# Attach single child.
|
84
|
+
def <<(new_child)
|
85
|
+
attach new_child
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
# Detaches children_to_detach from self.
|
90
|
+
def detach(*children_to_detach)
|
91
|
+
children_to_detach.each{|c|
|
92
|
+
orphan(c)
|
93
|
+
}
|
94
|
+
end
|
95
|
+
|
96
|
+
# Detaches self from parent if there is a parent.
|
97
|
+
def detach_self
|
98
|
+
parent.detach(self) if parent
|
99
|
+
end
|
100
|
+
|
101
|
+
# Sets parent to p.
|
102
|
+
#
|
103
|
+
# Causes viewport to be set to nil and drawables to
|
104
|
+
# be added to parent's drawables.
|
105
|
+
def parent= new_parent
|
106
|
+
#~ if @parent
|
107
|
+
#~ puts object_id, "reparenting #{self} from #{@parent} to #{new_parent.inspect}"
|
108
|
+
#~ d = @parent
|
109
|
+
#~ end
|
110
|
+
@parent.remove_drawables drawables if @parent
|
111
|
+
@parent = new_parent
|
112
|
+
self.viewport = nil
|
113
|
+
@parent.add_drawables drawables if @parent
|
114
|
+
#~ p [:after, d.drawables] if d
|
115
|
+
#~ puts '','' if d
|
116
|
+
end
|
117
|
+
|
118
|
+
# A node is visible if its @visible is true and its parent is visible (if it has a parent.)
|
119
|
+
def visible
|
120
|
+
@visible and (parent ? parent.visible : true)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Adds d to drawables and parent's drawables.
|
124
|
+
def add_drawables(d)
|
125
|
+
parent.add_drawables d if parent
|
126
|
+
@drawables += d
|
127
|
+
end
|
128
|
+
|
129
|
+
# Removes d from drawables and parent's drawables.
|
130
|
+
def remove_drawables(d)
|
131
|
+
parent.remove_drawables d if parent
|
132
|
+
@drawables -= d
|
133
|
+
end
|
134
|
+
|
135
|
+
# Sets drawables to d and updates parent's drawables.
|
136
|
+
def drawables= d
|
137
|
+
if (d != @drawables) and parent
|
138
|
+
parent.drawables = ((parent.drawables - @drawables) + d)
|
139
|
+
end
|
140
|
+
@drawables = d
|
141
|
+
end
|
142
|
+
|
143
|
+
# Replaces orig node in scene graph with replacement by
|
144
|
+
# Attaching the replacement to orig's parent, and attaching
|
145
|
+
# orig's children to replacement.
|
146
|
+
#
|
147
|
+
# If no replacement is given, removes orig from scenegraph
|
148
|
+
# and attaches its children to its parent. If there is no parent or
|
149
|
+
# replacement, does nothing.
|
150
|
+
#
|
151
|
+
def replace_node(orig, replacement=nil)
|
152
|
+
return unless orig
|
153
|
+
replacement ||= orig.parent
|
154
|
+
return unless replacement
|
155
|
+
replacement.detach(*orig.children)
|
156
|
+
replacement.attach(*orig.children)
|
157
|
+
orig.detach(*orig.children)
|
158
|
+
orig.parent.attach(replacement) if orig.parent
|
159
|
+
orig.detach_self
|
160
|
+
end
|
161
|
+
|
162
|
+
# Renders the SceneObject by pushing state, applying, calling render
|
163
|
+
# for each child, and popping state.
|
164
|
+
#
|
165
|
+
# Not used with collapsing Viewport #render.
|
166
|
+
def render(*a)
|
167
|
+
push_state
|
168
|
+
apply
|
169
|
+
children.each{|c| c.render if c.visible }
|
170
|
+
pop_state
|
171
|
+
end
|
172
|
+
|
173
|
+
# The collapsed state of a SceneObject is its parent's collapsed state,
|
174
|
+
# which fits in with SceneObjects not editing OpenGL state.
|
175
|
+
def absolute_transform
|
176
|
+
parent.absolute_transform
|
177
|
+
end
|
178
|
+
|
179
|
+
def absolute_transform_for_drawing
|
180
|
+
absolute_transform
|
181
|
+
end
|
182
|
+
|
183
|
+
def absolute_material
|
184
|
+
#~ unless parent
|
185
|
+
#~ puts object_id, geometry.object_id, self, geometry
|
186
|
+
#~ ObjectSpace.each_object(Button){|b|
|
187
|
+
#~ if b.drawables.include? geometry
|
188
|
+
#~ puts b
|
189
|
+
#~ p b.drawables.to_a, b.children
|
190
|
+
#~ puts
|
191
|
+
#~ puts
|
192
|
+
#~ cc = b.children.find{|c|
|
193
|
+
#~ c.geometry == geometry if c.is_a? Model
|
194
|
+
#~ }
|
195
|
+
#~ p cc
|
196
|
+
#~ end
|
197
|
+
#~ }
|
198
|
+
#~ end
|
199
|
+
parent.absolute_material
|
200
|
+
end
|
201
|
+
|
202
|
+
def absolute_texture
|
203
|
+
parent.absolute_texture
|
204
|
+
end
|
205
|
+
|
206
|
+
def absolute_geometry
|
207
|
+
parent.absolute_geometry
|
208
|
+
end
|
209
|
+
|
210
|
+
def absolute_shader
|
211
|
+
parent.absolute_shader
|
212
|
+
end
|
213
|
+
|
214
|
+
# Applies the SceneObject to OpenGL state.
|
215
|
+
# For SceneObject, this is empty.
|
216
|
+
def apply
|
217
|
+
end
|
218
|
+
|
219
|
+
# Pushes the relevant OpenGL state stack.
|
220
|
+
# Empty for SceneObject.
|
221
|
+
def push_state
|
222
|
+
end
|
223
|
+
|
224
|
+
# Pops the relevant OpenGL state stack.
|
225
|
+
# Empty for SceneObject.
|
226
|
+
def pop_state
|
227
|
+
end
|
228
|
+
|
229
|
+
# Creates a clone of the SceneObject.
|
230
|
+
# If deep is set to true, also clones the children.
|
231
|
+
# If deep is false, clears children.
|
232
|
+
#
|
233
|
+
def clone(deep=false)
|
234
|
+
c = super()
|
235
|
+
if deep
|
236
|
+
c.children = []
|
237
|
+
c.drawables.clear
|
238
|
+
cchildren = c.children.map{|ch| ch.clone(deep) }
|
239
|
+
c.attach *cchildren
|
240
|
+
else
|
241
|
+
c.children = []
|
242
|
+
c.drawables.clear
|
243
|
+
end
|
244
|
+
c.parent = nil
|
245
|
+
c
|
246
|
+
end
|
247
|
+
|
248
|
+
def inspect
|
249
|
+
"#<#{self.class.name}:#{object_id}>"
|
250
|
+
end
|
251
|
+
|
252
|
+
def touch!(mtime=Time.now.to_f)
|
253
|
+
@mtime = mtime
|
254
|
+
parent.touch!(@mtime) if parent
|
255
|
+
nil
|
256
|
+
end
|
257
|
+
|
258
|
+
private
|
259
|
+
|
260
|
+
def adopt(c)
|
261
|
+
children.push c
|
262
|
+
c.parent = self
|
263
|
+
c.listener_count.each{|k,v| increment_listener_count k, v }
|
264
|
+
touch!
|
265
|
+
end
|
266
|
+
|
267
|
+
def orphan(c)
|
268
|
+
if children.include? c
|
269
|
+
children.delete c
|
270
|
+
c.parent = nil
|
271
|
+
c.listener_count.each{|k,v| decrement_listener_count k, v }
|
272
|
+
touch!
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
end
|
277
|
+
|
278
|
+
|
279
|
+
end
|