in src/scenegraph/vrml_smjs.c [408:1271]
JSBool gf_sg_js_has_instance(JSContext *c, JSHandleObject obj, JSMutableHandleValue __val, JSBool *vp)
#elif defined(USE_FFDEV_15)
JSBool gf_sg_js_has_instance(JSContext *c, JSHandleObject obj,const jsval *val, JSBool *vp)
#else
JSBool gf_sg_js_has_instance(JSContext *c, JSObject *obj,const jsval *val, JSBool *vp)
#endif
#else
JSBool gf_sg_js_has_instance(JSContext *c, JSObject *obj, jsval val, JSBool *vp)
#endif
{
#ifdef USE_FFDEV_18
jsval *val = __val._;
#endif
*vp = JS_FALSE;
#if (JS_VERSION>=185)
if (val && JSVAL_IS_OBJECT(*val)) {
JSObject *p = JSVAL_TO_OBJECT(*val);
#else
if (JSVAL_IS_OBJECT(val)) {
JSObject *p = JSVAL_TO_OBJECT(val);
#endif
JSClass *js_class = JS_GET_CLASS(c, obj);
if (JS_InstanceOf(c, p, js_class, NULL) ) *vp = JS_TRUE;
}
return JS_TRUE;
}
#ifndef GPAC_DISABLE_SVG
/*SVG tags for script handling*/
#include <gpac/nodes_svg.h>
GF_Node *dom_get_element(JSContext *c, JSObject *obj);
#endif
JSBool gf_sg_script_to_node_field(struct JSContext *c, jsval v, GF_FieldInfo *field, GF_Node *owner, GF_JSField *parent);
jsval gf_sg_script_to_smjs_field(GF_ScriptPriv *priv, GF_FieldInfo *field, GF_Node *parent, Bool force_evaluate);
static void JSScript_NodeModified(GF_SceneGraph *sg, GF_Node *node, GF_FieldInfo *info, GF_Node *script);
Bool JSScriptFromFile(GF_Node *node, const char *opt_file, Bool no_complain, jsval *rval);
void gf_sg_js_call_gc(JSContext *c)
{
gf_sg_lock_javascript(c, 1);
#ifdef USE_FFDEV_14
JS_GC(js_rt->js_runtime);
#else
JS_GC(c);
#endif
gf_sg_lock_javascript(c, 0);
}
void do_js_gc(JSContext *c, GF_Node *node)
{
#ifdef FORCE_GC
node->sgprivate->scenegraph->trigger_gc = GF_TRUE;
#endif
if (node->sgprivate->scenegraph->trigger_gc) {
node->sgprivate->scenegraph->trigger_gc = GF_FALSE;
gf_sg_js_call_gc(c);
}
}
#ifndef GPAC_DISABLE_VRML
/*MPEG4 & X3D tags (for node tables & script handling)*/
#include <gpac/nodes_mpeg4.h>
#include <gpac/nodes_x3d.h>
void SFColor_fromHSV(SFColor *col)
{
Fixed f, q, t, p, hue, sat, val;
u32 i;
hue = col->red;
sat = col->green;
val = col->blue;
if (sat==0) {
col->red = col->green = col->blue = val;
return;
}
if (hue == FIX_ONE) hue = 0;
else hue *= 6;
i = FIX2INT( gf_floor(hue) );
f = hue-i;
p = gf_mulfix(val, FIX_ONE - sat);
q = gf_mulfix(val, FIX_ONE - gf_mulfix(sat,f));
t = gf_mulfix(val, FIX_ONE - gf_mulfix(sat, FIX_ONE - f));
switch (i) {
case 0:
col->red = val;
col->green = t;
col->blue = p;
break;
case 1:
col->red = q;
col->green = val;
col->blue = p;
break;
case 2:
col->red = p;
col->green = val;
col->blue = t;
break;
case 3:
col->red = p;
col->green = q;
col->blue = val;
break;
case 4:
col->red = t;
col->green = p;
col->blue = val;
break;
case 5:
col->red = val;
col->green = p;
col->blue = q;
break;
}
}
void SFColor_toHSV(SFColor *col)
{
Fixed h, s;
Fixed _max = MAX(col->red, MAX(col->green, col->blue));
Fixed _min = MIN(col->red, MAX(col->green, col->blue));
s = (_max == 0) ? 0 : gf_divfix(_max - _min, _max);
if (s != 0) {
Fixed rl = gf_divfix(_max - col->red, _max - _min);
Fixed gl = gf_divfix(_max - col->green, _max - _min);
Fixed bl = gf_divfix(_max - col->blue, _max - _min);
if (_max == col->red) {
if (_min == col->green) h = 60*(5+bl);
else h = 60*(1-gl);
} else if (_max == col->green) {
if (_min == col->blue) h = 60*(1+rl);
else h = 60*(3-bl);
} else {
if (_min == col->red) h = 60*(3+gl);
else h = 60*(5-rl);
}
} else {
h = 0;
}
col->red = h;
col->green = s;
col->blue = _max;
}
static GFINLINE GF_JSField *NewJSField(JSContext *c)
{
GF_JSField *ptr;
GF_SAFEALLOC(ptr, GF_JSField);
ptr->js_ctx = c;
return ptr;
}
static GFINLINE M_Script *JS_GetScript(JSContext *c)
{
return (M_Script *) JS_GetContextPrivate(c);
}
static GFINLINE GF_ScriptPriv *JS_GetScriptStack(JSContext *c)
{
M_Script *script = (M_Script *) JS_GetContextPrivate(c);
return script->sgprivate->UserPrivate;
}
static void script_error(JSContext *c, const char *msg, JSErrorReport *jserr)
{
if (jserr->linebuf) {
GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JavaScript] Error: %s - line %d (%s) - file %s\n", msg, jserr->lineno, jserr->linebuf, jserr->filename));
} else if (jserr->filename) {
GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JavaScript] Error: %s - line %d - file %s\n", msg, jserr->lineno, jserr->filename));
} else {
GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JavaScript] Error: %s - line %d\n", msg, jserr->lineno));
}
}
static JSBool SMJS_FUNCTION(JSPrint)
{
SMJS_ARGS
if (!argc) return JS_FALSE;
if (JSVAL_IS_STRING(argv[0])) {
char *str = SMJS_CHARS(c, argv[0]);
_ScriptMessage(c, str);
SMJS_FREE(c, str);
}
if (JSVAL_IS_INT(argv[0]) && (argc>1) && JSVAL_IS_STRING(argv[1]) ) {
u32 level = JSVAL_TO_INT(argv[0]);
char *str = SMJS_CHARS(c, argv[1]);
if (level > GF_LOG_DEBUG) level = GF_LOG_DEBUG;
if (str[0] == '[') {
GF_LOG(level, GF_LOG_CONSOLE, ("%s\n", str));
} else {
GF_LOG(level, GF_LOG_CONSOLE, ("[JS] %s\n", str));
}
SMJS_FREE(c, str);
}
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(getName)
{
JSString *s = JS_NewStringCopyZ(c, "GPAC RichMediaEngine");
if (!s) return JS_FALSE;
SMJS_SET_RVAL( STRING_TO_JSVAL(s) );
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(getVersion)
{
JSString *s = JS_NewStringCopyZ(c, GPAC_FULL_VERSION);
if (!s) return JS_FALSE;
SMJS_SET_RVAL( STRING_TO_JSVAL(s) );
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(getCurrentSpeed)
{
GF_JSAPIParam par;
GF_Node *node = JS_GetContextPrivate(c);
par.time = 0;
ScriptAction(c, NULL, GF_JSAPI_OP_GET_SPEED, node->sgprivate->scenegraph->RootNode, &par);
SMJS_SET_RVAL( JS_MAKE_DOUBLE( c, par.time) );
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(getCurrentFrameRate)
{
GF_JSAPIParam par;
GF_Node *node = JS_GetContextPrivate(c);
par.time = 0;
ScriptAction(c, NULL, GF_JSAPI_OP_GET_FPS, node->sgprivate->scenegraph->RootNode, &par);
SMJS_SET_RVAL( JS_MAKE_DOUBLE( c, par.time) );
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(getWorldURL)
{
GF_JSAPIParam par;
GF_Node *node = JS_GetContextPrivate(c);
par.uri.url = NULL;
par.uri.nb_params = 0;
if (ScriptAction(c, NULL, GF_JSAPI_OP_RESOLVE_URI, node->sgprivate->scenegraph->RootNode, &par)) {
JSString *s = JS_NewStringCopyZ(c, par.uri.url);
if (!s) return JS_FALSE;
SMJS_SET_RVAL( STRING_TO_JSVAL(s) );
gf_free(par.uri.url);
return JS_TRUE;
}
return JS_FALSE;
}
static JSObject *node_get_binding(GF_ScriptPriv *priv, GF_Node *node, Bool is_constructor)
{
JSObject *obj;
GF_JSField *field;
if (node->sgprivate->interact && node->sgprivate->interact->js_binding && node->sgprivate->interact->js_binding->node) {
field = node->sgprivate->interact->js_binding->node;
if (!field->is_rooted) {
gf_js_add_root(priv->js_ctx, &field->obj, GF_JSGC_OBJECT);
field->is_rooted=1;
}
return field->obj;
}
field = NewJSField(priv->js_ctx);
field->field.fieldType = GF_SG_VRML_SFNODE;
field->node = node;
field->field.far_ptr = &field->node;
node->sgprivate->flags |= GF_NODE_HAS_BINDING;
gf_node_register(node, NULL);
obj = JS_NewObject(priv->js_ctx, &js_rt->SFNodeClass._class, 0, 0);
SMJS_SET_PRIVATE(priv->js_ctx, obj, field);
field->obj = obj;
gf_list_add(priv->js_cache, obj);
/*remember the object*/
if (!node->sgprivate->interact) GF_SAFEALLOC(node->sgprivate->interact, struct _node_interactive_ext);
if (!node->sgprivate->interact->js_binding) {
GF_SAFEALLOC(node->sgprivate->interact->js_binding, struct _node_js_binding);
node->sgprivate->interact->js_binding->fields = gf_list_new();
}
node->sgprivate->flags |= GF_NODE_HAS_BINDING;
node->sgprivate->interact->js_binding->node = field;
if (!is_constructor) {
field->is_rooted = 1;
gf_js_add_root(priv->js_ctx, &field->obj, GF_JSGC_OBJECT);
}
return obj;
}
static JSBool SMJS_FUNCTION(getScript)
{
GF_ScriptPriv *priv = JS_GetScriptStack(c);
GF_Node *node = JS_GetContextPrivate(c);
JSObject *an_obj = node_get_binding(priv, node, 0);
if (an_obj) SMJS_SET_RVAL( OBJECT_TO_JSVAL(an_obj) );
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(loadScript)
{
Bool no_complain = 0;
char *url;
GF_Node *node = JS_GetContextPrivate(c);
SMJS_ARGS
jsval aval;
if (!argc || !JSVAL_IS_STRING(argv[0])) return JS_TRUE;
if ((argc>1) && JSVAL_IS_BOOLEAN(argv[1])) no_complain = (JSVAL_TO_BOOLEAN(argv[1])==JS_TRUE) ? 1 : 0;
url = SMJS_CHARS(c, argv[0]);
if (url) {
JSScriptFromFile(node, url, no_complain, &aval);
SMJS_SET_RVAL(aval);
}
SMJS_FREE(c, url);
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(getProto)
{
JSObject *an_obj;
GF_ScriptPriv *priv = JS_GetScriptStack(c);
GF_Node *node = JS_GetContextPrivate(c);
SMJS_SET_RVAL( JSVAL_NULL);
if (!node->sgprivate->scenegraph->pOwningProto) {
return JS_TRUE;
}
node = (GF_Node *) node->sgprivate->scenegraph->pOwningProto;
an_obj = node_get_binding(priv, node, 0);
if (an_obj) SMJS_SET_RVAL( OBJECT_TO_JSVAL(an_obj) );
return JS_TRUE;
}
#ifndef GPAC_DISABLE_SVG
char *js_get_utf8(jsval val);
jsval dom_element_construct(JSContext *c, GF_Node *n);
#endif
static JSBool SMJS_FUNCTION(vrml_parse_xml)
{
#ifndef GPAC_DISABLE_SVG
GF_SceneGraph *sg;
GF_Node *node;
char *str;
GF_Node *gf_sm_load_svg_from_string(GF_SceneGraph *sg, char *svg_str);
SMJS_ARGS
str = js_get_utf8(argv[0]);
if (!str) return JS_TRUE;
node = JS_GetContextPrivate(c);
sg = node->sgprivate->scenegraph;
node = gf_sm_load_svg_from_string(sg, str);
gf_free(str);
SMJS_SET_RVAL( dom_element_construct(c, node) );
#endif
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(getElementById)
{
GF_Node *elt;
JSObject *an_obj;
char *name = NULL;
u32 ID = 0;
GF_ScriptPriv *priv = JS_GetScriptStack(c);
GF_Node *sc = JS_GetContextPrivate(c);
SMJS_ARGS
if (JSVAL_IS_STRING(argv[0])) name = SMJS_CHARS(c, argv[0]);
else if (JSVAL_IS_INT(argv[0])) ID = JSVAL_TO_INT(argv[0]);
if (!ID && !name) return JS_FALSE;
elt = NULL;
if (ID) elt = gf_sg_find_node(sc->sgprivate->scenegraph, ID);
else elt = gf_sg_find_node_by_name(sc->sgprivate->scenegraph, name);
SMJS_FREE(c, name);
if (!elt) return JS_TRUE;
an_obj = node_get_binding(priv, elt, 0);
if (an_obj) SMJS_SET_RVAL( OBJECT_TO_JSVAL(an_obj) );
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(replaceWorld)
{
return JS_TRUE;
}
static void on_route_to_object(GF_Node *node, GF_Route *_r)
{
jsval argv[2], rval;
Double time;
GF_FieldInfo t_info;
GF_ScriptPriv *priv;
JSObject *obj;
GF_RouteToScript *r = (GF_RouteToScript *)_r;
if (!node) return;
priv = gf_node_get_private(node);
if (!priv) return;
if (!r->FromNode) {
if (r->obj) {
// gf_js_remove_root(priv->js_ctx, &r->obj, GF_JSGC_OBJECT);
r->obj=NULL;
}
if ( ! JSVAL_IS_VOID(r->fun)) {
// gf_js_remove_root(priv->js_ctx, &r->fun, GF_JSGC_OBJECT);
r->fun=JSVAL_NULL;
}
return;
}
obj = (JSObject *) r->obj;
if (!obj) obj = priv->js_obj;
memset(&t_info, 0, sizeof(GF_FieldInfo));
time = gf_node_get_scene_time(node);
t_info.far_ptr = &time;
t_info.fieldType = GF_SG_VRML_SFTIME;
t_info.fieldIndex = -1;
t_info.name = "timestamp";
gf_sg_lock_javascript(priv->js_ctx, 1);
argv[1] = gf_sg_script_to_smjs_field(priv, &t_info, node, 1);
argv[0] = gf_sg_script_to_smjs_field(priv, &r->FromField, r->FromNode, 1);
/*protect args*/
if (JSVAL_IS_GCTHING(argv[0])) gf_js_add_root(priv->js_ctx, &argv[0], GF_JSGC_VAL);
if (JSVAL_IS_GCTHING(argv[1])) gf_js_add_root(priv->js_ctx, &argv[1], GF_JSGC_VAL);
JS_CallFunctionValue(priv->js_ctx, obj, (jsval) r->fun, 2, argv, &rval);
/*release args*/
if (JSVAL_IS_GCTHING(argv[0])) gf_js_remove_root(priv->js_ctx, &argv[0], GF_JSGC_VAL);
if (JSVAL_IS_GCTHING(argv[1])) gf_js_remove_root(priv->js_ctx, &argv[1], GF_JSGC_VAL);
/*check any pending exception if outer-most event*/
if ( (JS_IsRunning(priv->js_ctx)==JS_FALSE) && JS_IsExceptionPending(priv->js_ctx)) {
JS_ReportPendingException(priv->js_ctx);
JS_ClearPendingException(priv->js_ctx);
}
gf_sg_lock_javascript(priv->js_ctx, 0);
do_js_gc(priv->js_ctx, node);
}
static JSBool SMJS_FUNCTION(addRoute)
{
GF_JSField *ptr;
GF_Node *n1, *n2;
char *f1, *f2;
GF_FieldInfo info;
u32 f_id1, f_id2;
GF_Err e;
SMJS_ARGS
if (argc!=4) return JS_FALSE;
if (!JSVAL_IS_OBJECT(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE;
ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0]));
assert(ptr->field.fieldType==GF_SG_VRML_SFNODE);
n1 = * ((GF_Node **)ptr->field.far_ptr);
if (!n1) return JS_FALSE;
n2 = NULL;
if (!JSVAL_IS_STRING(argv[1])) return JS_FALSE;
f1 = SMJS_CHARS(c, argv[1]);
if (!f1) return JS_FALSE;
if (!strnicmp(f1, "_field", 6)) {
f_id1 = atoi(f1+6);
e = gf_node_get_field(n1, f_id1, &info);
} else {
e = gf_node_get_field_by_name(n1, f1, &info);
f_id1 = info.fieldIndex;
}
SMJS_FREE(c, f1);
if (e != GF_OK) return JS_FALSE;
if (!JSVAL_IS_OBJECT(argv[2])) return JS_FALSE;
/*regular route*/
if (GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[2]), &js_rt->SFNodeClass, NULL) && JSVAL_IS_STRING(argv[3]) ) {
GF_Route *r;
ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[2]));
assert(ptr->field.fieldType==GF_SG_VRML_SFNODE);
n2 = * ((GF_Node **)ptr->field.far_ptr);
if (!n2) return JS_FALSE;
f2 = SMJS_CHARS(c, argv[3]);
if (!f2) return JS_FALSE;
if (!strnicmp(f2, "_field", 6)) {
f_id2 = atoi(f2+6);
e = gf_node_get_field(n2, f_id2, &info);
} else {
if ((n2->sgprivate->tag==TAG_MPEG4_Script)
#ifndef GPAC_DISABLE_X3D
|| (n2->sgprivate->tag==TAG_X3D_Script)
#endif
) {
GF_FieldInfo src = info;
if (gf_node_get_field_by_name(n2, f2, &info) != GF_OK) {
gf_sg_script_field_new(n2, GF_SG_SCRIPT_TYPE_EVENT_IN, src.fieldType, f2);
}
}
e = gf_node_get_field_by_name(n2, f2, &info);
f_id2 = info.fieldIndex;
}
SMJS_FREE(c, f2);
if (e != GF_OK) return JS_FALSE;
r = gf_sg_route_new(n1->sgprivate->scenegraph, n1, f_id1, n2, f_id2);
if (!r) return JS_FALSE;
}
/*route to object*/
else {
u32 i = 0;
const char *fun_name;
GF_RouteToScript *r = NULL;
if (!JSVAL_IS_OBJECT(argv[3]) || !JS_ObjectIsFunction(c, JSVAL_TO_OBJECT(argv[3])) ) return JS_FALSE;
fun_name = JS_GetFunctionName( JS_ValueToFunction(c, argv[3] ) );
if (fun_name && n1->sgprivate->interact && n1->sgprivate->interact->routes ) {
while ( (r = (GF_RouteToScript*)gf_list_enum(n1->sgprivate->interact->routes, &i) )) {
if ( (r->FromNode == n1)
&& (r->FromField.fieldIndex == f_id1)
&& (r->ToNode == (GF_Node*)JS_GetScript(c))
&& !stricmp(r->ToField.name, fun_name)
)
break;
}
}
if ( !r ) {
GF_SAFEALLOC(r, GF_RouteToScript)
if (!r) return JS_FALSE;
r->FromNode = n1;
r->FromField.fieldIndex = f_id1;
gf_node_get_field(r->FromNode, f_id1, &r->FromField);
r->ToNode = (GF_Node*)JS_GetScript(c);
r->ToField.fieldType = GF_SG_VRML_SCRIPT_FUNCTION;
r->ToField.on_event_in = on_route_to_object;
r->ToField.eventType = GF_SG_EVENT_IN;
r->ToField.far_ptr = NULL;
r->ToField.name = fun_name;
r->obj = JSVAL_TO_OBJECT( argv[2] ) ;
// gf_js_add_root(c, & r->obj, GF_JSGC_OBJECT);
r->fun = argv[3];
// gf_js_add_root(c, &r->fun, GF_JSGC_OBJECT);
r->is_setup = 1;
r->graph = n1->sgprivate->scenegraph;
if (!n1->sgprivate->interact) GF_SAFEALLOC(n1->sgprivate->interact, struct _node_interactive_ext);
if (!n1->sgprivate->interact->routes) n1->sgprivate->interact->routes = gf_list_new();
gf_list_add(n1->sgprivate->interact->routes, r);
gf_list_add(n1->sgprivate->scenegraph->Routes, r);
}
}
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(deleteRoute)
{
GF_JSField *ptr;
GF_Node *n1, *n2;
char *f1, *f2;
GF_FieldInfo info;
GF_Route *r;
GF_Err e;
u32 f_id1, f_id2, i;
SMJS_ARGS
if (argc!=4) return JS_FALSE;
if (!JSVAL_IS_OBJECT(argv[0]) || JSVAL_IS_NULL(argv[0]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE;
if (JSVAL_IS_STRING(argv[1]) && JSVAL_IS_NULL(argv[2]) && JSVAL_IS_NULL(argv[3])) {
ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0]));
assert(ptr->field.fieldType==GF_SG_VRML_SFNODE);
n1 = * ((GF_Node **)ptr->field.far_ptr);
f1 = SMJS_CHARS(c, argv[1]);
if (!strcmp(f1, "ALL")) {
while (n1->sgprivate->interact && n1->sgprivate->interact->routes && gf_list_count(n1->sgprivate->interact->routes) ) {
r = gf_list_get(n1->sgprivate->interact->routes, 0);
gf_sg_route_del(r);
}
}
SMJS_FREE(c, f1);
return JS_TRUE;
}
if (!JSVAL_IS_OBJECT(argv[2]) || !GF_JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[2]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE;
if (!JSVAL_IS_STRING(argv[1]) || !JSVAL_IS_STRING(argv[3])) return JS_FALSE;
ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[0]));
assert(ptr->field.fieldType==GF_SG_VRML_SFNODE);
n1 = * ((GF_Node **)ptr->field.far_ptr);
ptr = (GF_JSField *) SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(argv[2]));
assert(ptr->field.fieldType==GF_SG_VRML_SFNODE);
n2 = * ((GF_Node **)ptr->field.far_ptr);
if (!n1 || !n2) return JS_FALSE;
if (!n1->sgprivate->interact) return JS_TRUE;
f1 = SMJS_CHARS(c, argv[1]);
f2 = SMJS_CHARS(c, argv[3]);
if (!f1 || !f2) {
SMJS_FREE(c, f1);
SMJS_FREE(c, f2);
return JS_FALSE;
}
if (!strnicmp(f1, "_field", 6)) {
f_id1 = atoi(f1+6);
e = gf_node_get_field(n1, f_id1, &info);
} else {
e = gf_node_get_field_by_name(n1, f1, &info);
f_id1 = info.fieldIndex;
}
SMJS_FREE(c, f1);
if (e != GF_OK) return JS_FALSE;
if (!strnicmp(f2, "_field", 6)) {
f_id2 = atoi(f2+6);
e = gf_node_get_field(n2, f_id2, &info);
} else {
e = gf_node_get_field_by_name(n2, f2, &info);
f_id2 = info.fieldIndex;
}
SMJS_FREE(c, f2);
if (e != GF_OK) return JS_FALSE;
i=0;
while ((r = gf_list_enum(n1->sgprivate->interact->routes, &i))) {
if (r->FromField.fieldIndex != f_id1) continue;
if (r->ToNode != n2) continue;
if (r->ToField.fieldIndex != f_id2) continue;
gf_sg_route_del(r);
return JS_TRUE;
}
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(loadURL)
{
u32 i;
GF_JSAPIParam par;
jsval item;
jsuint len;
JSObject *p;
GF_JSField *f;
SMJS_ARGS
M_Script *script = (M_Script *) JS_GetContextPrivate(c);
if (argc < 1) return JS_FALSE;
if (JSVAL_IS_STRING(argv[0])) {
Bool res;
par.uri.url = SMJS_CHARS(c, argv[0]);
/*TODO add support for params*/
par.uri.nb_params = 0;
res = ScriptAction(c, NULL, GF_JSAPI_OP_LOAD_URL, (GF_Node *)script, &par);
SMJS_FREE(c, par.uri.url);
return res ? JS_TRUE : JS_FALSE;
}
if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE;
JS_ValueToObject(c, argv[0], &p);
f = (GF_JSField *) SMJS_GET_PRIVATE(c, p);
if (!f || !f->js_list) return JS_FALSE;
JS_GetArrayLength(c, f->js_list, &len);
for (i=0; i<len; i++) {
JS_GetElement(c, f->js_list, (jsint) i, &item);
if (JSVAL_IS_STRING(item)) {
Bool res;
par.uri.url = SMJS_CHARS(c, item);
/*TODO add support for params*/
par.uri.nb_params = 0;
res = ScriptAction(c, NULL, GF_JSAPI_OP_LOAD_URL, (GF_Node*)script, &par);
SMJS_FREE(c, par.uri.url);
if (res) return JS_TRUE;
}
}
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(setDescription)
{
GF_JSAPIParam par;
GF_Node *node = JS_GetContextPrivate(c);
SMJS_ARGS
if (!argc || !JSVAL_IS_STRING(argv[0])) return JS_FALSE;
par.uri.url = SMJS_CHARS(c, argv[0]);
ScriptAction(c, NULL, GF_JSAPI_OP_SET_TITLE, node->sgprivate->scenegraph->RootNode, &par);
SMJS_FREE(c, par.uri.url);
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(createVrmlFromString)
{
#ifndef GPAC_DISABLE_LOADER_BT
GF_ScriptPriv *priv;
GF_FieldInfo field;
/*BT/VRML from string*/
GF_List *gf_sm_load_bt_from_string(GF_SceneGraph *in_scene, char *node_str, Bool force_wrl);
char *str;
GF_List *nlist;
SMJS_ARGS
GF_Node *sc_node = JS_GetContextPrivate(c);
if (argc < 1) return JS_FALSE;
if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE;
str = SMJS_CHARS(c, argv[0]);
nlist = gf_sm_load_bt_from_string(sc_node->sgprivate->scenegraph, str, 1);
SMJS_FREE(c, str);
if (!nlist) return JS_FALSE;
priv = JS_GetScriptStack(c);
memset(&field, 0, sizeof(GF_FieldInfo));
field.fieldType = GF_SG_VRML_MFNODE;
field.far_ptr = &nlist;
SMJS_SET_RVAL( gf_sg_script_to_smjs_field(priv, &field, NULL, 0) );
/*don't forget to unregister all this stuff*/
while (gf_list_count(nlist)) {
GF_Node *n = gf_list_get(nlist, 0);
gf_list_rem(nlist, 0);
gf_node_unregister(n, NULL);
}
gf_list_del(nlist);
return JS_TRUE;
#else
return JS_FALSE;
#endif
}
void gf_node_event_out_proto(GF_Node *node, u32 FieldIndex);
void Script_FieldChanged(JSContext *c, GF_Node *parent, GF_JSField *parent_owner, GF_FieldInfo *field)
{
GF_ScriptPriv *priv;
u32 script_field;
u32 i;
GF_ScriptField *sf;
if (!parent) {
parent = parent_owner->owner;
field = &parent_owner->field;
}
if (!parent) return;
script_field = 0;
if ((parent->sgprivate->tag == TAG_MPEG4_Script)
#ifndef GPAC_DISABLE_X3D
|| (parent->sgprivate->tag == TAG_X3D_Script)
#endif
) {
script_field = 1;
if ( (GF_Node *) JS_GetContextPrivate(c) == parent) script_field = 2;
}
if (script_field!=2) {
if (field->on_event_in) field->on_event_in(parent, NULL);
else if (script_field && (field->eventType==GF_SG_EVENT_IN) ) {
gf_sg_script_event_in(parent, field);
gf_node_changed_internal(parent, field, 0);
return;
}
/*field has changed, set routes...*/
if (parent->sgprivate->tag == TAG_ProtoNode) {
GF_ProtoInstance *inst = (GF_ProtoInstance *)parent;
gf_sg_proto_propagate_event(parent, field->fieldIndex, (GF_Node*)JS_GetScript(c));
/* Node exposedField can also be routed to another field */
gf_node_event_out_proto(parent, field->fieldIndex);
//hardcoded protos be implemented in ways not inspecting the node_dirty propagation scheme (eg defining an SFNode in their interface, not linked with the graph).
//in this case handle the node as a regular one
if (inst->flags & GF_SG_PROTO_HARDCODED) {
gf_node_changed_internal(parent, field, 0);
}
} else {
gf_node_event_out(parent, field->fieldIndex);
gf_node_changed_internal(parent, field, 0);
}
return;
}
/*otherwise mark field if eventOut*/
if (parent_owner || parent) {
priv = parent ? parent->sgprivate->UserPrivate : parent_owner->owner->sgprivate->UserPrivate;
i=0;
while ((sf = gf_list_enum(priv->fields, &i))) {
if (sf->ALL_index == field->fieldIndex) {
/*queue eventOut*/
if (sf->eventType == GF_SG_EVENT_OUT) {
sf->activate_event_out = 1;
}
}
}
}
}
SMJS_FUNC_PROP_SET( gf_sg_script_eventout_set_prop)
u32 i;
char *eventName;
GF_ScriptPriv *script;
GF_Node *n;
GF_ScriptField *sf;
GF_FieldInfo info;
jsval idval;
JSString *str;
JS_IdToValue(c, id, &idval);
if (! SMJS_ID_IS_STRING(id)) return JS_FALSE;
str = SMJS_ID_TO_STRING(id);
if (!str) return JS_FALSE;
/*avoids gcc warning*/
if (!obj) obj=NULL;
script = JS_GetScriptStack(c);
if (!script) return JS_FALSE;
n = (GF_Node *) JS_GetScript(c);
eventName = SMJS_CHARS_FROM_STRING(c, str);
i=0;
while ((sf = gf_list_enum(script->fields, &i))) {
if (!stricmp(sf->name, eventName)) {
gf_node_get_field(n, sf->ALL_index, &info);
gf_sg_script_to_node_field(c, *vp, &info, n, NULL);
sf->activate_event_out = 1;
SMJS_FREE(c, eventName);
return JS_TRUE;
}
}
SMJS_FREE(c, eventName);
return JS_FALSE;
}