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