📄 vrml_smjs.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / Scene Graph 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 <gpac/internal/scenegraph_dev.h>/*MPEG4 & X3D tags (for node tables & script handling)*/#include <gpac/nodes_mpeg4.h>#include <gpac/nodes_x3d.h>#ifdef GPAC_HAS_SPIDERMONKEY#ifndef GPAC_DISABLE_SVG/*SVG tags for script handling*/#include <gpac/nodes_svg_da.h>#endif#define _ScriptMessage(_c, _e, _msg) { \ GF_Node *_n = (GF_Node *) JS_GetContextPrivate(_c); \ if (_n->sgprivate->scenegraph->script_action) {\ GF_JSAPIParam par; \ par.info.e = (_e); \ par.info.msg = (_msg); \ _n->sgprivate->scenegraph->script_action(_n->sgprivate->scenegraph->script_action_cbck, GF_JSAPI_OP_MESSAGE, NULL, &par);\ } \ }static GFINLINE Bool ScriptAction(JSContext *c, GF_SceneGraph *scene, u32 type, GF_Node *node, GF_JSAPIParam *param){ if (!scene) { GF_Node *n = (GF_Node *) JS_GetContextPrivate(c); scene = n->sgprivate->scenegraph; } if (scene->script_action) return scene->script_action(scene->script_action_cbck, type, node, param); return 0;}#define GF_SETUP_JS(the_class, cname, flag, addp, delp, getp, setp, enump, resp, conv, fin) \ memset(&the_class, 0, sizeof(the_class)); \ the_class.name = cname; \ the_class.flags = flag; \ the_class.addProperty = addp; \ the_class.delProperty = delp; \ the_class.getProperty = getp; \ the_class.setProperty = setp; \ the_class.enumerate = enump; \ the_class.resolve = resp; \ the_class.convert = conv; \ the_class.finalize = fin; typedef struct{ JSRuntime *js_runtime; u32 nb_inst; JSClass globalClass; JSClass browserClass; JSClass SFNodeClass; JSClass SFVec2fClass; JSClass SFVec3fClass; JSClass SFRotationClass; JSClass SFColorClass; JSClass SFImageClass; JSClass MFInt32Class; JSClass MFBoolClass; JSClass MFFloatClass; JSClass MFTimeClass; JSClass MFVec2fClass; JSClass MFVec3fClass; JSClass MFRotationClass; JSClass MFColorClass; JSClass MFStringClass; JSClass MFUrlClass; JSClass MFNodeClass;} GF_JSRuntime;static GF_JSRuntime *js_rt = NULL;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(){ GF_JSField *ptr; GF_SAFEALLOC(ptr, GF_JSField) 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){// GF_JSInterface *ifce = JS_GetInterface(c);// if (ifce) ifce->ScriptMessage(ifce->callback, GF_SCRIPT_ERROR, msg); GF_LOG(GF_LOG_ERROR, GF_LOG_SCRIPT, ("[JavaScript] Error: %s", msg));}static JSBool JSPrint(JSContext *c, JSObject *p, uintN argc, jsval *argv, jsval *rval){ u32 i; char buf[5000]; strcpy(buf, ""); for (i = 0; i < argc; i++) { JSString *str = JS_ValueToString(c, argv[i]); if (!str) return JS_FALSE; if (i) strcat(buf, " "); strcat(buf, JS_GetStringBytes(str)); } _ScriptMessage(c, GF_SCRIPT_INFO, buf); return JS_TRUE;}static JSBool getName(JSContext *c, JSObject *obj, uintN n, jsval *v, jsval *rval){ JSString *s = JS_NewStringCopyZ(c, "GPAC Browser"); if (!s) return JS_FALSE; *rval = STRING_TO_JSVAL(s); return JS_TRUE;}static JSBool getVersion(JSContext*c, JSObject*obj, uintN n, jsval *v, jsval *rval){ JSString *s = JS_NewStringCopyZ(c, GPAC_VERSION); if (!s) return JS_FALSE; *rval = STRING_TO_JSVAL(s); return JS_TRUE;}static JSBool getCurrentSpeed(JSContext *c, JSObject *o, uintN n, jsval *v, jsval *rval){ *rval = DOUBLE_TO_JSVAL(JS_NewDouble( c, 30.0 )); return JS_TRUE;}static JSBool getCurrentFrameRate(JSContext *c, JSObject*o, uintN n, jsval *v, jsval*rval){ *rval = DOUBLE_TO_JSVAL(JS_NewDouble(c, 30.0 )); return JS_TRUE;}static JSBool getWorldURL(JSContext*c, JSObject*obj, uintN n, jsval *v, jsval *rval){ GF_JSAPIParam par; GF_Node *node = JS_GetContextPrivate(c); if (ScriptAction(c, NULL, GF_JSAPI_OP_GET_SCENE_URI, node->sgprivate->scenegraph->RootNode, &par)) { JSString *s = JS_NewStringCopyZ(c, par.uri.url); if (!s) return JS_FALSE; *rval = STRING_TO_JSVAL(s); return JS_TRUE; } return JS_FALSE;}static JSBool replaceWorld(JSContext*c, JSObject*o, uintN n, jsval *v, jsval *rv){ return JS_TRUE;}static JSBool addRoute(JSContext*c, JSObject*o, uintN argc, jsval *argv, jsval *rv){ GF_JSField *ptr; GF_Node *n1, *n2; char *f1, *f2; GF_FieldInfo info; GF_Route *r; u32 f_id1, f_id2; if (argc!=4) return JS_FALSE; if (!JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; if (!JSVAL_IS_OBJECT(argv[2]) || !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 *) JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0])); assert(ptr->field.fieldType==GF_SG_VRML_SFNODE); n1 = * ((GF_Node **)ptr->field.far_ptr); ptr = (GF_JSField *) JS_GetPrivate(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; f1 = JS_GetStringBytes(JSVAL_TO_STRING(argv[1])); f2 = JS_GetStringBytes(JSVAL_TO_STRING(argv[3])); if (!f1 || !f2) return JS_FALSE; if (!strnicmp(f1, "_field", 6)) { f_id1 = atoi(f1+6); if (gf_node_get_field(n1, f_id1, &info) != GF_OK) return JS_FALSE; } else { if (gf_node_get_field_by_name(n1, f1, &info) != GF_OK) return JS_FALSE; f_id1 = info.fieldIndex; } if (!strnicmp(f2, "_field", 6)) { f_id2 = atoi(f2+6); if (gf_node_get_field(n2, f_id2, &info) != GF_OK) return JS_FALSE; } else { if (gf_node_get_field_by_name(n2, f2, &info) != GF_OK) return JS_FALSE; f_id2 = info.fieldIndex; } r = gf_sg_route_new(n1->sgprivate->scenegraph, n1, f_id1, n2, f_id2); if (!r) return JS_FALSE; return JS_TRUE;}static JSBool deleteRoute(JSContext*c, JSObject*o, uintN argc, jsval *argv, jsval *rv){ GF_JSField *ptr; GF_Node *n1, *n2; char *f1, *f2; GF_FieldInfo info; GF_Route *r; u32 f_id1, f_id2, i; if (argc!=4) return JS_FALSE; if (!JSVAL_IS_OBJECT(argv[0]) || !JS_InstanceOf(c, JSVAL_TO_OBJECT(argv[0]), &js_rt->SFNodeClass, NULL) ) return JS_FALSE; if (!JSVAL_IS_OBJECT(argv[2]) || !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 *) JS_GetPrivate(c, JSVAL_TO_OBJECT(argv[0])); assert(ptr->field.fieldType==GF_SG_VRML_SFNODE); n1 = * ((GF_Node **)ptr->field.far_ptr); ptr = (GF_JSField *) JS_GetPrivate(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 = JS_GetStringBytes(JSVAL_TO_STRING(argv[1])); f2 = JS_GetStringBytes(JSVAL_TO_STRING(argv[3])); if (!f1 || !f2) return JS_FALSE; if (!strnicmp(f1, "_field", 6)) { f_id1 = atoi(f1+6); if (gf_node_get_field(n1, f_id1, &info) != GF_OK) return JS_FALSE; } else { if (gf_node_get_field_by_name(n1, f1, &info) != GF_OK) return JS_FALSE; f_id1 = info.fieldIndex; } if (!strnicmp(f2, "_field", 6)) { f_id2 = atoi(f2+6); if (gf_node_get_field(n2, f_id2, &info) != GF_OK) return JS_FALSE; } else { if (gf_node_get_field_by_name(n2, f2, &info) != GF_OK) return JS_FALSE; f_id2 = info.fieldIndex; } i=0; while ((r = gf_list_enum(n1->sgprivate->interact->events, &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 loadURL(JSContext*c, JSObject*obj, uintN argc, jsval *argv, jsval *rval){ u32 i; GF_JSAPIParam par; jsval item; jsuint len; JSObject *p; GF_JSField *f; M_Script *script = (M_Script *) JS_GetContextPrivate(c); if (argc < 1) return JS_FALSE; if (JSVAL_IS_STRING(argv[0])) { JSString *str = JSVAL_TO_STRING(argv[0]); par.uri.url = JS_GetStringBytes(str); /*TODO add support for params*/ par.uri.nb_params = 0; if (ScriptAction(c, NULL, GF_JSAPI_OP_LOAD_URL, (GF_Node *)script, &par)) return JS_TRUE; return JS_FALSE; } if (!JSVAL_IS_OBJECT(argv[0])) return JS_FALSE; JS_ValueToObject(c, argv[0], &p); f = (GF_JSField *) JS_GetPrivate(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)) { JSString *str = JSVAL_TO_STRING(item); par.uri.url = JS_GetStringBytes(str); /*TODO add support for params*/ par.uri.nb_params = 0; if (ScriptAction(c, NULL, GF_JSAPI_OP_LOAD_URL, (GF_Node*)script, &par) ) return JS_TRUE; } } return JS_TRUE;}static JSBool setDescription(JSContext*c, JSObject*o, uintN n, jsval *v, jsval *rv){ return JS_TRUE;}static JSBool createVrmlFromString(JSContext*c, JSObject*obj, uintN argc, jsval *argv, jsval *rval){ 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); JSString *js_str; char *str; GF_List *nlist; GF_Node *sc_node = JS_GetContextPrivate(c); if (argc < 1) return JS_FALSE; if (!JSVAL_IS_STRING(argv[0])) return JS_FALSE; js_str = JSVAL_TO_STRING(argv[0]); str = JS_GetStringBytes(js_str); nlist = gf_sm_load_bt_from_string(sc_node->sgprivate->scenegraph, str); if (!nlist) return JSVAL_NULL; priv = JS_GetScriptStack(c); memset(&field, 0, sizeof(GF_FieldInfo)); field.fieldType = GF_SG_VRML_MFNODE; field.far_ptr = &nlist; *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); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -