| /* | |
| * GPAC - Multimedia Framework C SDK | |
| * | |
| * Authors: Jean Le Feuvre | |
| * Copyright (c) Telecom ParisTech 2000-2023 | |
| * All rights reserved | |
| * | |
| * This file is part of GPAC / Scene Compositor sub-project | |
| * | |
| * GPAC is free software; you can redistribute it and/or modify | |
| * it under the terms of the GNU Lesser General Public License as published by | |
| * the Free Software Foundation; either version 2, or (at your option) | |
| * any later version. | |
| * | |
| * GPAC is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; see the file COPYING. If not, write to | |
| * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
| * | |
| */ | |
| #include "nodes_stacks.h" | |
| #if !defined(GPAC_DISABLE_VRML) && !defined(GPAC_DISABLE_COMPOSITOR) | |
| GF_List *Bindable_GetStack(GF_Node *bindable) | |
| { | |
| void *st; | |
| if (!bindable) return 0; | |
| st = gf_node_get_private(bindable); | |
| switch (gf_node_get_tag(bindable)) { | |
| case TAG_MPEG4_Background2D: | |
| return ((Background2DStack*)st)->reg_stacks; | |
| case TAG_MPEG4_Viewport: | |
| case TAG_MPEG4_NavigationInfo: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_NavigationInfo: | |
| #endif | |
| return ((ViewStack*)st)->reg_stacks; | |
| #ifndef GPAC_DISABLE_3D | |
| case TAG_MPEG4_Background: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Background: | |
| #endif | |
| return ((BackgroundStack*)st)->reg_stacks; | |
| case TAG_MPEG4_Viewpoint: | |
| case TAG_MPEG4_Fog: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Viewpoint: | |
| case TAG_X3D_Fog: | |
| #endif | |
| return ((ViewStack*)st)->reg_stacks; | |
| #endif | |
| default: | |
| return NULL; | |
| } | |
| } | |
| Bool Bindable_GetIsBound(GF_Node *bindable) | |
| { | |
| if (!bindable) return GF_FALSE; | |
| switch (gf_node_get_tag(bindable)) { | |
| case TAG_MPEG4_Background2D: | |
| return ((M_Background2D*)bindable)->isBound; | |
| case TAG_MPEG4_Viewport: | |
| return ((M_Viewport*)bindable)->isBound; | |
| case TAG_MPEG4_Background: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Background: | |
| #endif | |
| return ((M_Background*)bindable)->isBound; | |
| case TAG_MPEG4_NavigationInfo: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_NavigationInfo: | |
| #endif | |
| return ((M_NavigationInfo*)bindable)->isBound; | |
| case TAG_MPEG4_Viewpoint: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Viewpoint: | |
| #endif | |
| return ((M_Viewpoint*)bindable)->isBound; | |
| case TAG_MPEG4_Fog: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Fog: | |
| #endif | |
| return ((M_Fog*)bindable)->isBound; | |
| default: | |
| return GF_FALSE; | |
| } | |
| } | |
| void Bindable_SetIsBound(GF_Node *bindable, Bool val) | |
| { | |
| Bool has_bind_time = GF_FALSE; | |
| if (!bindable) return; | |
| switch (gf_node_get_tag(bindable)) { | |
| case TAG_MPEG4_Background2D: | |
| if ( ((M_Background2D*)bindable)->isBound == val) return; | |
| ((M_Background2D*)bindable)->isBound = val; | |
| break; | |
| case TAG_MPEG4_Viewport: | |
| if ( ((M_Viewport*)bindable)->isBound == val) return; | |
| ((M_Viewport*)bindable)->isBound = val; | |
| ((M_Viewport*)bindable)->bindTime = gf_node_get_scene_time(bindable); | |
| has_bind_time = GF_TRUE; | |
| break; | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Background: | |
| if ( ((X_Background*)bindable)->isBound == val) return; | |
| ((X_Background*)bindable)->isBound = val; | |
| ((X_Background*)bindable)->bindTime = gf_node_get_scene_time(bindable); | |
| has_bind_time = GF_TRUE; | |
| break; | |
| #endif | |
| case TAG_MPEG4_Background: | |
| if ( ((M_Background*)bindable)->isBound == val) return; | |
| ((M_Background*)bindable)->isBound = val; | |
| break; | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_NavigationInfo: | |
| if ( ((X_NavigationInfo*)bindable)->isBound == val) return; | |
| ((X_NavigationInfo*)bindable)->isBound = val; | |
| ((X_NavigationInfo*)bindable)->bindTime = gf_node_get_scene_time(bindable); | |
| has_bind_time = GF_TRUE; | |
| break; | |
| #endif | |
| case TAG_MPEG4_NavigationInfo: | |
| if ( ((M_NavigationInfo*)bindable)->isBound == val) return; | |
| ((M_NavigationInfo*)bindable)->isBound = val; | |
| break; | |
| case TAG_MPEG4_Viewpoint: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Viewpoint: | |
| #endif | |
| if ( ((M_Viewpoint*)bindable)->isBound == val) return; | |
| ((M_Viewpoint*)bindable)->isBound = val; | |
| ((M_Viewpoint*)bindable)->bindTime = gf_node_get_scene_time(bindable); | |
| has_bind_time = GF_TRUE; | |
| break; | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Fog: | |
| if ( ((X_Fog*)bindable)->isBound == val) return; | |
| ((X_Fog*)bindable)->isBound = val; | |
| ((X_Fog*)bindable)->bindTime = gf_node_get_scene_time(bindable); | |
| has_bind_time = GF_TRUE; | |
| break; | |
| #endif | |
| case TAG_MPEG4_Fog: | |
| if ( ((M_Fog*)bindable)->isBound == val) return; | |
| ((M_Fog*)bindable)->isBound = val; | |
| break; | |
| default: | |
| return; | |
| } | |
| gf_node_event_out_str(bindable, "isBound"); | |
| if (has_bind_time) gf_node_event_out_str(bindable, "bindTime"); | |
| /*force invalidate of the bindable stack's owner*/ | |
| gf_node_dirty_set(bindable, 0, GF_TRUE); | |
| } | |
| Bool Bindable_GetSetBind(GF_Node *bindable) | |
| { | |
| if (!bindable) return GF_FALSE; | |
| switch (gf_node_get_tag(bindable)) { | |
| case TAG_MPEG4_Background2D: | |
| return ((M_Background2D*)bindable)->set_bind; | |
| case TAG_MPEG4_Viewport: | |
| return ((M_Viewport*)bindable)->set_bind; | |
| case TAG_MPEG4_Background: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Background: | |
| #endif | |
| return ((M_Background*)bindable)->set_bind; | |
| case TAG_MPEG4_NavigationInfo: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_NavigationInfo: | |
| #endif | |
| return ((M_NavigationInfo*)bindable)->set_bind; | |
| case TAG_MPEG4_Viewpoint: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Viewpoint: | |
| #endif | |
| return ((M_Viewpoint*)bindable)->set_bind; | |
| case TAG_MPEG4_Fog: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Fog: | |
| #endif | |
| return ((M_Fog*)bindable)->set_bind; | |
| default: | |
| return GF_FALSE; | |
| } | |
| } | |
| void Bindable_SetSetBindEx(GF_Node *bindable, Bool val, GF_List *stack) | |
| { | |
| if (!bindable) return; | |
| switch (gf_node_get_tag(bindable)) { | |
| case TAG_MPEG4_Background2D: | |
| ((M_Background2D*)bindable)->set_bind = val; | |
| ((M_Background2D*)bindable)->on_set_bind(bindable, NULL); | |
| break; | |
| case TAG_MPEG4_Viewport: | |
| ((M_Viewport*)bindable)->set_bind = val; | |
| ((M_Viewport*)bindable)->on_set_bind(bindable, (GF_Route*)stack); | |
| break; | |
| case TAG_MPEG4_Background: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Background: | |
| #endif | |
| ((M_Background*)bindable)->set_bind = val; | |
| ((M_Background*)bindable)->on_set_bind(bindable, NULL); | |
| break; | |
| case TAG_MPEG4_NavigationInfo: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_NavigationInfo: | |
| #endif | |
| ((M_NavigationInfo*)bindable)->set_bind = val; | |
| ((M_NavigationInfo*)bindable)->on_set_bind(bindable, NULL); | |
| break; | |
| case TAG_MPEG4_Viewpoint: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Viewpoint: | |
| #endif | |
| ((M_Viewpoint*)bindable)->set_bind = val; | |
| ((M_Viewpoint*)bindable)->on_set_bind(bindable, NULL); | |
| break; | |
| case TAG_MPEG4_Fog: | |
| #ifndef GPAC_DISABLE_X3D | |
| case TAG_X3D_Fog: | |
| #endif | |
| ((M_Fog*)bindable)->set_bind = val; | |
| ((M_Fog*)bindable)->on_set_bind(bindable, NULL); | |
| break; | |
| default: | |
| return; | |
| } | |
| } | |
| void Bindable_SetSetBind(GF_Node *bindable, Bool val) | |
| { | |
| Bindable_SetSetBindEx(bindable, val, NULL); | |
| } | |
| void Bindable_OnSetBind(GF_Node *bindable, GF_List *stack_list, GF_List *for_stack) | |
| { | |
| u32 i; | |
| Bool on_top, is_bound, set_bind; | |
| GF_Node *node; | |
| GF_List *stack; | |
| set_bind = Bindable_GetSetBind(bindable); | |
| is_bound = Bindable_GetIsBound(bindable); | |
| if (!set_bind && !is_bound) return; | |
| if (set_bind && is_bound) return; | |
| i=0; | |
| while ((stack = (GF_List*)gf_list_enum(stack_list, &i))) { | |
| if (for_stack && (for_stack!=stack)) continue; | |
| on_top = (gf_list_get(stack, 0)==bindable) ? GF_TRUE : GF_FALSE; | |
| if (!set_bind) { | |
| if (is_bound) Bindable_SetIsBound(bindable, GF_FALSE); | |
| if (on_top && (gf_list_count(stack)>1)) { | |
| gf_list_rem(stack, 0); | |
| gf_list_add(stack, bindable); | |
| node = (GF_Node*)gf_list_get(stack, 0); | |
| Bindable_SetIsBound(node, GF_TRUE); | |
| } | |
| } else { | |
| if (!is_bound) Bindable_SetIsBound(bindable, GF_TRUE); | |
| if (!on_top) { | |
| /*push old top one down and unbind*/ | |
| node = (GF_Node*)gf_list_get(stack, 0); | |
| Bindable_SetIsBound(node, GF_FALSE); | |
| /*insert new top*/ | |
| gf_list_del_item(stack, bindable); | |
| gf_list_insert(stack, bindable, 0); | |
| } | |
| } | |
| } | |
| /*force invalidate of the bindable stack's owner*/ | |
| gf_node_dirty_set(bindable, 0, GF_TRUE); | |
| /*and redraw scene*/ | |
| gf_sc_invalidate(gf_sc_get_compositor(bindable), NULL); | |
| } | |
| void BindableStackDelete(GF_List *stack) | |
| { | |
| while (gf_list_count(stack)) { | |
| GF_List *bind_stack_list; | |
| GF_Node *bindable = (GF_Node*)gf_list_get(stack, 0); | |
| gf_list_rem(stack, 0); | |
| bind_stack_list = Bindable_GetStack(bindable); | |
| if (bind_stack_list) { | |
| gf_list_del_item(bind_stack_list, stack); | |
| } | |
| } | |
| gf_list_del(stack); | |
| } | |
| void PreDestroyBindable(GF_Node *bindable, GF_List *stack_list) | |
| { | |
| Bool is_bound = Bindable_GetIsBound(bindable); | |
| Bindable_SetIsBound(bindable, GF_FALSE); | |
| while (gf_list_count(stack_list)) { | |
| GF_List *stack = (GF_List*)gf_list_get(stack_list, 0); | |
| gf_list_rem(stack_list, 0); | |
| gf_list_del_item(stack, bindable); | |
| if (is_bound) { | |
| GF_Node *stack_top = (GF_Node*)gf_list_get(stack, 0); | |
| if (stack_top) Bindable_SetSetBind(stack_top, GF_TRUE); | |
| } | |
| } | |
| } | |
| #endif /*GPAC_DISABLE_VRML && GPAC_DISABLE_COMPOSITOR*/ |