Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Compositor sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 :
26 : #include "nodes_stacks.h"
27 :
28 : #include <gpac/nodes_mpeg4.h>
29 : #include <gpac/nodes_x3d.h>
30 :
31 :
32 : #ifndef GPAC_DISABLE_VRML
33 :
34 : typedef struct
35 : {
36 : GF_TimeNode time_handle;
37 : Bool store_info;
38 : Double start_time, cycle_interval;
39 : u32 num_cycles;
40 : GF_Compositor *compositor;
41 : #ifndef GPAC_DISABLE_X3D
42 : Bool is_x3d;
43 : #endif
44 : } TimeSensorStack;
45 :
46 92464 : static void timesensor_destroy(GF_Node *ts, void *rs, Bool is_destroy)
47 : {
48 92464 : if (is_destroy) {
49 536 : TimeSensorStack *st = (TimeSensorStack *)gf_node_get_private(ts);
50 536 : if (st->time_handle.is_registered) {
51 139 : gf_sc_unregister_time_node(st->compositor, &st->time_handle);
52 : }
53 536 : gf_free(st);
54 : }
55 92464 : }
56 :
57 :
58 : static
59 : void timesensor_deactivate(TimeSensorStack *stack, M_TimeSensor *ts)
60 : {
61 96 : ts->isActive = 0;
62 96 : gf_node_event_out((GF_Node *) ts, 7);//"isActive"
63 : assert(stack->time_handle.is_registered);
64 96 : stack->time_handle.needs_unregister = 1;
65 96 : stack->num_cycles = 0;
66 : }
67 :
68 : static
69 23090 : void timesensor_update_time(GF_TimeNode *st)
70 : {
71 : Double currentTime, cycleTime;
72 : Fixed newFraction;
73 : u32 inc;
74 23090 : M_TimeSensor *TS = (M_TimeSensor *)st->udta;
75 23090 : TimeSensorStack *stack = (TimeSensorStack *)gf_node_get_private(st->udta);
76 :
77 23090 : if (! TS->enabled) {
78 458 : if (TS->isActive) {
79 6 : TS->cycleTime = gf_node_get_scene_time(st->udta);
80 6 : gf_node_event_out(st->udta, 5);//"cycleTime"
81 : timesensor_deactivate(stack, TS);
82 : }
83 : return;
84 : }
85 :
86 22632 : if (stack->store_info) {
87 653 : stack->store_info = 0;
88 653 : stack->start_time = TS->startTime;
89 653 : stack->cycle_interval = TS->cycleInterval;
90 : }
91 :
92 22632 : currentTime = gf_node_get_scene_time(st->udta);
93 22632 : if (!TS->isActive) {
94 2511 : if (currentTime < stack->start_time) return;
95 : /*special case: if we're greater than both start and stop time don't activate*/
96 797 : if (!TS->isActive && (TS->stopTime > stack->start_time) && (currentTime >= TS->stopTime)) {
97 418 : stack->time_handle.needs_unregister = 1;
98 418 : return;
99 : }
100 : #ifndef GPAC_DISABLE_X3D
101 379 : if (stack->is_x3d && !TS->loop) {
102 152 : if (!stack->start_time && !gf_sys_old_arch_compat() ) return;
103 152 : if (currentTime >= TS->startTime+stack->cycle_interval) return;
104 : }
105 : #endif
106 : }
107 :
108 20348 : cycleTime = currentTime - stack->start_time - stack->num_cycles * stack->cycle_interval;
109 20348 : newFraction = FLT2FIX ( fmod(cycleTime, stack->cycle_interval) / stack->cycle_interval );
110 :
111 20348 : if (TS->isActive) {
112 20121 : TS->time = currentTime;
113 20121 : gf_node_event_out(st->udta, 8);//"time"
114 :
115 : /*VRML:
116 : "f = fmod( (now - startTime) , cycleInterval) / cycleInterval
117 : if (f == 0.0 && now > startTime) fraction_changed = 1.0
118 : else fraction_changed = f"
119 : */
120 20121 : if (!newFraction && (currentTime > stack->start_time ) ) newFraction = FIX_ONE;
121 :
122 : /*check for deactivation - if so generate a fraction_changed AS IF NOW WAS EXACTLY STOPTIME*/
123 20121 : if ((TS->stopTime > stack->start_time) && (currentTime >= TS->stopTime) ) {
124 10 : cycleTime = TS->stopTime - stack->start_time - stack->num_cycles * stack->cycle_interval;
125 10 : TS->fraction_changed = FLT2FIX( fmod(cycleTime, stack->cycle_interval) / stack->cycle_interval );
126 : /*cf above*/
127 10 : if (TS->fraction_changed < FIX_EPSILON) TS->fraction_changed = FIX_ONE;
128 10 : gf_node_event_out(st->udta, 6);//"fraction_changed"
129 : timesensor_deactivate(stack, TS);
130 : return;
131 : }
132 20111 : if (! TS->loop) {
133 2055 : if (cycleTime >= stack->cycle_interval) {
134 80 : TS->fraction_changed = FIX_ONE;
135 80 : gf_node_event_out(st->udta, 6);//"fraction_changed"
136 : timesensor_deactivate(stack, TS);
137 : return;
138 : }
139 : }
140 20031 : if (newFraction != TS->fraction_changed) {
141 19278 : TS->fraction_changed = newFraction;
142 19278 : gf_node_event_out(st->udta, 6);//"fraction_changed"
143 : }
144 : }
145 :
146 : /*we're (about to be) active: VRML:
147 : "A time-dependent node is inactive until its startTime is reached. When time now becomes greater than or
148 : equal to startTime, an isActive TRUE event is generated and the time-dependent node becomes active */
149 :
150 20258 : if (!TS->isActive) {
151 227 : st->needs_unregister = 0;
152 227 : TS->isActive = 1;
153 227 : gf_node_event_out(st->udta, 7); //"isActive"
154 227 : TS->cycleTime = currentTime;
155 227 : gf_node_event_out(st->udta, 5);//"cycleTime"
156 227 : TS->fraction_changed = newFraction;
157 227 : gf_node_event_out(st->udta, 6);//"fraction_changed"
158 : }
159 :
160 : //compute cycle time
161 20258 : if (TS->loop && (cycleTime >= stack->cycle_interval) ) {
162 655 : inc = 1 + (u32) ( (cycleTime - stack->cycle_interval ) / stack->cycle_interval );
163 655 : stack->num_cycles += inc;
164 655 : cycleTime -= inc*stack->cycle_interval;
165 655 : TS->cycleTime = currentTime - cycleTime;
166 655 : gf_node_event_out(st->udta, 5);//"cycleTime"
167 : }
168 : }
169 :
170 536 : void compositor_init_timesensor(GF_Compositor *compositor, GF_Node *node)
171 : {
172 : TimeSensorStack *st;
173 536 : GF_SAFEALLOC(st, TimeSensorStack);
174 536 : if (!st) {
175 0 : GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Compositor] Failed to allocate time sensor 2d stack\n"));
176 : return;
177 : }
178 536 : st->time_handle.UpdateTimeNode = timesensor_update_time;
179 536 : st->time_handle.udta = node;
180 536 : st->store_info = 1;
181 536 : st->compositor = compositor;
182 : #ifndef GPAC_DISABLE_X3D
183 536 : st->is_x3d = (gf_node_get_tag(node)==TAG_X3D_TimeSensor) ? 1 : 0;
184 : #endif
185 536 : gf_node_set_private(node, st);
186 536 : gf_node_set_callback_function(node, timesensor_destroy);
187 : /*time sensor needs to be run only if def'ed, otherwise it doesn't impact scene*/
188 : //if (gf_node_get_id(node))
189 536 : gf_sc_register_time_node(compositor, &st->time_handle);
190 : }
191 :
192 :
193 325 : void compositor_timesensor_modified(GF_Node *t)
194 : {
195 : M_TimeSensor *ts = (M_TimeSensor *)t;
196 325 : TimeSensorStack *stack = (TimeSensorStack *) gf_node_get_private(t);
197 325 : if (!stack) return;
198 :
199 325 : if (ts->isActive) timesensor_update_time(&stack->time_handle);
200 :
201 325 : if (!ts->isActive) stack->store_info = 1;
202 :
203 325 : if (ts->enabled) {
204 293 : stack->time_handle.needs_unregister = 0;
205 293 : if (!stack->time_handle.is_registered) {
206 110 : gf_sc_register_time_node(stack->compositor, &stack->time_handle);
207 : }
208 : }
209 : }
210 :
211 : #endif /*GPAC_DISABLE_VRML*/
|