soby 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 269d82eee352fce114a0120f71fccaab7f25d02a
4
+ data.tar.gz: 06534754ac6193202a319cabaed39b3b4d9ca93d
5
+ SHA512:
6
+ metadata.gz: bd29c3af78d994f2d0ed175a37cd272a0f8af53dac5579724b24b958e50f2df3a2de374210ea14a0b0307bc7ec4da919980d54adc93c33600c2235d1ae23ed74
7
+ data.tar.gz: d2eb41a775fe04d13157045f9550f23069002b6b91eb2467f4334648935aefce550fb18a6112022c44e768187f32b81b418838e0aad0e7fc6ed745f786434974
data/lib/soby/cam.rb ADDED
@@ -0,0 +1,103 @@
1
+
2
+ class Cam
3
+
4
+ include_package 'processing.core'
5
+
6
+ attr_accessor :mat, :angle, :translation, :scale, :pre_translation, :post_translation
7
+ attr_accessor :quat
8
+
9
+ @@interp = Processing::PMatrix3D.new
10
+
11
+ def initialize
12
+ @scale = 1
13
+ @angle = 0;
14
+ @translation = PVector.new
15
+ @mat = PMatrix3D.new
16
+ @pre_translation = PVector.new
17
+ @post_translation = PVector.new
18
+
19
+ @is_computed = false
20
+ end
21
+
22
+ ## TODO: check modif at
23
+ def compute_mat
24
+
25
+ puts "Warning Camera already computed " if @is_computed
26
+ return if @is_computed
27
+
28
+ @is_computed = true
29
+
30
+ @mat.reset
31
+
32
+ @mat.translate(@post_translation.x, @post_translation.y)
33
+ @mat.scale(@scale)
34
+
35
+ @mat.translate(@translation.x, @translation.y)
36
+ @mat.rotate(@angle)
37
+
38
+ @mat.translate(@pre_translation.x, @pre_translation.y)
39
+
40
+ @mat
41
+ end
42
+
43
+
44
+
45
+ # Value = 0 : self, value = 1 : cam2
46
+ def lerp(cam2, value)
47
+
48
+ complement = 1 - value
49
+
50
+ # puts "Value #{value} "
51
+ # puts "complement #{complement} "
52
+
53
+ interp = @@interp
54
+ interp.reset
55
+
56
+ interp.m00 = @mat.m00 * complement + cam2.mat.m00 * value
57
+ interp.m01 = @mat.m01 * complement + cam2.mat.m01 * value
58
+ interp.m02 = @mat.m02 * complement + cam2.mat.m02 * value
59
+ interp.m03 = @mat.m03 * complement + cam2.mat.m03 * value
60
+
61
+ interp.m10 = @mat.m10 * complement + cam2.mat.m10 * value
62
+ interp.m11 = @mat.m11 * complement + cam2.mat.m11 * value
63
+ interp.m12 = @mat.m12 * complement + cam2.mat.m12 * value
64
+ interp.m13 = @mat.m13 * complement + cam2.mat.m13 * value
65
+
66
+ interp.m20 = @mat.m20 * complement + cam2.mat.m20 * value
67
+ interp.m21 = @mat.m21 * complement + cam2.mat.m21 * value
68
+ interp.m22 = @mat.m22 * complement + cam2.mat.m22 * value
69
+ interp.m23 = @mat.m23 * complement + cam2.mat.m23 * value
70
+
71
+ interp.m30 = @mat.m30 * complement + cam2.mat.m30 * value
72
+ interp.m31 = @mat.m31 * complement + cam2.mat.m31 * value
73
+ interp.m32 = @mat.m32 * complement + cam2.mat.m32 * value
74
+ interp.m33 = @mat.m33 * complement + cam2.mat.m33 * value
75
+
76
+ interp
77
+
78
+ end
79
+
80
+ private
81
+
82
+ def create_mat4x4(mat)
83
+ Matrix4x4.new(mat.m00, mat.m01, mat.m02, mat.m03,\
84
+ mat.m10, mat.m11, mat.m12, mat.m13,\
85
+ mat.m20, mat.m21, mat.m22, mat.m23,\
86
+ mat.m30, mat.m31, mat.m32, mat.m33)
87
+ end
88
+
89
+ def create_pmatrix(mat)
90
+ PMatrix3D.new(mat[0][0], mat[0][1], mat[0][2], mat[0][3],\
91
+ mat[1][0], mat[1][1], mat[1][2], mat[1][3],\
92
+ mat[2][0], mat[2][1], mat[2][2], mat[2][3],\
93
+ mat[3][0], mat[3][1], mat[3][2], mat[3][3])
94
+ end
95
+
96
+ def set_pmatrix(mat, pmatrix)
97
+ pmatrix.set(mat[0][0], mat[0][1], mat[0][2], mat[0][3],\
98
+ mat[1][0], mat[1][1], mat[1][2], mat[1][3],\
99
+ mat[2][0], mat[2][1], mat[2][2], mat[2][3],\
100
+ mat[3][0], mat[3][1], mat[3][2], mat[3][3])
101
+ end
102
+ end
103
+
@@ -0,0 +1,342 @@
1
+ require 'ostruct'
2
+ require 'base64'
3
+
4
+ class Presentation
5
+
6
+ include_package 'processing.core'
7
+
8
+ include Soby
9
+
10
+ attr_accessor :geometry, :slides, :pshape, :svg, :transform
11
+ attr_accessor :width, :height, :matrix, :videos
12
+ attr_reader :nb_slides, :debug
13
+
14
+ attr_accessor :graphics
15
+
16
+ def initialize (app, url)
17
+ @app = app
18
+ xml = app.loadXML(url)
19
+ @pshape = PShapeSVG.new(xml)
20
+ @svg = Nokogiri::XML(open(url)).children[1];
21
+
22
+ @graphics = @app.g
23
+ build_internal
24
+
25
+ end
26
+
27
+ def width ; @pshape.getWidth; end
28
+ def height ; @pshape.getHeight; end
29
+
30
+
31
+ def build_internal
32
+
33
+ # Create the frames..
34
+ @slides = {}
35
+ @nb_slides = 0
36
+ @playing_videos = []
37
+
38
+ puts "Svg null, look for the error... !" if @svg == nil
39
+ return if @svg == nil
40
+
41
+ load_frames
42
+ load_videos
43
+ load_animations
44
+ end
45
+
46
+ def draw
47
+ @graphics.shape pshape, 0, 0
48
+ # display_videos
49
+ end
50
+
51
+
52
+ def load_frames
53
+
54
+ puts "Loading the frames..."
55
+ @svg.children.each do |child|
56
+
57
+ next unless child.name =~ /frame/
58
+
59
+ ## ignore if it references nothing.
60
+ attr = child.attributes
61
+ next if attr["refid"] == nil
62
+
63
+ slide = Slide.new(child)
64
+
65
+ # get the element associated with each slide...
66
+ @svg.search("[id=" + slide.refid + "]").each do |elem|
67
+
68
+ case elem.name
69
+ when "rect", "image"
70
+ add_rect_or_image_frame(elem, slide)
71
+ when "g"
72
+ add_group(elem, slide)
73
+ else
74
+ puts "Slide type not supported ! " + elem.name
75
+ end # end case
76
+ end # search
77
+ end # frame
78
+ end
79
+
80
+ def add_slide(new_slide)
81
+
82
+ puts "Add slide, id " << new_slide.title << " numero " << new_slide.sequence
83
+ @slides[new_slide.sequence] = new_slide
84
+ @slides[new_slide.title] = new_slide
85
+ @nb_slides = @nb_slides+1
86
+ end
87
+
88
+
89
+ def add_rect_or_image_frame(element, slide)
90
+ id = slide.title
91
+ refid = slide.refid
92
+
93
+ add_slide(slide)
94
+
95
+ # set the geometry & transformation
96
+ transform = get_global_transform element
97
+ @slides[id].set_geometry(element, transform[0])
98
+ pshape_element = @pshape.getChild(refid)
99
+
100
+ # hide the element
101
+ if pshape_element == nil
102
+ puts "Error: rect or Image ID: #{refid} not found. CHECK THE PROCESSING VERSION."
103
+ else
104
+ pshape_element.setVisible(!@slides[id].hide) if element.name == "rect"
105
+ end
106
+
107
+ puts "Slide #{id} created from a rect : #{refid}" if element.name == "rect"
108
+ puts "Slide #{id} created from an image: #{refid}" if element.name == "image"
109
+ end
110
+
111
+
112
+ def add_group(group, slide)
113
+
114
+ id = slide.title
115
+ refid = slide.refid
116
+ add_slide(slide)
117
+
118
+ # TODO: Find the bounding box of any group..
119
+ # TODO: Hide the whole group ?
120
+ surf_max = 0
121
+ biggest_rect = nil
122
+
123
+ ## biggest_rect surface..
124
+ group.css("rect").each do |rect|
125
+ # (group.css("rect") + group.css("image")).each do |rect|
126
+
127
+ if biggest_rect == nil
128
+ biggest_rect = rect
129
+ end
130
+
131
+ surf_rect = rect.attributes["width"].value.to_i \
132
+ * rect.attributes["height"].value.to_i
133
+
134
+ if(surf_rect > surf_max)
135
+ biggest_rect = rect
136
+ surf_max = surf_rect
137
+ end
138
+ end # rect.each
139
+
140
+ rect_id = biggest_rect.attributes["id"].value
141
+ transform = get_global_transform biggest_rect
142
+ @slides[id].set_geometry(biggest_rect, transform[0])
143
+
144
+ # The description (code to excute) might be in the group and not in the rect.
145
+ ## TODO: check if it should really be the first ?
146
+ desc = group.css("desc").first
147
+ title = group.css("title").first
148
+
149
+ if desc != nil
150
+ if title == nil || (title.text.match(/animation/) == nil and title.text.match(/video/) == nil)
151
+ puts "Group Description read #{desc.text}"
152
+
153
+ @slides[id].description = desc.text
154
+ end
155
+ end
156
+
157
+ e = @pshape.getChild(rect_id)
158
+ # hide the rect
159
+ if e == nil
160
+ puts "Error: rect ID: #{rect_id} not found "
161
+ else
162
+ @pshape.getChild(rect_id).setVisible(!@slides[id].hide)
163
+ end
164
+
165
+ puts "Slide #{id} created from a group, and the rectangle: #{rect_id}"
166
+
167
+ end
168
+
169
+
170
+
171
+
172
+ def load_videos
173
+ # Load the videos...
174
+ puts "Loading the videos..."
175
+
176
+ @svg.css("rect").each do |rect|
177
+
178
+ return if rect.attributes["id"] == nil
179
+ id = rect.attributes["id"].value #get the id
180
+
181
+ title = rect.css("title")
182
+ next if title == nil
183
+
184
+ is_video = title.text.match(/video/) != nil
185
+ next unless is_video
186
+
187
+ t = rect.css("desc").text.split("\n")
188
+ slide_id = t[0]
189
+ path = t[1]
190
+
191
+ puts ("Loading the video : " + path)
192
+
193
+ # Get the transformation
194
+ tr = get_global_transform rect
195
+
196
+ video = MyVideo.new(path, @slides[slide_id], tr[0], tr[1], tr[2])
197
+
198
+ if @slides[slide_id] == nil
199
+ puts "Error -> The video #{id} is linked to the slide #{slide_id} which is not found !"
200
+ else
201
+
202
+ @slides[slide_id].add_video(video)
203
+ puts "Video #{id} loaded with #{slide_id}"
204
+ end
205
+
206
+ # Hide the rect, and ... TODO replace it with a special object
207
+ # @pshape.getChild(id).setVisible(false)
208
+ end
209
+ end
210
+
211
+
212
+
213
+ def load_animations
214
+
215
+ puts "Loading the animations..."
216
+
217
+ @svg.css("*").each do |elem|
218
+
219
+ valid = false
220
+ elem.children.each do |child|
221
+ valid = true if child.name == "title" && child.text.match(/animation/)
222
+ end
223
+
224
+ next unless valid
225
+
226
+ id = elem.attributes["id"].value
227
+
228
+ # Get the animation information
229
+ t = elem.css("desc").text.split("\n")
230
+
231
+ # 1. which slide
232
+ # 2. when
233
+ slide_id = t[0]
234
+ anim_id = t[1].to_i
235
+
236
+ animation = OpenStruct.new
237
+ animation.pshape_elem = @pshape.getChild(id)
238
+
239
+ puts "Animation found on slide #{slide_id} with element #{animation.pshape_elem}"
240
+
241
+ if @slides[slide_id] == nil
242
+ puts "Error -> The animation #{id} is linked to the slide #{slide_id} which is not found !"
243
+ else
244
+ # add the animation
245
+ @slides[slide_id].add_animation(anim_id, animation)
246
+
247
+ # hide the group !
248
+ animation.pshape_elem.setVisible(false) unless animation.pshape_elem == nil
249
+ puts "Animation #{id} loaded with #{slide_id}"
250
+ end
251
+ end
252
+
253
+ end
254
+
255
+ def display_videos
256
+ if not @app.is_moving
257
+
258
+ slide_no = @app.current_slide_no
259
+
260
+ # # Display the videos
261
+ if slide_no > 0 and @slides[slide_no].has_videos?
262
+
263
+
264
+ # draw the object
265
+ @graphics.imageMode(Processing::App::CORNER)
266
+
267
+ @slides[slide_no].videos.each do |my_video|
268
+ @graphics.push_matrix
269
+ @graphics.modelview.apply(my_video.matrix)
270
+
271
+ # when the video is loaded it is saved... so that the memory can
272
+ # hopefully be freed
273
+ @playing_videos << my_video if my_video.play
274
+
275
+ # my_video.video.read if my_video.video.available?
276
+ # my_video.video.read
277
+ @graphics.image(my_video.video, 0, 0, my_video.width, my_video.height)
278
+
279
+
280
+ @graphics.pop_matrix
281
+ end # videos.each
282
+
283
+ else # has_videos
284
+
285
+ ## no video, free some memory
286
+ @playing_videos.each do |my_video|
287
+ puts "Saving memory. "
288
+ my_video.video.stop
289
+ my_video.video = nil
290
+ System.gc
291
+ end
292
+ @playing_videos = []
293
+ end
294
+ end
295
+ end
296
+
297
+
298
+
299
+ class MyVideo
300
+
301
+ include_package 'processing.video'
302
+ include_package 'processing.video.Movie'
303
+ include_package 'org.gestreamer.elements'
304
+
305
+ attr_reader :matrix, :width, :height, :slide
306
+ attr_accessor :video
307
+
308
+ def initialize(path, slide, matrix, width, height)
309
+ @path = path
310
+ @width = width
311
+ @height = height
312
+ @matrix = matrix
313
+ @slide = slide
314
+ end
315
+
316
+ def play
317
+ if @video == nil
318
+
319
+ absolute_path = $app.sketchPath "" << @path
320
+
321
+ puts ("loading the video : " + absolute_path)
322
+ vid = Movie.new($app, absolute_path)
323
+
324
+ # vid = Movie.new($app, @path)
325
+ puts "Loaded "
326
+ puts vid, vid.width, vid.height
327
+ vid.play
328
+ @video = vid
329
+ true
330
+ else
331
+ false
332
+ end
333
+ end
334
+
335
+ end
336
+
337
+
338
+ def to_s
339
+ "Slides #{@slides.size}"
340
+ end
341
+
342
+ end
data/lib/soby/slide.rb ADDED
@@ -0,0 +1,166 @@
1
+ class Slide
2
+
3
+ attr_accessor :next, :previous, :refid, :sequence, :hide, :matrix, :description
4
+ attr_reader :x, :y, :width, :height, :transform, :title ,:id
5
+
6
+ # transition states
7
+ attr_reader :transition_duration_ms, :timeout_ms, :timeout_enable, :transition_profile
8
+ attr_reader :videos, :animations
9
+
10
+
11
+ def initialize (element)
12
+
13
+ attr = element.attributes
14
+
15
+ ## Zoom & Path -> not used...
16
+ # @transition_path_hide = attr["transition-path-hide"].value
17
+ # @transition_zoom_percent = attr["transition-zoom-percent"].value
18
+
19
+ #Not always set ! We use the title instead
20
+ # @id = attr["id"].value
21
+
22
+ @transition_profile = attr["transition-profile"].value
23
+ @transition_duration_ms = attr["transition-duration-ms"].value.to_f
24
+ @timeout_ms = attr["timeout-ms"].value.to_f
25
+ @timeout_enable = attr["timeout-enable"].value == "true"
26
+ # @show_in_frame_list = attr["show-in-frame-list"].value
27
+
28
+ @clip = attr["clip"].value
29
+ @hide = attr["hide"].value == "true"
30
+ @sequence = attr["sequence"].value.to_i
31
+ @title = attr["title"].value
32
+ @refid = attr["refid"].value
33
+
34
+ init_transition_profile
35
+
36
+ @videos = []
37
+ @animations = []
38
+ @current_animation = 0
39
+ end
40
+
41
+ def is_hidden?
42
+ @hide
43
+ end
44
+
45
+
46
+ def init_transition_profile
47
+ case @transition_profile
48
+ when "linear"
49
+ @transition = Proc.new { |x| x }
50
+ when "accelerate"
51
+ @transition = Proc.new { |x| x**3 }
52
+ when "strong-accelerate"
53
+ @transition = Proc.new { |x| x**5 }
54
+ when "decelerate"
55
+ @transition = Proc.new { |x| 1 - Math.pow(1 - x, 3) }
56
+ when "strong-decelerate"
57
+ @transition = Proc.new { |x| 1 - Math.pow(1 - x, 5) }
58
+ when "accelerate-decelerate"
59
+ @transition = Proc.new { |x|
60
+ xs = x <= 0.5 ? x : 1 - x
61
+ y = Math.pow(2 * xs, 3) / 2
62
+ x <= 0.5 ? y : 1 - y
63
+ }
64
+ when "strong-decelerate-accelerate"
65
+ @transition = Proc.new { |x|
66
+ xs = x <= 0.5 ? x : 1 - x
67
+ y = Math.pow(2 * xs, 5) / 2
68
+ x <= 0.5 ? y : 1 - y
69
+ }
70
+ when "immediate-beginning"
71
+ @transition = Proc.new { |x| 1 }
72
+ when "immediate-end"
73
+ @transition = Proc.new { |x| x === 1 ? 1 : 0}
74
+ when "immediate-middle"
75
+ @transition = Proc.new { |x| x >= 0.5 ? 1 : 0}
76
+
77
+ else
78
+ @transition = Proc.new {|x| x }
79
+ end
80
+ end
81
+
82
+
83
+ def add_video (video)
84
+ @videos << video
85
+ end
86
+
87
+ def has_videos?()
88
+ @videos.size() != 0
89
+ end
90
+
91
+
92
+ def add_animation (id, animation)
93
+ @animations[id] = animation
94
+ end
95
+
96
+ def has_next_animation?()
97
+ return false if @animations.size == 0
98
+ return @current_animation < @animations.size
99
+ end
100
+
101
+ def next_animation
102
+ @current_animation = @current_animation + 1
103
+ @animations[@current_animation -1]
104
+ end
105
+
106
+ def has_previous_animation?()
107
+ return false if @animations.size == 0
108
+ return @current_animation > 0
109
+ end
110
+
111
+ def previous_animation
112
+ @current_animation = @current_animation - 1
113
+ @animations[@current_animation]
114
+ end
115
+
116
+
117
+ def set_geometry (element, matrix)
118
+
119
+ @matrix = matrix
120
+ attr = element.attributes
121
+
122
+ # @label = attr["label"].value
123
+ # @id = attr["id"].value
124
+ @x = attr["x"].value.to_f
125
+ @y = attr["y"].value.to_f
126
+ @width = attr["width"].value.to_f
127
+ @height = attr["height"].value.to_f
128
+
129
+ @description = element.css("desc").text if element.css("desc").size > 0
130
+ @title = element.css("title").text if element.css("title").size > 0
131
+
132
+ ## TODO : check if title != animation and video
133
+
134
+ # Animation & Video are not ruby Code !
135
+ if @title != nil
136
+ if @title.match(/animation/) or @title.match(/video/)
137
+ @description = nil
138
+ end
139
+ end
140
+
141
+ #eval @description if @description
142
+ end
143
+
144
+ def transition x
145
+ @transition.call x
146
+ end
147
+
148
+
149
+ def to_s
150
+ ["id ",@id.to_s ," ",
151
+ "transition_path_hide ",@transition_path_hide.to_s ," ",
152
+ "transition_profile ",@transition_profile.to_s ," ",
153
+ "transition_zoom_percent ",@transition_zoom_percent.to_s ," ",
154
+ "transition_duration_ms ",@transition_duration_ms.to_s ," ",
155
+ "timeout_ms ",@timeout_ms.to_s ," ",
156
+ "timeout_enable ",@timeout_enable.to_s ," ",
157
+ "show_in_frame_list ",@show_in_frame_list.to_s ," ",
158
+ "clip ",@clip.to_s ," ",
159
+ "hide ",@hide.to_s ," ",
160
+ "sequence ",@sequence.to_s ," ",
161
+ "title ",@title.to_s ," ",
162
+ "refid ",@refid.to_s ," " ].join
163
+ end
164
+ end
165
+
166
+
@@ -0,0 +1,53 @@
1
+
2
+ module Soby
3
+
4
+ include_package 'processing.core'
5
+
6
+ def read_transform (text)
7
+ if(text.match("matrix"))
8
+ text = text.split(/[,\(]/) # split with , or (
9
+ return PMatrix2D.new(text[1].to_f, text[3].to_f, text[5].to_f, \
10
+ text[2].to_f, text[4].to_f, text[6].to_f) if(text.size == 7)
11
+ end
12
+
13
+ if(text.match("translate"))
14
+ text = text.split(/[,\(]/)
15
+ return PMatrix2D.new(1, 0, text[1].to_f, 0, 1, text[2].to_f)
16
+ end
17
+ end
18
+
19
+
20
+ def get_global_transform element
21
+ e = element
22
+ global_transform = PMatrix3D.new
23
+
24
+ attr = e.attributes
25
+
26
+ global_transform.translate(attr["x"].value.to_f, attr["y"].value.to_f)
27
+
28
+ while e.class != Nokogiri::XML::Document do
29
+ t = e.attribute("transform")
30
+ if (t != nil)
31
+ tr = read_transform(t.value)
32
+ global_transform.preApply(tr)
33
+ end
34
+ e = e.parent
35
+ end
36
+
37
+ [global_transform , attr["width"].value.to_f, attr["height"].value.to_f]
38
+ end
39
+
40
+ def get_angle (mat)
41
+ Math.atan2(mat.m01, mat.m00)
42
+ end
43
+
44
+
45
+ def create_mat4x4(mat)
46
+ Matrix4x4.new(mat.m00, mat.m01, mat.m02, mat.m03,\
47
+ mat.m10, mat.m11, mat.m12, mat.m13,\
48
+ mat.m20, mat.m21, mat.m22, mat.m23,\
49
+ mat.m30, mat.m31, mat.m32, mat.m33)
50
+ end
51
+
52
+
53
+ end
data/lib/soby.rb ADDED
@@ -0,0 +1,403 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'nokogiri' # for XML.
4
+ require 'ruby-processing'
5
+ require 'java'
6
+
7
+ # For the other files, we need to load the libraries
8
+ Processing::App::load_library 'video', 'toxiclibscore'
9
+
10
+ require_relative 'soby/transforms'
11
+ require_relative 'soby/presentation'
12
+ require_relative 'soby/slide'
13
+ require_relative 'soby/cam'
14
+
15
+ class SobyPlayer < Processing::App
16
+
17
+ include_package 'processing.core'
18
+ include_package 'toxi.geom'
19
+
20
+ import 'toxi.geom.Matrix4x4'
21
+
22
+ attr_accessor :prez, :prev_cam, :next_cam, :slides
23
+ attr_reader :is_moving, :current_slide_no
24
+
25
+ # attr_accessor :background_max_color, :background_min_color, :background_constrain
26
+ attr_accessor :cam
27
+
28
+
29
+ def running? () @is_running end
30
+
31
+ TRANSITION_DURATION = 1000
32
+
33
+ # no Border
34
+ def init
35
+ super
36
+ removeFrameBorder
37
+ end
38
+
39
+ def removeFrameBorder
40
+ frame.removeNotify
41
+ frame.setUndecorated true
42
+ frame.addNotify
43
+ end
44
+
45
+
46
+ def setup
47
+ @ready = false
48
+ size 1024, 768, OPENGL
49
+
50
+ ## Some bugs with this.
51
+ ## frame.setResizable true if frame != nil
52
+
53
+ init_player
54
+
55
+ @custom_setup_done = true
56
+ @ready = true
57
+ end
58
+
59
+ def ready?
60
+ @ready
61
+ end
62
+
63
+ def init_player
64
+ @prez = nil
65
+ @current_slide_no = 0
66
+ @is_running = false
67
+ init_cameras
68
+ end
69
+
70
+ def init_cameras
71
+ # current camera matrix
72
+ @cam = PMatrix3D.new
73
+
74
+ # Cameras for movement.
75
+ @prev_cam = Cam.new
76
+ @next_cam = Cam.new
77
+ @is_moving = false
78
+ @current_ratio = 0
79
+ end
80
+
81
+
82
+ ## To be overriden by the Presentation Code.
83
+ def custom_setup
84
+
85
+ end
86
+
87
+ def custom_pre_draw
88
+ background(255)
89
+ end
90
+
91
+ def custom_post_draw
92
+
93
+ end
94
+
95
+
96
+ def draw
97
+
98
+ if not @custom_setup_done
99
+ custom_setup
100
+ @custom_setup_done = true
101
+ end
102
+
103
+ custom_pre_draw
104
+
105
+ smooth(8)
106
+
107
+ shapeMode(CORNER)
108
+ imageMode(CORNER)
109
+
110
+ if(running?)
111
+
112
+ push_matrix
113
+
114
+ update_cam
115
+ self.g.modelview.apply(@cam)
116
+ @prez.draw
117
+ @prez.display_videos
118
+ pop_matrix
119
+
120
+ run_slide_code
121
+ display_slide_number
122
+ end
123
+
124
+ custom_post_draw
125
+ end
126
+
127
+ def run_slide_code
128
+ translate 0, 0, 1
129
+ if not @is_moving and @current_slide_no != 0
130
+ desc = @prez.slides[@current_slide_no].description
131
+ if(desc != nil)
132
+ # puts "EVAL #{desc}"
133
+ eval desc
134
+ end
135
+ end
136
+ end
137
+
138
+
139
+ def display_slide_number
140
+ # Slide number
141
+ push_matrix
142
+ translate(@width - 40, @height - 45)
143
+ fill(30)
144
+ strokeWeight(3)
145
+ stroke(190)
146
+ ellipseMode(CENTER)
147
+ ellipse(18, 22, 35, 35)
148
+ fill(255)
149
+ noStroke
150
+ textSize(20)
151
+ text(@current_slide_no.to_s, 10, 30)
152
+ pop_matrix
153
+ end
154
+
155
+ alias :default_display_slide_number :display_slide_number
156
+
157
+
158
+ def key_pressed
159
+
160
+ if key == 'g'
161
+ puts "Garbage"
162
+ Java::JavaLang::System.gc
163
+ end
164
+
165
+ return if @prez == nil
166
+
167
+ if keyCode == LEFT
168
+ prev_slide
169
+ end
170
+
171
+ if keyCode == RIGHT
172
+ next_slide
173
+ end
174
+
175
+ # puts "slide #{@current_slide_no} "
176
+ end
177
+
178
+ def mouse_dragged
179
+ if not @is_moving
180
+ tr = PMatrix3D.new
181
+ tr.translate(mouse_x - pmouse_x, mouse_y - pmouse_y)
182
+
183
+ @cam.preApply(tr)
184
+ @next_cam.mat.preApply(tr)
185
+ end
186
+ end
187
+
188
+ def mouseWheel(event)
189
+ e = event.getAmount()
190
+ if not @is_moving
191
+ tr = PMatrix3D.new
192
+ tr.translate(mouse_x, mouse_y)
193
+ tr.scale(e < 0 ? 1.05 : 1 / 1.05)
194
+ tr.translate(-mouse_x, -mouse_y)
195
+ @cam.preApply(tr)
196
+ end
197
+ end
198
+
199
+
200
+ def set_prez (prez)
201
+ # PShape.loadedImages.clear
202
+ @prez = prez
203
+ @slides = prez.slides
204
+ goto_slide 0
205
+ @is_running = true
206
+ @prez_middle = PVector.new(@prez.width / 2.0, @prez.height / 2.0)
207
+
208
+ puts "Presentation size "
209
+ puts @prez.width
210
+ puts @prez.height
211
+
212
+ @custom_setup_done = false
213
+ end
214
+
215
+ def compute_view(view, slide_number)
216
+ # view = createGraphics(@width, @height, P3D)
217
+ # @next_view = createGraphics(@width, @height)
218
+ view.beginDraw
219
+
220
+ cam = slide_view slide_number
221
+ view.g.modelview.apply(cam)
222
+ view.shapeMode(CORNER)
223
+ view.shape(@prez.pshape, 0, 0)
224
+ view.endDraw
225
+
226
+ view
227
+ end
228
+
229
+
230
+ def next_slide
231
+ is_last_slide = @current_slide_no >= @prez.nb_slides
232
+ is_slide_zero = current_slide_no == 0
233
+
234
+ # Gloal view
235
+ if is_slide_zero
236
+ goto_slide(@current_slide_no + 1)
237
+ return
238
+ end
239
+
240
+ # animation
241
+ if @slides[@current_slide_no].has_next_animation?
242
+ puts "Animation Next "
243
+ anim = @slides[@current_slide_no].next_animation
244
+ anim.pshape_elem.setVisible(true)
245
+ else
246
+ goto_slide(@current_slide_no + 1) unless is_last_slide
247
+ end
248
+
249
+ end
250
+
251
+ def prev_slide
252
+ return if @current_slide_no <= 0
253
+
254
+ if current_slide_no == 0
255
+ goto_slide(@current_slide_no - 1)
256
+ return
257
+ end
258
+
259
+ if @slides[@current_slide_no].has_previous_animation?
260
+ puts "Animation Previous "
261
+ anim = @slides[@current_slide_no].previous_animation
262
+ anim.pshape_elem.setVisible(false)
263
+ else
264
+ goto_slide(@current_slide_no - 1)
265
+ end
266
+
267
+ end
268
+
269
+ def goto_slide (next_slide)
270
+
271
+ current_slide = @current_slide_no
272
+
273
+ use_global_view = next_slide == 0 || next_slide > @prez.slides.size
274
+
275
+ cam = global_view if use_global_view
276
+ cam = slide_view(next_slide) if next_slide > 0
277
+
278
+ # previous next is now old.
279
+ @prev_cam = @next_cam
280
+ @prev_cam.mat.set(@cam)
281
+ @next_cam = cam
282
+
283
+ @current_slide_no = next_slide
284
+
285
+ if use_global_view
286
+ @transition_duration = TRANSITION_DURATION.to_f
287
+ else
288
+ @transition_duration = @slides[@current_slide_no].transition_duration_ms
289
+ end
290
+
291
+ @transition_start_time = millis
292
+ @is_moving = true
293
+ @current_ratio = 0
294
+
295
+ ## trigger the slide_change function (user defined)
296
+ slide_change
297
+ end
298
+
299
+ def slide_change
300
+
301
+ end
302
+
303
+
304
+ def update_cam
305
+
306
+ return unless @is_moving
307
+ return if @slides.size == 0
308
+
309
+ elapsed_time = millis - @transition_start_time
310
+ @current_ratio = elapsed_time.to_f / @transition_duration.to_f
311
+
312
+ @current_ratio = @slides[@current_slide_no].transition @current_ratio unless @current_slide_no == 0
313
+
314
+ if @current_ratio > 1 && @is_moving
315
+ @is_moving = false
316
+ @cam = @prev_cam.lerp(@next_cam, 1)
317
+
318
+ # save a copy
319
+ @prev_cam.mat = @cam.get
320
+ return
321
+ end
322
+
323
+ # puts @current_ratio
324
+ @cam = @prev_cam.lerp(@next_cam, @current_ratio)
325
+
326
+ end
327
+
328
+ def slide_view (slide_no)
329
+
330
+ if slide_no > @prez.slides.size
331
+ puts "No more slides"
332
+ return
333
+ end
334
+
335
+ return if @prez.slides[slide_no] == nil
336
+
337
+ puts "slide view..." << slide_no.to_s
338
+
339
+ # check slide number
340
+ w = @prez.slides[slide_no].width
341
+ h = @prez.slides[slide_no].height
342
+ x = @prez.slides[slide_no].x
343
+ y = @prez.slides[slide_no].y
344
+
345
+ sc1 = @width.to_f / w.to_f
346
+ sc2 = @height.to_f / h.to_f
347
+
348
+ # scale
349
+ sc = [sc1, sc2].min
350
+
351
+
352
+ # translate
353
+ dx = ((@width / sc) - w) * 0.5
354
+ dy = ((@height / sc) - h) * 0.5
355
+
356
+ cam = Cam.new
357
+
358
+ m = PMatrix3D.new
359
+ m.apply @prez.slides[slide_no].matrix
360
+ m.invert
361
+
362
+ # Scale
363
+ tr = PMatrix3D.new
364
+ tr.scale(sc)
365
+ m.preApply(tr)
366
+ m.translate(dx, dy)
367
+
368
+ # center
369
+ cam.mat = m
370
+ cam
371
+
372
+ end
373
+
374
+
375
+ def global_view
376
+ # ortho(left, right, bottom, top)
377
+ # frustum(left, right, bottom, top, near, far)
378
+
379
+ my_scale = find_scale
380
+
381
+ # centering
382
+ dx = ((@width / my_scale) - @prez.width) * 0.5
383
+ dy = ((@height / my_scale) - @prez.height) * 0.5
384
+
385
+ cam = Cam.new
386
+ cam.scale = my_scale
387
+ # Not necessary : display from the center...
388
+ cam.post_translation.set(dx, dy)
389
+ cam.compute_mat
390
+ cam
391
+ end
392
+
393
+ def find_scale
394
+ sc1 = @width / @prez.width
395
+ sc2 = @height / @prez.height
396
+ return [sc1, sc2].min
397
+ end
398
+ private :find_scale
399
+
400
+
401
+ end
402
+
403
+
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: soby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Laviole
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.3
20
+ requirement: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - '>='
23
+ - !ruby/object:Gem::Version
24
+ version: 1.6.3
25
+ prerelease: false
26
+ type: :runtime
27
+ - !ruby/object:Gem::Dependency
28
+ name: ruby-processing
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.6.7
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - '>='
37
+ - !ruby/object:Gem::Version
38
+ version: 2.6.7
39
+ prerelease: false
40
+ type: :runtime
41
+ description: Based on Sozi, it works plays presentation using Ruby-processing.
42
+ email: poqudrof@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - lib/soby.rb
48
+ - lib/soby/cam.rb
49
+ - lib/soby/slide.rb
50
+ - lib/soby/presentation.rb
51
+ - lib/soby/transforms.rb
52
+ homepage: https://github.com/poqudrof/Soby
53
+ licenses:
54
+ - LGPL
55
+ metadata: {}
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 2.1.9
73
+ signing_key:
74
+ specification_version: 4
75
+ summary: Sozi player !
76
+ test_files: []