soby 0.0.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 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: []