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 #ifndef GPAC_DISABLE_VRML
29
Bindable_GetStack(GF_Node * bindable)30 GF_List *Bindable_GetStack(GF_Node *bindable)
31 {
32 void *st;
33 if (!bindable) return 0;
34 st = gf_node_get_private(bindable);
35 switch (gf_node_get_tag(bindable)) {
36 case TAG_MPEG4_Background2D:
37 return ((Background2DStack*)st)->reg_stacks;
38 case TAG_MPEG4_Viewport:
39 case TAG_MPEG4_NavigationInfo:
40 #ifndef GPAC_DISABLE_X3D
41 case TAG_X3D_NavigationInfo:
42 #endif
43 return ((ViewStack*)st)->reg_stacks;
44 #ifndef GPAC_DISABLE_3D
45 case TAG_MPEG4_Background:
46 #ifndef GPAC_DISABLE_X3D
47 case TAG_X3D_Background:
48 #endif
49 return ((BackgroundStack*)st)->reg_stacks;
50 case TAG_MPEG4_Viewpoint:
51 case TAG_MPEG4_Fog:
52 #ifndef GPAC_DISABLE_X3D
53 case TAG_X3D_Viewpoint:
54 case TAG_X3D_Fog:
55 #endif
56 return ((ViewStack*)st)->reg_stacks;
57 #endif
58 default:
59 return NULL;
60 }
61 }
62
Bindable_GetIsBound(GF_Node * bindable)63 Bool Bindable_GetIsBound(GF_Node *bindable)
64 {
65 if (!bindable) return GF_FALSE;
66 switch (gf_node_get_tag(bindable)) {
67 case TAG_MPEG4_Background2D:
68 return ((M_Background2D*)bindable)->isBound;
69 case TAG_MPEG4_Viewport:
70 return ((M_Viewport*)bindable)->isBound;
71 case TAG_MPEG4_Background:
72 #ifndef GPAC_DISABLE_X3D
73 case TAG_X3D_Background:
74 #endif
75 return ((M_Background*)bindable)->isBound;
76 case TAG_MPEG4_NavigationInfo:
77 #ifndef GPAC_DISABLE_X3D
78 case TAG_X3D_NavigationInfo:
79 #endif
80 return ((M_NavigationInfo*)bindable)->isBound;
81 case TAG_MPEG4_Viewpoint:
82 #ifndef GPAC_DISABLE_X3D
83 case TAG_X3D_Viewpoint:
84 #endif
85 return ((M_Viewpoint*)bindable)->isBound;
86 case TAG_MPEG4_Fog:
87 #ifndef GPAC_DISABLE_X3D
88 case TAG_X3D_Fog:
89 #endif
90 return ((M_Fog*)bindable)->isBound;
91 default:
92 return GF_FALSE;
93 }
94 }
95
Bindable_SetIsBound(GF_Node * bindable,Bool val)96 void Bindable_SetIsBound(GF_Node *bindable, Bool val)
97 {
98 Bool has_bind_time = GF_FALSE;
99 if (!bindable) return;
100 switch (gf_node_get_tag(bindable)) {
101 case TAG_MPEG4_Background2D:
102 if ( ((M_Background2D*)bindable)->isBound == val) return;
103 ((M_Background2D*)bindable)->isBound = val;
104 break;
105 case TAG_MPEG4_Viewport:
106 if ( ((M_Viewport*)bindable)->isBound == val) return;
107 ((M_Viewport*)bindable)->isBound = val;
108 ((M_Viewport*)bindable)->bindTime = gf_node_get_scene_time(bindable);
109 has_bind_time = GF_TRUE;
110 break;
111 #ifndef GPAC_DISABLE_X3D
112 case TAG_X3D_Background:
113 if ( ((X_Background*)bindable)->isBound == val) return;
114 ((X_Background*)bindable)->isBound = val;
115 ((X_Background*)bindable)->bindTime = gf_node_get_scene_time(bindable);
116 has_bind_time = GF_TRUE;
117 break;
118 #endif
119 case TAG_MPEG4_Background:
120 if ( ((M_Background*)bindable)->isBound == val) return;
121 ((M_Background*)bindable)->isBound = val;
122 break;
123 #ifndef GPAC_DISABLE_X3D
124 case TAG_X3D_NavigationInfo:
125 if ( ((X_NavigationInfo*)bindable)->isBound == val) return;
126 ((X_NavigationInfo*)bindable)->isBound = val;
127 ((X_NavigationInfo*)bindable)->bindTime = gf_node_get_scene_time(bindable);
128 has_bind_time = GF_TRUE;
129 break;
130 #endif
131 case TAG_MPEG4_NavigationInfo:
132 if ( ((M_NavigationInfo*)bindable)->isBound == val) return;
133 ((M_NavigationInfo*)bindable)->isBound = val;
134 break;
135 case TAG_MPEG4_Viewpoint:
136 #ifndef GPAC_DISABLE_X3D
137 case TAG_X3D_Viewpoint:
138 #endif
139 if ( ((M_Viewpoint*)bindable)->isBound == val) return;
140 ((M_Viewpoint*)bindable)->isBound = val;
141 ((M_Viewpoint*)bindable)->bindTime = gf_node_get_scene_time(bindable);
142 has_bind_time = GF_TRUE;
143 break;
144 #ifndef GPAC_DISABLE_X3D
145 case TAG_X3D_Fog:
146 if ( ((X_Fog*)bindable)->isBound == val) return;
147 ((X_Fog*)bindable)->isBound = val;
148 ((X_Fog*)bindable)->bindTime = gf_node_get_scene_time(bindable);
149 has_bind_time = GF_TRUE;
150 break;
151 #endif
152 case TAG_MPEG4_Fog:
153 if ( ((M_Fog*)bindable)->isBound == val) return;
154 ((M_Fog*)bindable)->isBound = val;
155 break;
156 default:
157 return;
158 }
159 gf_node_event_out_str(bindable, "isBound");
160 if (has_bind_time) gf_node_event_out_str(bindable, "bindTime");
161 /*force invalidate of the bindable stack's owner*/
162 gf_node_dirty_set(bindable, 0, GF_TRUE);
163 }
164
165
Bindable_GetSetBind(GF_Node * bindable)166 Bool Bindable_GetSetBind(GF_Node *bindable)
167 {
168 if (!bindable) return GF_FALSE;
169 switch (gf_node_get_tag(bindable)) {
170 case TAG_MPEG4_Background2D:
171 return ((M_Background2D*)bindable)->set_bind;
172 case TAG_MPEG4_Viewport:
173 return ((M_Viewport*)bindable)->set_bind;
174 case TAG_MPEG4_Background:
175 #ifndef GPAC_DISABLE_X3D
176 case TAG_X3D_Background:
177 #endif
178 return ((M_Background*)bindable)->set_bind;
179 case TAG_MPEG4_NavigationInfo:
180 #ifndef GPAC_DISABLE_X3D
181 case TAG_X3D_NavigationInfo:
182 #endif
183 return ((M_NavigationInfo*)bindable)->set_bind;
184 case TAG_MPEG4_Viewpoint:
185 #ifndef GPAC_DISABLE_X3D
186 case TAG_X3D_Viewpoint:
187 #endif
188 return ((M_Viewpoint*)bindable)->set_bind;
189 case TAG_MPEG4_Fog:
190 #ifndef GPAC_DISABLE_X3D
191 case TAG_X3D_Fog:
192 #endif
193 return ((M_Fog*)bindable)->set_bind;
194 default:
195 return GF_FALSE;
196 }
197 }
198
Bindable_SetSetBindEx(GF_Node * bindable,Bool val,GF_List * stack)199 void Bindable_SetSetBindEx(GF_Node *bindable, Bool val, GF_List *stack)
200 {
201 if (!bindable) return;
202 switch (gf_node_get_tag(bindable)) {
203 case TAG_MPEG4_Background2D:
204 ((M_Background2D*)bindable)->set_bind = val;
205 ((M_Background2D*)bindable)->on_set_bind(bindable, NULL);
206 break;
207 case TAG_MPEG4_Viewport:
208 ((M_Viewport*)bindable)->set_bind = val;
209 ((M_Viewport*)bindable)->on_set_bind(bindable, (GF_Route*)stack);
210 break;
211 case TAG_MPEG4_Background:
212 #ifndef GPAC_DISABLE_X3D
213 case TAG_X3D_Background:
214 #endif
215 ((M_Background*)bindable)->set_bind = val;
216 ((M_Background*)bindable)->on_set_bind(bindable, NULL);
217 break;
218 case TAG_MPEG4_NavigationInfo:
219 #ifndef GPAC_DISABLE_X3D
220 case TAG_X3D_NavigationInfo:
221 #endif
222 ((M_NavigationInfo*)bindable)->set_bind = val;
223 ((M_NavigationInfo*)bindable)->on_set_bind(bindable, NULL);
224 break;
225 case TAG_MPEG4_Viewpoint:
226 #ifndef GPAC_DISABLE_X3D
227 case TAG_X3D_Viewpoint:
228 #endif
229 ((M_Viewpoint*)bindable)->set_bind = val;
230 ((M_Viewpoint*)bindable)->on_set_bind(bindable, NULL);
231 break;
232 case TAG_MPEG4_Fog:
233 #ifndef GPAC_DISABLE_X3D
234 case TAG_X3D_Fog:
235 #endif
236 ((M_Fog*)bindable)->set_bind = val;
237 ((M_Fog*)bindable)->on_set_bind(bindable, NULL);
238 break;
239 default:
240 return;
241 }
242 }
Bindable_SetSetBind(GF_Node * bindable,Bool val)243 void Bindable_SetSetBind(GF_Node *bindable, Bool val)
244 {
245 Bindable_SetSetBindEx(bindable, val, NULL);
246 }
247
Bindable_OnSetBind(GF_Node * bindable,GF_List * stack_list,GF_List * for_stack)248 void Bindable_OnSetBind(GF_Node *bindable, GF_List *stack_list, GF_List *for_stack)
249 {
250 u32 i;
251 Bool on_top, is_bound, set_bind;
252 GF_Node *node;
253 GF_List *stack;
254
255 set_bind = Bindable_GetSetBind(bindable);
256 is_bound = Bindable_GetIsBound(bindable);
257
258 if (!set_bind && !is_bound) return;
259 if (set_bind && is_bound) return;
260
261 i=0;
262 while ((stack = (GF_List*)gf_list_enum(stack_list, &i))) {
263 if (for_stack && (for_stack!=stack)) continue;
264
265 on_top = (gf_list_get(stack, 0)==bindable) ? GF_TRUE : GF_FALSE;
266
267 if (!set_bind) {
268 if (is_bound) Bindable_SetIsBound(bindable, GF_FALSE);
269 if (on_top && (gf_list_count(stack)>1)) {
270 gf_list_rem(stack, 0);
271 gf_list_add(stack, bindable);
272 node = (GF_Node*)gf_list_get(stack, 0);
273 Bindable_SetIsBound(node, GF_TRUE);
274 }
275 } else {
276 if (!is_bound) Bindable_SetIsBound(bindable, GF_TRUE);
277 if (!on_top) {
278 /*push old top one down and unbind*/
279 node = (GF_Node*)gf_list_get(stack, 0);
280 Bindable_SetIsBound(node, GF_FALSE);
281 /*insert new top*/
282 gf_list_del_item(stack, bindable);
283 gf_list_insert(stack, bindable, 0);
284 }
285 }
286 }
287 /*force invalidate of the bindable stack's owner*/
288 gf_node_dirty_set(bindable, 0, GF_TRUE);
289 /*and redraw scene*/
290 gf_sc_invalidate(gf_sc_get_compositor(bindable), NULL);
291 }
292
BindableStackDelete(GF_List * stack)293 void BindableStackDelete(GF_List *stack)
294 {
295 while (gf_list_count(stack)) {
296 GF_List *bind_stack_list;
297 GF_Node *bindable = (GF_Node*)gf_list_get(stack, 0);
298 gf_list_rem(stack, 0);
299 bind_stack_list = Bindable_GetStack(bindable);
300 if (bind_stack_list) {
301 gf_list_del_item(bind_stack_list, stack);
302 assert(gf_list_find(bind_stack_list, stack)<0);
303 }
304 }
305 gf_list_del(stack);
306 }
307
PreDestroyBindable(GF_Node * bindable,GF_List * stack_list)308 void PreDestroyBindable(GF_Node *bindable, GF_List *stack_list)
309 {
310 Bool is_bound = Bindable_GetIsBound(bindable);
311 Bindable_SetIsBound(bindable, GF_FALSE);
312
313 while (gf_list_count(stack_list)) {
314 GF_List *stack = (GF_List*)gf_list_get(stack_list, 0);
315 gf_list_rem(stack_list, 0);
316 gf_list_del_item(stack, bindable);
317 if (is_bound) {
318 GF_Node *stack_top = (GF_Node*)gf_list_get(stack, 0);
319 if (stack_top) Bindable_SetSetBind(stack_top, GF_TRUE);
320 }
321 }
322 }
323
324 #endif /*GPAC_DISABLE_VRML*/
325