You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mxe/src/coin-1-fixes.patch

4041 lines
134 KiB

This file is part of MXE. See LICENSE.md for licensing information.
Contains ad hoc patches for cross building.
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tony Theodore <tonyt@logyst.com>
Date: Sat, 18 Nov 2017 20:43:52 +1100
Subject: [PATCH 1/2] fixes
This patch has been taken from: https://bitbucket.org/msys2/coin/commits/69e9990b05cee506f5fa16c6edad02a7808bc610/raw/
It was modified to work with Coin 3.1.3.
(The order of the template arguments of SbHash was switched.)
diff --git a/include/Inventor/C/glue/spidermonkey.h b/include/Inventor/C/glue/spidermonkey.h
index 1111111..2222222 100644
--- a/include/Inventor/C/glue/spidermonkey.h
+++ b/include/Inventor/C/glue/spidermonkey.h
@@ -47,7 +47,7 @@ extern "C" {
Structs and defines.
*/
typedef int JSBool;
-typedef long jsword;
+typedef intmax_t jsword;
typedef jsword jsval;
typedef jsword jsid;
typedef int intN;
diff --git a/include/Inventor/C/glue/spidermonkey.h.orig b/include/Inventor/C/glue/spidermonkey.h.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/include/Inventor/C/glue/spidermonkey.h.orig
@@ -0,0 +1,470 @@
+#ifndef COIN_GLUE_SPIDERMONKEY_H
+#define COIN_GLUE_SPIDERMONKEY_H
+
+/**************************************************************************\
+ *
+ * This file is part of the Coin 3D visualization library.
+ * Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * ("GPL") version 2 as published by the Free Software Foundation.
+ * See the file LICENSE.GPL at the root directory of this source
+ * distribution for additional information about the GNU GPL.
+ *
+ * For using Coin with software that can not be combined with the GNU
+ * GPL, and for taking advantage of the additional benefits of our
+ * support services, please contact Kongsberg Oil & Gas Technologies
+ * about acquiring a Coin Professional Edition License.
+ *
+ * See http://www.coin3d.org/ for more information.
+ *
+ * Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ * http://www.sim.no/ sales@sim.no coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+#include <Inventor/C/basic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if 0 /* to get proper auto-indentation in emacs */
+}
+#endif /* emacs indentation */
+
+
+/*
+ This is used to detect whether the 'jsapi.h' was included by the
+ user or not. The JSVERSION_IS_ECMA is defined in the 'jspubtd.h'
+ file in the SpiderMonkey header directory.
+*/
+#ifndef JSVERSION_IS_ECMA
+
+
+/*
+ Structs and defines.
+*/
+typedef int JSBool;
+typedef long jsword;
+typedef jsword jsval;
+typedef jsword jsid;
+typedef int intN;
+typedef unsigned int uintN;
+typedef uint16_t jschar;
+
+typedef int32_t jsrefcount;
+typedef uint8_t jsbytecode;
+typedef uint32_t JSHashNumber;
+typedef uint32_t jsatomid;
+
+typedef enum JSType {
+ JSTYPE_VOID,
+ JSTYPE_OBJECT,
+ JSTYPE_FUNCTION,
+ JSTYPE_STRING,
+ JSTYPE_NUMBER,
+ JSTYPE_BOOLEAN,
+ JSTYPE_LIMIT
+} JSType;
+
+typedef enum JSAccessMode {
+ JSACC_PROTO = 0,
+ JSACC_PARENT = 1,
+ JSACC_IMPORT = 2,
+ JSACC_WATCH = 3,
+ JSACC_READ = 4,
+ JSACC_WRITE = 8,
+ JSACC_LIMIT
+} JSAccessMode;
+
+typedef enum JSGCStatus {
+ JSGC_BEGIN,
+ JSGC_END,
+ JSGC_MARK_END,
+ JSGC_FINALIZE_END
+} JSGCStatus;
+
+struct JSIdArray {
+ int32_t length;
+ jsid vector[1];
+};
+
+typedef void JSRuntime;
+typedef void JSContext;
+typedef void JSObject;
+typedef void JSObjectOps;
+typedef void JSXDRState;
+typedef void JSString;
+typedef struct JSClass JSClass;
+typedef struct JSPropertySpec JSPropertySpec;
+typedef int JSVersion;
+typedef void JSFunction;
+typedef struct JSFunctionSpec JSFunctionSpec;
+typedef struct JSErrorReport JSErrorReport;
+typedef void JSScript;
+
+#define JS_DLL_CALLBACK /* FIXME: set up this define properly. 20050601 mortene. */
+
+typedef JSBool (* JS_DLL_CALLBACK JSPropertyOp)(JSContext *, JSObject *, jsval, jsval *);
+typedef JSBool (* JS_DLL_CALLBACK JSEnumerateOp)(JSContext *, JSObject *);
+typedef JSBool (* JS_DLL_CALLBACK JSResolveOp)(JSContext *, JSObject *, jsval);
+typedef JSBool (* JS_DLL_CALLBACK JSConvertOp)(JSContext *, JSObject *, JSType, jsval *);
+typedef void (* JS_DLL_CALLBACK JSFinalizeOp)(JSContext *, JSObject *);
+typedef JSObjectOps * (* JS_DLL_CALLBACK JSGetObjectOps)(JSContext *, JSClass *);
+typedef JSBool (* JS_DLL_CALLBACK JSCheckAccessOp)(JSContext *, JSObject *, jsval, JSAccessMode, jsval *);
+typedef JSBool (* JS_DLL_CALLBACK JSNative)(JSContext *, JSObject *, uintN, jsval *, jsval *);
+typedef JSBool (* JS_DLL_CALLBACK JSXDRObjectOp)(JSXDRState *, JSObject **);
+typedef JSBool (* JS_DLL_CALLBACK JSHasInstanceOp)(JSContext *, JSObject *, jsval, JSBool *);
+typedef uint32_t (* JS_DLL_CALLBACK JSMarkOp)(JSContext *, JSObject *, void *);
+
+struct JSClass {
+ const char * name;
+ uint32_t flags;
+ JSPropertyOp addProperty;
+ JSPropertyOp delProperty;
+ JSPropertyOp getProperty;
+ JSPropertyOp setProperty;
+ JSEnumerateOp enumerate;
+ JSResolveOp resolve;
+ JSConvertOp convert;
+ JSFinalizeOp finalize;
+ JSGetObjectOps getObjectOps;
+ JSCheckAccessOp checkAccess;
+ JSNative call;
+ JSNative construct;
+ JSXDRObjectOp xdrObject;
+ JSHasInstanceOp hasInstance;
+ JSMarkOp mark;
+ jsword spare;
+};
+
+struct JSPropertySpec {
+ const char * name;
+ int8_t tinyid;
+ uint8_t flags;
+ JSPropertyOp getter;
+ JSPropertyOp setter;
+};
+
+struct JSFunctionSpec {
+ const char *name;
+ JSNative call;
+ uint8_t nargs;
+ uint8_t flags;
+ uint16_t extra;
+};
+
+struct JSErrorReport {
+ const char * filename;
+ uintN lineno;
+ const char * linebuf;
+ const char * tokenptr;
+ const jschar * uclinebuf;
+ const jschar * uctokenptr;
+ uintN flags;
+ uintN errorNumber;
+ const jschar * ucmessage;
+ const jschar ** messageArgs;
+};
+
+
+/* Defines and macros. ************************************************** */
+
+#define JSVAL_OBJECT 0x0
+#define JSVAL_INT 0x1
+#define JSVAL_DOUBLE 0x2
+#define JSVAL_STRING 0x4
+#define JSVAL_BOOLEAN 0x6
+
+#define JS_BIT(n) ((uint32_t)1 << (n))
+#define JS_BITMASK(n) (JS_BIT(n) - 1)
+
+#define JSVAL_TAGBITS 3
+#define JSVAL_TAGMASK JS_BITMASK(JSVAL_TAGBITS)
+#define JSVAL_TAG(v) ((v) & JSVAL_TAGMASK)
+#define JSVAL_SETTAG(v,t) ((v) | (t))
+#define JSVAL_CLRTAG(v) ((v) & ~(jsval)JSVAL_TAGMASK)
+
+#define JSVAL_IS_PRIMITIVE(v) (!JSVAL_IS_OBJECT(v) || JSVAL_IS_NULL(v))
+#define JSVAL_IS_OBJECT(v) (JSVAL_TAG(v) == JSVAL_OBJECT)
+#define JSVAL_IS_NUMBER(v) (JSVAL_IS_INT(v) || JSVAL_IS_DOUBLE(v))
+#define JSVAL_IS_INT(v) (((v) & JSVAL_INT) && (v) != JSVAL_VOID)
+#define JSVAL_IS_DOUBLE(v) (JSVAL_TAG(v) == JSVAL_DOUBLE)
+#define JSVAL_IS_STRING(v) (JSVAL_TAG(v) == JSVAL_STRING)
+#define JSVAL_IS_BOOLEAN(v) (JSVAL_TAG(v) == JSVAL_BOOLEAN)
+#define JSVAL_IS_NULL(v) ((v) == JSVAL_NULL)
+#define JSVAL_IS_VOID(v) ((v) == JSVAL_VOID)
+
+#define BOOLEAN_TO_JSVAL(b) JSVAL_SETTAG((jsval)(b) << JSVAL_TAGBITS, JSVAL_BOOLEAN)
+#define JSVAL_TO_BOOLEAN(v) ((JSBool)((v) >> JSVAL_TAGBITS))
+
+#define JSVAL_INT_BITS 31
+#define JSVAL_INT_POW2(n) ((jsval)1 << (n))
+#define JSVAL_INT_MIN ((jsval)1 - JSVAL_INT_POW2(30))
+#define JSVAL_INT_MAX (JSVAL_INT_POW2(30) - 1)
+#define INT_FITS_IN_JSVAL(i) ((uint32_t)((i)+JSVAL_INT_MAX) <= 2*JSVAL_INT_MAX)
+#define JSVAL_TO_INT(v) ((int32_t)(v) >> 1)
+#define INT_TO_JSVAL(i) (((jsval)(i) << 1) | JSVAL_INT)
+
+#define JSVAL_TO_GCTHING(v) ((void *)JSVAL_CLRTAG(v))
+#define JSVAL_TO_OBJECT(v) ((JSObject *)JSVAL_TO_GCTHING(v))
+#define JSVAL_TO_DOUBLE(v) ((double *)JSVAL_TO_GCTHING(v))
+#define JSVAL_TO_STRING(v) ((JSString *)JSVAL_TO_GCTHING(v))
+#define OBJECT_TO_JSVAL(obj) ((jsval)(obj))
+#define DOUBLE_TO_JSVAL(dp) JSVAL_SETTAG((jsval)(dp), JSVAL_DOUBLE)
+#define STRING_TO_JSVAL(str) JSVAL_SETTAG((jsval)(str), JSVAL_STRING)
+#define JSVAL_TO_PRIVATE(v) ((void *)((v) & ~JSVAL_INT))
+#define PRIVATE_TO_JSVAL(p) ((jsval)(p) | JSVAL_INT)
+
+#define JSPROP_ENUMERATE 0x01
+#define JSPROP_READONLY 0x02
+#define JSPROP_PERMANENT 0x04
+#define JSPROP_EXPORTED 0x08
+#define JSPROP_GETTER 0x10
+#define JSPROP_SETTER 0x20
+#define JSPROP_SHARED 0x40
+#define JSPROP_INDEX 0x80
+
+#define JS_FALSE (int)0
+#define JS_TRUE (int)1
+
+#define JSVAL_VOID INT_TO_JSVAL(0 - JSVAL_INT_POW2(30))
+#define JSVAL_NULL OBJECT_TO_JSVAL(0)
+#define JSVAL_ZERO INT_TO_JSVAL(0)
+#define JSVAL_ONE INT_TO_JSVAL(1)
+#define JSVAL_FALSE BOOLEAN_TO_JSVAL(JS_FALSE)
+#define JSVAL_TRUE BOOLEAN_TO_JSVAL(JS_TRUE)
+
+#define JSCLASS_HAS_PRIVATE (1<<0)
+#define JSCLASS_NEW_ENUMERATE (1<<1)
+#define JSCLASS_NEW_RESOLVE (1<<2)
+#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3)
+#define JSCLASS_SHARE_ALL_PROPERTIES (1<<4)
+#define JSCLASS_NEW_RESOLVE_GETS_START (1<<5)
+
+#define JSFUN_BOUND_METHOD 0x40
+
+#define JSOPTION_STRICT JS_BIT(0)
+#define JSOPTION_WERROR JS_BIT(1)
+#define JSOPTION_VAROBJFIX JS_BIT(2)
+#define JSOPTION_PRIVATE_IS_NSISUPPORTS JS_BIT(3)
+#define JSOPTION_COMPILE_N_GO JS_BIT(4)
+
+
+/* Function typedefs. *************************************************** */
+
+typedef void (* JS_DLL_CALLBACK JSErrorReporter)(JSContext *, const char *, JSErrorReport *);
+typedef JSBool (* JS_DLL_CALLBACK JSGCCallback)(JSContext *, JSGCStatus);
+
+#endif /* !JSVERSION_IS_ECMA */
+
+typedef JSBool (* JS_EvaluateScript_t)(JSContext *, JSObject *, const char *, uintN, const char *, uintN, jsval *);
+typedef JSString * (* JS_ValueToString_t)(JSContext *, jsval);
+typedef char * (* JS_GetStringBytes_t)(JSString *);
+typedef JSBool (* JS_SetProperty_t)(JSContext *, JSObject *, const char *, jsval *);
+typedef JSBool (* JS_GetProperty_t)(JSContext *, JSObject *, const char *, jsval *);
+typedef JSBool (* JS_CallFunctionName_t)(JSContext *, JSObject *, const char *, uintN, jsval *, jsval *);
+typedef JSBool (* JS_CallFunctionValue_t)(JSContext *, JSObject *, jsval, uintN, jsval *, jsval *);
+typedef JSObject * (* JS_ConstructObjectWithArguments_t)(JSContext *, JSClass *, JSObject *, JSObject *, uintN, jsval *);
+typedef JSRuntime * (* JS_NewRuntime_t)(uint32_t);
+typedef void (* JS_DestroyRuntime_t)(JSRuntime *);
+typedef JSContext * (* JS_NewContext_t)(JSRuntime *, size_t);
+typedef void (* JS_DestroyContext_t)(JSContext *);
+typedef void (* JS_ShutDown_t)(void);
+typedef JSObject * (* JS_NewObject_t)(JSContext *, JSClass *, JSObject *, JSObject *);
+typedef JSBool (* JS_InitStandardClasses_t)(JSContext *, JSObject *);
+typedef JSErrorReporter (* JS_SetErrorReporter_t)(JSContext *, JSErrorReporter);
+typedef JSBool (* JS_PropertyStub_t)(JSContext *, JSObject *, jsval, jsval *);
+typedef JSBool (* JS_EnumerateStub_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_ResolveStub_t)(JSContext *, JSObject *, jsval);
+typedef JSBool (* JS_ConvertStub_t)(JSContext *, JSObject *, JSType, jsval *);
+typedef void (* JS_FinalizeStub_t)(JSContext *, JSObject *);
+typedef const char * (* JS_GetImplementationVersion_t)(void);
+typedef void * (* JS_GetPrivate_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_SetPrivate_t)(JSContext *, JSObject *, void *);
+typedef JSFunction * (* JS_NewFunction_t)(JSContext *, JSNative, uintN, uintN flags, JSObject *, const char *);
+typedef JSObject * (* JS_GetFunctionObject_t)(JSFunction *);
+typedef JSObject * (* JS_DefineObject_t)(JSContext *, JSObject *, const char *, JSClass *, JSObject *, uintN);
+typedef JSBool (* JS_DefineProperties_t)(JSContext *, JSObject *, JSPropertySpec *);
+typedef JSObject * (* JS_GetParent_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_SetParent_t)(JSContext *, JSObject *, JSObject *);
+typedef JSBool (* JS_DefineFunctions_t)(JSContext *, JSObject *, JSFunctionSpec *);
+typedef JSString * (* JS_NewStringCopyZ_t)(JSContext *, const char *);
+typedef JSType (* JS_TypeOfValue_t)(JSContext *, jsval);
+typedef const char * (* JS_GetTypeName_t)(JSContext *, JSType);
+typedef JSBool (* JS_InstanceOf_t)(JSContext *, JSObject *, JSClass *, jsval *);
+typedef JSObject * (* JS_InitClass_t)(JSContext *, JSObject *, JSObject *, JSClass *,
+ JSNative, uintN, JSPropertySpec *, JSFunctionSpec *,
+ JSPropertySpec *, JSFunctionSpec *);
+typedef JSBool (* JS_NewDoubleValue_t)(JSContext *, double, jsval *);
+typedef void * (* JS_GetContextPrivate_t)(JSContext *);
+typedef void (* JS_SetContextPrivate_t)(JSContext *, void *);
+typedef JSBool (* JS_ValueToBoolean_t)(JSContext *, jsval, JSBool *);
+typedef JSBool (* JS_ValueToNumber_t)(JSContext *, jsval, double *);
+typedef JSObject * (* JS_NewArrayObject_t)(JSContext *, int32_t, jsval *);
+typedef JSBool (* JS_GetArrayLength_t)(JSContext *, JSObject *, uint32_t *);
+typedef JSBool (* JS_SetArrayLength_t)(JSContext *, JSObject *, uint32_t);
+typedef JSBool (* JS_HasArrayLength_t)(JSContext *, JSObject *, uint32_t *);
+typedef JSBool (* JS_GetElement_t)(JSContext *, JSObject *, int32_t, jsval *);
+typedef JSBool (* JS_SetElement_t)(JSContext *, JSObject *, int32_t, jsval *);
+typedef JSBool (* JS_AddRoot_t)(JSContext *, void *);
+typedef JSBool (* JS_RemoveRoot_t)(JSContext *, void *);
+typedef size_t (* JS_GetStringLength_t)(JSString *);
+typedef JSBool (* JS_LookupProperty_t)(JSContext *, JSObject *, const char *, jsval *);
+typedef JSBool (* JS_DefineProperty_t)(JSContext *, JSObject *, const char *, jsval, JSPropertyOp, JSPropertyOp, uintN);
+typedef JSScript * (* JS_CompileFile_t)(JSContext *, JSObject *, const char *);
+typedef JSBool (* JS_ValueToObject_t)(JSContext *, jsval, JSObject **);
+typedef JSBool (* JS_ExecuteScript_t)(JSContext *, JSObject *, JSScript *, jsval *);
+typedef JSBool (* JS_IsExceptionPending_t)(JSContext *);
+typedef JSBool (* JS_GetPendingException_t)(JSContext *, jsval *);
+typedef void (* JS_SetPendingException_t)(JSContext *, jsval);
+typedef void (* JS_ClearPendingException_t)(JSContext *);
+typedef double * (* JS_NewDouble_t)(JSContext *, double);
+typedef JSBool (* JS_CallFunction_t)(JSContext *, JSObject *, JSFunction *, uintN, jsval *, jsval *);
+typedef JSFunction * (* JS_ValueToFunction_t)(JSContext *, jsval);
+typedef void (* JS_ReportError_t)(JSContext *, const char *, ...);
+typedef JSBool (* JS_IsArrayObject_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_ObjectIsFunction_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_ValueToECMAInt32_t)(JSContext *, jsval, int32_t *);
+typedef JSFunction * (* JS_DefineFunction_t)(JSContext *, JSObject *, const char *, JSNative, uintN, uintN);
+typedef JSObject * (* JS_GetGlobalObject_t)(JSContext *);
+typedef JSGCCallback (* JS_SetGCCallback_t)(JSContext *, JSGCCallback);
+typedef void (* JS_GC_t)(JSContext *);
+typedef void (* JS_MaybeGC_t)(JSContext *);
+typedef JSBool (* JS_IsRunning_t)(JSContext *);
+typedef JSBool (* JS_DeleteProperty_t)(JSContext *, JSObject *, const char *);
+typedef JSScript * (* JS_CompileScript_t)(JSContext *, JSObject *,
+ const char *, size_t,
+ const char *, uintN);
+typedef jsval (* JS_GetNaNValue_t)(JSContext *);
+typedef jsval (* JS_GetNegativeInfinityValue_t)(JSContext *);
+typedef jsval (* JS_GetPositiveInfinityValue_t)(JSContext *);
+typedef jsval (* JS_GetEmptyStringValue_t)(JSContext *);
+typedef JSBool (* JS_SetPropertyAttributes_t)(JSContext *, JSObject *, const char *, uintN, JSBool *);
+typedef JSBool (* JS_GetPropertyAttributes_t)(JSContext *, JSObject *, const char *, uintN *, JSBool *);
+typedef JSClass * (* JS_GetClass_t)(JSObject *);
+typedef JSObject * (* JS_GetPrototype_t)(JSContext *, JSObject *);
+typedef JSObject * (* JS_SetPrototype_t)(JSContext *, JSObject *, JSObject *);
+typedef intN (* JS_CompareStrings_t)(JSString *, JSString *);
+typedef uint32_t (* JS_GetOptions_t)(JSContext *);
+typedef uint32_t (* JS_SetOptions_t)(JSContext *, uint32_t);
+typedef uint32_t (* JS_ToggleOptions_t)(JSContext *, uint32_t);
+typedef struct JSIdArray * (* JS_Enumerate_t)(JSContext *, JSObject *);
+typedef JSBool (* JS_IdToValue_t)(JSContext *, jsid, jsval *);
+typedef const char * (* JS_GetFunctionName_t)(JSFunction *);
+typedef JSObject * (* JS_GetConstructor_t)(JSContext *, JSObject *);
+typedef void (* JS_DestroyIdArray_t)(JSContext *, struct JSIdArray *);
+
+
+/* Access interface. **************************************************** */
+
+typedef struct {
+ int available;
+
+ JS_CallFunctionName_t JS_CallFunctionName;
+ JS_CallFunctionValue_t JS_CallFunctionValue;
+ JS_ConstructObjectWithArguments_t JS_ConstructObjectWithArguments;
+ JS_ConvertStub_t JS_ConvertStub;
+ JS_DestroyContext_t JS_DestroyContext;
+ JS_DestroyRuntime_t JS_DestroyRuntime;
+ JS_EnumerateStub_t JS_EnumerateStub;
+ JS_EvaluateScript_t JS_EvaluateScript;
+ JS_FinalizeStub_t JS_FinalizeStub;
+ JS_GetClass_t JS_GetClass;
+ JS_GetImplementationVersion_t JS_GetImplementationVersion;
+ JS_GetProperty_t JS_GetProperty;
+ JS_GetStringBytes_t JS_GetStringBytes;
+ JS_InitStandardClasses_t JS_InitStandardClasses;
+ JS_NewContext_t JS_NewContext;
+ JS_NewObject_t JS_NewObject;
+ JS_NewRuntime_t JS_NewRuntime;
+ JS_PropertyStub_t JS_PropertyStub;
+ JS_ResolveStub_t JS_ResolveStub;
+ JS_SetErrorReporter_t JS_SetErrorReporter;
+ JS_SetProperty_t JS_SetProperty;
+ JS_ShutDown_t JS_ShutDown;
+ JS_ValueToString_t JS_ValueToString;
+ JS_DefineObject_t JS_DefineObject;
+ JS_DefineProperties_t JS_DefineProperties;
+ JS_GetPrivate_t JS_GetPrivate;
+ JS_SetPrivate_t JS_SetPrivate;
+ JS_NewFunction_t JS_NewFunction;
+ JS_GetFunctionObject_t JS_GetFunctionObject;
+ JS_GetParent_t JS_GetParent;
+ JS_SetParent_t JS_SetParent;
+ JS_DefineFunctions_t JS_DefineFunctions;
+ JS_NewStringCopyZ_t JS_NewStringCopyZ;
+ JS_TypeOfValue_t JS_TypeOfValue;
+ JS_GetTypeName_t JS_GetTypeName;
+ JS_InstanceOf_t JS_InstanceOf;
+ JS_InitClass_t JS_InitClass;
+ JS_NewDoubleValue_t JS_NewDoubleValue;
+ JS_GetContextPrivate_t JS_GetContextPrivate;
+ JS_SetContextPrivate_t JS_SetContextPrivate;
+ JS_ValueToBoolean_t JS_ValueToBoolean;
+ JS_ValueToNumber_t JS_ValueToNumber;
+ JS_NewArrayObject_t JS_NewArrayObject;
+ JS_GetArrayLength_t JS_GetArrayLength;
+ JS_SetArrayLength_t JS_SetArrayLength;
+ JS_HasArrayLength_t JS_HasArrayLength;
+ JS_GetElement_t JS_GetElement;
+ JS_SetElement_t JS_SetElement;
+ JS_AddRoot_t JS_AddRoot;
+ JS_RemoveRoot_t JS_RemoveRoot;
+ JS_GetStringLength_t JS_GetStringLength;
+ JS_LookupProperty_t JS_LookupProperty;
+ JS_DefineProperty_t JS_DefineProperty;
+ JS_CompileFile_t JS_CompileFile;
+ JS_ValueToObject_t JS_ValueToObject;
+ JS_ExecuteScript_t JS_ExecuteScript;
+ JS_IsExceptionPending_t JS_IsExceptionPending;
+ JS_GetPendingException_t JS_GetPendingException;
+ JS_SetPendingException_t JS_SetPendingException;
+ JS_ClearPendingException_t JS_ClearPendingException;
+ JS_NewDouble_t JS_NewDouble;
+ JS_CallFunction_t JS_CallFunction;
+ JS_ValueToFunction_t JS_ValueToFunction;
+ JS_ReportError_t JS_ReportError;
+ JS_IsArrayObject_t JS_IsArrayObject;
+ JS_ObjectIsFunction_t JS_ObjectIsFunction;
+ // Note: We use this function instead of JS_ValueToInt32() since the
+ // latter is buggy in versions of SpiderMonkey older than 2005-09-29,
+ // see Mozilla bug #284032.
+ JS_ValueToECMAInt32_t JS_ValueToECMAInt32;
+ JS_DefineFunction_t JS_DefineFunction;
+ JS_GetGlobalObject_t JS_GetGlobalObject;
+ JS_SetGCCallback_t JS_SetGCCallback;
+ JS_GC_t JS_GC;
+ JS_MaybeGC_t JS_MaybeGC;
+ JS_IsRunning_t JS_IsRunning;
+ JS_DeleteProperty_t JS_DeleteProperty;
+ JS_CompileScript_t JS_CompileScript;
+ JS_GetNaNValue_t JS_GetNaNValue;
+ JS_GetNegativeInfinityValue_t JS_GetNegativeInfinityValue;
+ JS_GetPositiveInfinityValue_t JS_GetPositiveInfinityValue;
+ JS_GetEmptyStringValue_t JS_GetEmptyStringValue;
+ JS_SetPropertyAttributes_t JS_SetPropertyAttributes;
+ JS_GetPropertyAttributes_t JS_GetPropertyAttributes;
+ JS_GetPrototype_t JS_GetPrototype;
+ JS_SetPrototype_t JS_SetPrototype;
+ JS_CompareStrings_t JS_CompareStrings;
+ JS_GetOptions_t JS_GetOptions;
+ JS_SetOptions_t JS_SetOptions;
+ JS_ToggleOptions_t JS_ToggleOptions;
+ JS_Enumerate_t JS_Enumerate;
+ JS_IdToValue_t JS_IdToValue;
+ JS_GetFunctionName_t JS_GetFunctionName;
+ JS_GetConstructor_t JS_GetConstructor;
+ JS_DestroyIdArray_t JS_DestroyIdArray;
+
+} SpiderMonkey_t;
+
+COIN_DLL_API const SpiderMonkey_t * spidermonkey(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* !COIN_GLUE_SPIDERMONKEY_H */
diff --git a/src/foreignfiles/SoSTLFileKit.cpp b/src/foreignfiles/SoSTLFileKit.cpp
index 1111111..2222222 100644
--- a/src/foreignfiles/SoSTLFileKit.cpp
+++ b/src/foreignfiles/SoSTLFileKit.cpp
@@ -594,14 +594,14 @@ SoSTLFileKit::addFacet(const SbVec3f & v1, const SbVec3f & v2, const SbVec3f & v
SO_GET_ANY_PART(this, "facets", SoIndexedFaceSet);
// find existing indexes if any
- long v1idx = PRIVATE(this)->points->findPoint(v1), v1new = (v1idx == -1);
- long v2idx = PRIVATE(this)->points->findPoint(v2), v2new = (v2idx == -1);
- long v3idx = PRIVATE(this)->points->findPoint(v3), v3new = (v3idx == -1);
- if (!v1new) { v1idx = (long) PRIVATE(this)->points->getUserData(v1idx); }
- if (!v2new) { v2idx = (long) PRIVATE(this)->points->getUserData(v2idx); }
- if (!v3new) { v3idx = (long) PRIVATE(this)->points->getUserData(v3idx); }
- long nidx = PRIVATE(this)->normals->findPoint(n);
- if (nidx != -1) { nidx = (long) PRIVATE(this)->normals->getUserData(nidx); }
+ intmax_t v1idx = PRIVATE(this)->points->findPoint(v1), v1new = (v1idx == -1);
+ intmax_t v2idx = PRIVATE(this)->points->findPoint(v2), v2new = (v2idx == -1);
+ intmax_t v3idx = PRIVATE(this)->points->findPoint(v3), v3new = (v3idx == -1);
+ if (!v1new) { v1idx = (intmax_t) PRIVATE(this)->points->getUserData(v1idx); }
+ if (!v2new) { v2idx = (intmax_t) PRIVATE(this)->points->getUserData(v2idx); }
+ if (!v3new) { v3idx = (intmax_t) PRIVATE(this)->points->getUserData(v3idx); }
+ intmax_t nidx = PRIVATE(this)->normals->findPoint(n);
+ if (nidx != -1) { nidx = (intmax_t) PRIVATE(this)->normals->getUserData(nidx); }
// toss out invalid facets - facets where two or more points are in
// the same location. what are these - are they lines and points or
diff --git a/src/foreignfiles/SoSTLFileKit.cpp.orig b/src/foreignfiles/SoSTLFileKit.cpp.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/src/foreignfiles/SoSTLFileKit.cpp.orig
@@ -0,0 +1,799 @@
+/**************************************************************************\
+ *
+ * This file is part of the Coin 3D visualization library.
+ * Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * ("GPL") version 2 as published by the Free Software Foundation.
+ * See the file LICENSE.GPL at the root directory of this source
+ * distribution for additional information about the GNU GPL.
+ *
+ * For using Coin with software that can not be combined with the GNU
+ * GPL, and for taking advantage of the additional benefits of our
+ * support services, please contact Kongsberg Oil & Gas Technologies
+ * about acquiring a Coin Professional Edition License.
+ *
+ * See http://www.coin3d.org/ for more information.
+ *
+ * Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ * http://www.sim.no/ sales@sim.no coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#ifdef HAVE_NODEKITS
+
+#include <ForeignFiles/SoSTLFileKit.h>
+
+#include <Inventor/SbBasic.h>
+#include <Inventor/lists/SbList.h>
+#include <Inventor/errors/SoDebugError.h>
+#include <Inventor/actions/SoCallbackAction.h>
+#include <Inventor/actions/SoReorganizeAction.h>
+#include <Inventor/nodes/SoSeparator.h>
+#include <Inventor/nodes/SoShapeHints.h>
+#include <Inventor/nodes/SoTexture2.h>
+#include <Inventor/nodes/SoNormal.h>
+#include <Inventor/nodes/SoNormalBinding.h>
+#include <Inventor/nodes/SoMaterial.h>
+#include <Inventor/nodes/SoMaterialBinding.h>
+#include <Inventor/nodes/SoCoordinate3.h>
+#include <Inventor/nodes/SoIndexedFaceSet.h>
+#include <Inventor/nodes/SoInfo.h>
+#include <Inventor/SbBSPTree.h>
+#include <Inventor/SoPrimitiveVertex.h>
+
+#include "steel.h"
+#include "nodekits/SoSubKitP.h"
+
+
+#if 0
+ SoCallback "callbackList" SoBaseKit
+ SoSeparator "topSeparator" SoForeignFileKit
+ SoShapeHints "shapehints" SoSTLFileKit
+ SoTexture2 "texture" SoSTLFileKit
+ SoNormalBinding "normalbinding" SoSTLFileKit
+ SoNormal "normals" SoSTLFileKit
+ SoMaterialBinding "materialbinding" SoSTLFileKit
+ SoMaterial "material" SoSTLFileKit
+ SoCoordinate3 "coordinates" SoSTLFileKit
+ SoIndexedFaceSet "facets" SoSTLFileKit
+#endif // 0
+
+class SoSTLFileKitP {
+public:
+ SoSTLFileKitP(SoSTLFileKit * pub)
+ : api(pub) {
+ this->data = new SbList<uint16_t>;
+ this->points = new SbBSPTree;
+ this->normals = new SbBSPTree;
+ }
+ ~SoSTLFileKitP(void) {
+ delete this->data;
+ delete this->points;
+ delete this->normals;
+ }
+
+public:
+ SoSTLFileKit * const api;
+
+ SbList<uint16_t> * data;
+ SbBSPTree * points;
+ SbBSPTree * normals;
+
+ int numfacets;
+ int numvertices;
+ int numnormals;
+ int numsharedvertices;
+ int numsharednormals;
+ int numredundantfacets;
+}; // SoSTLFileKitP
+
+// *************************************************************************
+
+/*!
+ \class SoSTLFileKit SoSTLFileKit.h ForeignFiles/SoSTLFileKit.h
+ \brief SoSTLFileKit is a class for using STL files with Coin.
+
+ Class for using STL files with Coin. You can use it to read and
+ write STL files, and convert back and forth between Open Inventor
+ scene graphs and SoSTLFileKits.
+
+ STL files are 3D models intended for 3D printers, and is a format
+ supported by a wide variety of computer-aided design programs. STL
+ models are, because of their intended purpose, always
+ representations of solid objects. STL is short for
+ Stereolithography, the process used for 3D printing.
+
+ Ordinary STL models do not contain color information. There are,
+ however, two extensions to the binary file format for specifying
+ color. Currently neither extension is supported. This is caused by
+ lack of sample models using the extensions and will be added as soon
+ as such models are found. We have the specs on the extensions, and
+ it should be pretty straight-forwards to implement, but we want to
+ get it right at once since we have write support (we don't want to
+ inadvertently create a third color extension ;).
+
+ When writing STL files, certain STL model criterias are not enforced
+ by SoSTLFileKit. These are:
+
+ - STL models should represent complete solids - it is the user's
+ responsibility to give models of solid data to readScene(), and
+ not readScene()'s responsibility to check the incoming data.
+
+ - STL models should have all triangles in counterclockwise order.
+ This is not enforced either.
+
+ - STL models should reside in the positive octant of the coordinate
+ space. This is also the user's responsibility to ensure, although
+ adding functionality for translating the model should be easy, so
+ it might get implemented.
+
+ Since the color extensions are not supported yet, color information
+ is not collected either when converting Open Inventor scene graphs to
+ SoSTLFileKits.
+
+ \relates foreignfileformats
+ \COIN_CLASS_EXTENSION
+ \since Coin 3.0
+*/
+
+#define PRIVATE(obj) ((obj)->pimpl)
+
+SO_KIT_SOURCE(SoSTLFileKit)
+
+/*!
+ Initializes class and registers file identification functions.
+*/
+
+void
+SoSTLFileKit::initClass(void)
+{
+ SO_KIT_INIT_CLASS(SoSTLFileKit, SoForeignFileKit, SoForeignFileKit);
+
+ SoType type = SoSTLFileKit::getClassTypeId();
+ SoForeignFileKit::registerFileExtension(type, "stl", SoSTLFileKit::identify);
+}
+
+/*!
+ Returns wether or not \a filename is identified as an STL file.
+*/
+
+SbBool
+SoSTLFileKit::identify(const char * filename)
+{
+ assert(filename);
+ stl_reader * reader = stl_reader_create(filename);
+ if ( !reader ) {
+ return FALSE;
+ }
+ stl_reader_destroy(reader);
+ return TRUE;
+}
+
+/*!
+ Constructor.
+*/
+
+SoSTLFileKit::SoSTLFileKit(void)
+{
+ PRIVATE(this) = new SoSTLFileKitP(this);
+
+ SO_KIT_INTERNAL_CONSTRUCTOR(SoSTLFileKit);
+
+ SO_KIT_ADD_FIELD(info, (""));
+ SO_KIT_ADD_FIELD(binary, (FALSE));
+ SO_KIT_ADD_FIELD(colorization, (SoSTLFileKit::GREY));
+
+ SO_KIT_DEFINE_ENUM_VALUE(Colorization, GREY);
+ SO_KIT_DEFINE_ENUM_VALUE(Colorization, MATERIALISE);
+ SO_KIT_DEFINE_ENUM_VALUE(Colorization, TNO_VISICAM);
+
+ SO_KIT_SET_SF_ENUM_TYPE(colorization, Colorization);
+
+ SO_KIT_ADD_CATALOG_ENTRY(facets, SoIndexedFaceSet,
+ FALSE, topSeparator, \x0, FALSE);
+ SO_KIT_ADD_CATALOG_ENTRY(coordinates, SoCoordinate3,
+ FALSE, topSeparator, facets, FALSE);
+ SO_KIT_ADD_CATALOG_ENTRY(material, SoMaterial,
+ FALSE, topSeparator, coordinates, FALSE);
+ SO_KIT_ADD_CATALOG_ENTRY(materialbinding, SoMaterialBinding,
+ FALSE, topSeparator, material, FALSE);
+ SO_KIT_ADD_CATALOG_ENTRY(normals, SoNormal,
+ FALSE, topSeparator, materialbinding, FALSE);
+ SO_KIT_ADD_CATALOG_ENTRY(normalbinding, SoNormalBinding,
+ FALSE, topSeparator, normals, FALSE);
+ SO_KIT_ADD_CATALOG_ENTRY(texture, SoTexture2,
+ FALSE, topSeparator, normalbinding, FALSE);
+ SO_KIT_ADD_CATALOG_ENTRY(shapehints, SoShapeHints,
+ FALSE, topSeparator, texture, FALSE);
+
+ SO_KIT_INIT_INSTANCE();
+}
+
+/*!
+ Destructor.
+*/
+
+SoSTLFileKit::~SoSTLFileKit(void)
+{
+ delete PRIVATE(this);
+ PRIVATE(this) = NULL;
+}
+
+// doc in inherited class
+SbBool
+SoSTLFileKit::canReadFile(const char * filename) const
+{
+ if ( !filename ) return TRUE; // we can read STL files, in general
+ return SoSTLFileKit::identify(filename);
+}
+
+/*!
+ Reads in an STL file. Both ascii and binary files are supported.
+ For binary files, the color extensions are not implemented yet.
+
+ Returns FALSE if \a filename could not be opened or parsed
+ correctly.
+
+ \sa canReadFile, canWriteScene, writeScene
+*/
+
+SbBool
+SoSTLFileKit::readFile(const char * filename)
+{
+ assert(filename);
+
+ this->reset();
+
+ stl_reader * reader = stl_reader_create(filename);
+ if ( !reader ) {
+ SoDebugError::postInfo("SoSTLFileKit::readFile",
+ "unable to create STL reader for '%s'.",
+ filename);
+ return FALSE;
+ }
+
+ SbBool binary = (stl_reader_flags(reader) & STL_BINARY) ? TRUE : FALSE;
+
+ SoShapeHints * hints =
+ SO_GET_ANY_PART(this, "shapehints", SoShapeHints);
+ hints->vertexOrdering.setValue(SoShapeHints::UNKNOWN_ORDERING);
+ // what it should have been
+ // hints->vertexOrdering.setValue(SoShapeHints::COUNTERCLOCKWISE);
+ hints->shapeType.setValue(SoShapeHints::SOLID);
+ hints->faceType.setValue(SoShapeHints::UNKNOWN_FACE_TYPE);
+
+ SoNormalBinding * normalbinding =
+ SO_GET_ANY_PART(this, "normalbinding", SoNormalBinding);
+ normalbinding->value = SoNormalBinding::PER_FACE_INDEXED;
+
+ stl_facet * facet = stl_facet_create();
+ SbBool loop = TRUE, success = TRUE;
+ while ( loop ) {
+ const int peekval = stl_reader_peek(reader);
+ if ( peekval == STL_BEGIN ) {
+ } else if ( peekval == STL_INIT_INFO ) {
+ // FIXME: set info
+ } else if ( peekval == STL_EXIT_INFO ) {
+ } else if ( peekval == STL_END ) {
+ loop = FALSE;
+ } else if ( peekval == STL_FACET ) {
+ stl_real x, y, z;
+ stl_reader_fill_facet(reader, facet);
+ stl_facet_get_normal(facet, &x, &y, &z);
+ SbVec3f normal((float) x, (float) y, (float) z);
+ stl_facet_get_vertex1(facet, &x, &y, &z);
+ SbVec3f vertex1((float) x, (float) y, (float) z);
+ stl_facet_get_vertex2(facet, &x, &y, &z);
+ SbVec3f vertex2((float) x, (float) y, (float) z);
+ stl_facet_get_vertex3(facet, &x, &y, &z);
+ SbVec3f vertex3((float) x, (float) y, (float) z);
+ if ( normal.length() == 0.0f ) { // auto-calculate
+ SbVec3f v1(vertex2-vertex1);
+ SbVec3f v2(vertex3-vertex1);
+ normal = v1.cross(v2);
+ float len = normal.length();
+ if ( len > 0 ) normal /= len;
+ }
+ unsigned int data = stl_facet_get_padding(facet);
+
+ SbBool added = this->addFacet(vertex1, vertex2, vertex3, normal);
+
+#if defined(COIN_EXTRA_DEBUG) || 1
+ if ( added && binary ) {
+ // binary contains padding, which might be colorization
+ // colorization is not implemented yet, so therefore some debug
+ // output comes here so colorized models can be detected.
+ PRIVATE(this)->data->append((uint16_t) data);
+ if ( data != 0 ) {
+ fprintf(stderr, "facet %5d - data: %04x\n", PRIVATE(this)->numfacets - 1, data);
+ }
+ }
+#endif // COIN_EXTRA_DEBUG
+ } else if ( peekval == STL_ERROR ) {
+ SoDebugError::post("SoSTLFileKit::readFile",
+ "error '%s' after %d facets, line %d.",
+ stl_reader_get_error(reader),
+ PRIVATE(this)->numfacets,
+ stl_reader_get_line_number(reader));
+ loop = FALSE;
+ success = FALSE;
+ if (strcmp(stl_reader_get_error(reader), "premature end of file") == 0) {
+ // this one we will accept though - models with missing
+ // end-indicator have been found...
+ success = TRUE;
+ }
+ }
+ }
+
+ // done - no need for the BSP trees to contain data any more
+ PRIVATE(this)->points->clear();
+ PRIVATE(this)->normals->clear();
+
+ stl_facet_destroy(facet);
+ stl_reader_destroy(reader);
+
+ if ( !success ) {
+ this->reset();
+ } else {
+ this->organizeModel();
+ }
+ return success;
+}
+
+// doc in inherited class
+SbBool
+SoSTLFileKit::canReadScene(void) const
+{
+ return TRUE;
+}
+
+/*!
+ Converts a scene graph into an SoSTLFileKit. Useful for creating
+ STL files.
+
+ \sa canReadScene, canWriteFile, writeFile
+*/
+
+SbBool
+SoSTLFileKit::readScene(SoNode * scene)
+{
+ this->reset();
+
+ scene->ref();
+ SoCallbackAction cba;
+ cba.addTriangleCallback(SoType::fromName("SoNode"), add_facet_cb, this);
+ cba.apply(scene);
+ scene->unrefNoDelete();
+
+ // no need for the BSP trees to contain data any more
+ PRIVATE(this)->points->clear();
+ PRIVATE(this)->normals->clear();
+
+ this->organizeModel();
+
+ return TRUE;
+}
+
+// doc in inherited class
+SbBool
+SoSTLFileKit::canWriteScene(const char * format) const
+{
+ if ( !format ) return TRUE;
+ // FIXME: implement format checking (VRML1, VRML97)
+ return TRUE;
+}
+
+/*!
+ Converts the STL model into a native scene graph.
+
+ \sa canWriteScene
+*/
+
+SbBool
+SoSTLFileKit::writeScene(SoNode *& root, const char * format)
+{
+ static const char default_format[] = "#VRML 1.0"; // syntax for this?
+ if ( !format ) format = default_format;
+
+ SbBool success = true;
+
+ // FIXME: implement format check to specify scene graph setup
+ enum Format {
+ UNKNOWN,
+ VRML1,
+ VRML97
+ };
+
+ Format build = VRML1;
+
+ if ( build == VRML1 ) {
+ // create VRML1 scene
+ SoSeparator * sceneroot = new SoSeparator;
+ sceneroot->ref();
+
+ SoInfo * info = new SoInfo;
+ info->string = "STL model data, created by Coin " COIN_VERSION ".";
+ sceneroot->addChild(info);
+
+ SoShapeHints * shapehints_orig =
+ SO_GET_ANY_PART(this, "shapehints", SoShapeHints);
+ SoShapeHints * shapehints_copy = new SoShapeHints;
+ shapehints_copy->copyContents(shapehints_orig, FALSE);
+ sceneroot->addChild(shapehints_copy);
+
+ SoTexture2 * texture_orig = SO_GET_ANY_PART(this, "texture", SoTexture2);
+ SoTexture2 * texture_copy = new SoTexture2;
+ texture_copy->copyContents(texture_orig, FALSE);
+ sceneroot->addChild(texture_copy);
+
+ SoNormalBinding * normalbinding_orig =
+ SO_GET_ANY_PART(this, "normalbinding", SoNormalBinding);
+ SoNormalBinding * normalbinding_copy = new SoNormalBinding;
+ normalbinding_copy->copyContents(normalbinding_orig, FALSE);
+ sceneroot->addChild(normalbinding_copy);
+
+ SoNormal * normals_orig = SO_GET_ANY_PART(this, "normals", SoNormal);
+ SoNormal * normals_copy = new SoNormal;
+ normals_copy->copyContents(normals_orig, FALSE);
+ sceneroot->addChild(normals_copy);
+
+ SoMaterialBinding * materialbinding_orig =
+ SO_GET_ANY_PART(this, "materialbinding", SoMaterialBinding);
+ SoMaterialBinding * materialbinding_copy = new SoMaterialBinding;
+ materialbinding_copy->copyContents(materialbinding_orig, FALSE);
+ sceneroot->addChild(materialbinding_copy);
+
+ SoMaterial * material_orig = SO_GET_ANY_PART(this, "material", SoMaterial);
+ SoMaterial * material_copy = new SoMaterial;
+ material_copy->copyContents(material_orig, FALSE);
+ sceneroot->addChild(material_copy);
+
+ SoCoordinate3 * coordinates_orig =
+ SO_GET_ANY_PART(this, "coordinates", SoCoordinate3);
+ SoCoordinate3 * coordinates_copy = new SoCoordinate3;
+ coordinates_copy->copyContents(coordinates_orig, FALSE);
+ sceneroot->addChild(coordinates_copy);
+
+ SoIndexedFaceSet * facets_orig =
+ SO_GET_ANY_PART(this, "facets", SoIndexedFaceSet);
+ SoIndexedFaceSet * facets_copy = new SoIndexedFaceSet;
+ facets_copy->copyContents(facets_orig, FALSE);
+ sceneroot->addChild(facets_copy);
+
+ // optimize/reorganize mesh
+ SoReorganizeAction ra;
+ ra.apply(sceneroot);
+
+ // FIXME: remove redundant scene graph nodes after scene reorganization
+
+ sceneroot->unrefNoDelete();
+ root = sceneroot;
+ } else {
+ SoDebugError::postWarning("SoSTLFileKit::writeScene",
+ "unsupported format - could not create scene.");
+ success = FALSE;
+ }
+
+ return success;
+}
+
+// doc in inherited class
+SbBool
+SoSTLFileKit::canWriteFile(const char * filename) const
+{
+ return inherited::canWriteFile(filename);
+}
+
+/*!
+ Writes the STL model to an STL file.
+
+ \sa binary, info, canWriteFile, canReadScene
+*/
+
+SbBool
+SoSTLFileKit::writeFile(const char * filename)
+{
+ unsigned int flags = 0;
+ if ( this->binary.getValue() ) {
+ flags |= STL_BINARY;
+ // set up flags for colorization if wanted
+ }
+
+ stl_writer * writer = stl_writer_create(filename, flags);
+ if ( !writer ) {
+ return FALSE;
+ }
+
+ stl_facet * facet = stl_facet_create();
+ assert(facet);
+ stl_writer_set_facet(writer, facet);
+
+ SbString infostring = this->info.getValue();
+ if ( infostring.getLength() > 0 ) {
+ if ( stl_writer_set_info(writer, infostring.getString()) != STL_OK ) {
+ SoDebugError::post("SoSTLFileKit::writeFile",
+ "error: '%s'",
+ stl_writer_get_error(writer));
+ return FALSE;
+ }
+ }
+
+ this->ref();
+ SoCallbackAction cba;
+ cba.addTriangleCallback(SoNode::getClassTypeId(), put_facet_cb, writer);
+ cba.apply(this);
+ this->unrefNoDelete();
+
+ stl_writer_destroy(writer);
+
+ return TRUE;
+}
+
+// *************************************************************************
+
+/*!
+ Resets the STL model so it contains nothing.
+*/
+
+void
+SoSTLFileKit::reset(void)
+{
+ PRIVATE(this)->numvertices = 0;
+ PRIVATE(this)->numfacets = 0;
+ PRIVATE(this)->numnormals = 0;
+ PRIVATE(this)->numsharedvertices = 0;
+ PRIVATE(this)->numsharednormals = 0;
+ PRIVATE(this)->numredundantfacets = 0;
+
+ PRIVATE(this)->data->truncate(0);
+ PRIVATE(this)->points->clear();
+ PRIVATE(this)->normals->clear();
+
+ this->setAnyPart("shapehints", new SoShapeHints);
+ this->setAnyPart("texture", new SoTexture2);
+ this->setAnyPart("normalbinding", new SoNormalBinding);
+ this->setAnyPart("normals", new SoNormal);
+ this->setAnyPart("materialbinding", new SoMaterialBinding);
+ this->setAnyPart("material", new SoMaterial);
+ this->setAnyPart("coordinates", new SoCoordinate3);
+ this->setAnyPart("facets", new SoIndexedFaceSet);
+
+ SoNormalBinding * normalbinding =
+ SO_GET_ANY_PART(this, "normalbinding", SoNormalBinding);
+ normalbinding->value = SoNormalBinding::PER_FACE_INDEXED;
+
+ SoShapeHints * shapehints =
+ SO_GET_ANY_PART(this, "shapehints", SoShapeHints);
+ shapehints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
+ // proper model is
+ // shapehints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
+ // but many models are not proper
+ shapehints->shapeType = SoShapeHints::SOLID;
+}
+
+/*!
+ Adds one triangle to the STL model.
+
+ \sa reset, organizeModel
+*/
+
+SbBool
+SoSTLFileKit::addFacet(const SbVec3f & v1, const SbVec3f & v2, const SbVec3f & v3, const SbVec3f & n)
+{
+ SoNormal * normals =
+ SO_GET_ANY_PART(this, "normals", SoNormal);
+ SoCoordinate3 * coordinates =
+ SO_GET_ANY_PART(this, "coordinates", SoCoordinate3);
+ SoIndexedFaceSet * facets =
+ SO_GET_ANY_PART(this, "facets", SoIndexedFaceSet);
+
+ // find existing indexes if any
+ long v1idx = PRIVATE(this)->points->findPoint(v1), v1new = (v1idx == -1);
+ long v2idx = PRIVATE(this)->points->findPoint(v2), v2new = (v2idx == -1);
+ long v3idx = PRIVATE(this)->points->findPoint(v3), v3new = (v3idx == -1);
+ if (!v1new) { v1idx = (long) PRIVATE(this)->points->getUserData(v1idx); }
+ if (!v2new) { v2idx = (long) PRIVATE(this)->points->getUserData(v2idx); }
+ if (!v3new) { v3idx = (long) PRIVATE(this)->points->getUserData(v3idx); }
+ long nidx = PRIVATE(this)->normals->findPoint(n);
+ if (nidx != -1) { nidx = (long) PRIVATE(this)->normals->getUserData(nidx); }
+
+ // toss out invalid facets - facets where two or more points are in
+ // the same location. what are these - are they lines and points or
+ // something? selection? borders? creases?
+ if ((!v1new && !v2new && (v1idx == v2idx)) ||
+ (!v1new && !v3new && (v1idx == v3idx)) ||
+ (!v2new && !v3new && (v2idx == v3idx)) ||
+ (v1new && v2new && (v1 == v2)) ||
+ (v1new && v3new && (v1 == v3)) ||
+ (v2new && v3new && (v2 == v3))) {
+ // the above test is optimized for using vertex indexes if
+ // possible and avoid vec3f-comparisons when index-comparisons
+ // should have sufficed.
+ PRIVATE(this)->numredundantfacets += 1;
+ return FALSE;
+ }
+
+#if 0 // disabled (O(n^2))
+ // toss out redundant facets, if any...
+ if (!v1new && !v2new && !v3new) {
+ int count = facets->coordIndex.getNum();
+ const int32_t * points = facets->coordIndex.getValues(0);
+ int i;
+ for (i = 0; i < count; i++) {
+ if (points[i] == v1idx) {
+ int beg = i - (i % 4);
+ if ( ((points[beg] == v1idx) && (points[beg+1] == v2idx) &&
+ (points[beg+2] == v3idx)) ||
+ ((points[beg] == v2idx) && (points[beg+1] == v3idx) &&
+ (points[beg+2] == v1idx)) ||
+ ((points[beg] == v3idx) && (points[beg+1] == v1idx) &&
+ (points[beg+2] == v2idx)) ) {
+ // same vertices, same vertex ordering (we drop comparing normal)
+ PRIVATE(this)->numredundantfacets += 1;
+ return FALSE;
+ }
+ }
+ }
+ }
+#endif
+
+ // add facet (triangle) to faceset
+ if (v1new) {
+ v1idx = PRIVATE(this)->numvertices;
+ coordinates->point.set1Value(v1idx, v1);
+ PRIVATE(this)->points->addPoint(v1, (void *) v1idx);
+ PRIVATE(this)->numvertices++;
+ } else {
+ PRIVATE(this)->numsharedvertices++;
+ }
+ facets->coordIndex.set1Value(PRIVATE(this)->numfacets*4, v1idx);
+
+ if (v2new) {
+ v2idx = PRIVATE(this)->numvertices;
+ coordinates->point.set1Value(v2idx, v2);
+ PRIVATE(this)->points->addPoint(v2, (void *) v2idx);
+ PRIVATE(this)->numvertices++;
+ } else {
+ PRIVATE(this)->numsharedvertices++;
+ }
+ facets->coordIndex.set1Value(PRIVATE(this)->numfacets*4+1, v2idx);
+
+ if (v3new) {
+ v3idx = PRIVATE(this)->numvertices;
+ coordinates->point.set1Value(v3idx, v3);
+ PRIVATE(this)->points->addPoint(v3, (void *) v3idx);
+ PRIVATE(this)->numvertices++;
+ } else {
+ PRIVATE(this)->numsharedvertices++;
+ }
+ facets->coordIndex.set1Value(PRIVATE(this)->numfacets*4+2, v3idx);
+ facets->coordIndex.set1Value(PRIVATE(this)->numfacets*4+3, -1);
+
+ if (nidx == -1) {
+ nidx = PRIVATE(this)->numnormals;
+ normals->vector.set1Value(nidx, n);
+ PRIVATE(this)->normals->addPoint(n, (void *) nidx);
+ PRIVATE(this)->numnormals++;
+ } else {
+ PRIVATE(this)->numsharednormals++;
+ }
+ facets->normalIndex.set1Value(PRIVATE(this)->numfacets, nidx);
+
+ PRIVATE(this)->numfacets++;
+ return TRUE;
+}
+
+/*!
+ Should be called after the STL model is completely set up in the
+ SoSTLFileKit through import from a file or from a scene graph. The
+ model will then be optimized for fast rendering.
+
+ \sa addFacet, reset
+*/
+
+void
+SoSTLFileKit::organizeModel(void)
+{
+#if defined(COIN_EXTRA_DEBUG)
+ SoDebugError::postInfo("SoSTLFileKit::organizeModel",
+ "model data imported successfully. "
+ "%d unique vertices, %d reuses. "
+ "%d unique normals, %d reuses. "
+ "%d facets, %d redundant facets.",
+ PRIVATE(this)->numvertices,
+ PRIVATE(this)->numsharedvertices,
+ PRIVATE(this)->numnormals,
+ PRIVATE(this)->numsharednormals,
+ PRIVATE(this)->numfacets,
+ PRIVATE(this)->numredundantfacets);
+#endif // COIN_EXTRA_DEBUG
+
+ SoIndexedFaceSet * facets =
+ SO_GET_ANY_PART(this, "facets", SoIndexedFaceSet);
+
+ assert(facets->coordIndex.getNum() == PRIVATE(this)->numfacets*4);
+ assert(facets->normalIndex.getNum() == (PRIVATE(this)->numfacets));
+
+ if ( PRIVATE(this)->numfacets > 300 ) {
+ // FIXME: at some number of facets, reorganization for faster
+ // rendering should really be performed.
+ }
+}
+
+/*!
+ Helper callback for readScene(), calling addFacet() for each
+ triangle in the provided scene graph.
+
+ \sa readScene
+*/
+
+void
+SoSTLFileKit::add_facet_cb(void * closure,
+ SoCallbackAction * action,
+ const SoPrimitiveVertex * v1,
+ const SoPrimitiveVertex * v2,
+ const SoPrimitiveVertex * v3)
+{
+ assert(closure); assert(v1); assert(v2); assert(v3);
+ SoSTLFileKit * filekit = (SoSTLFileKit *) closure;
+
+ SbVec3f vertex1(v1->getPoint());
+ SbVec3f vertex2(v2->getPoint());
+ SbVec3f vertex3(v3->getPoint());
+
+ SbVec3f vec1(vertex2-vertex1);
+ SbVec3f vec2(vertex3-vertex1);
+ SbVec3f normal(vec1.cross(vec2));
+ float len = normal.length();
+ if ( len > 0.0f && len != 1.0f ) normal /= len;
+ assert(len != 0.0f);
+
+ filekit->addFacet(vertex1, vertex2, vertex3, normal);
+}
+
+/*!
+ Helper callback for writeFile(), writing each triangle in the STL
+ model to the STL file.
+
+ \sa writeFile
+*/
+
+void
+SoSTLFileKit::put_facet_cb(void * closure,
+ SoCallbackAction * action,
+ const SoPrimitiveVertex * v1,
+ const SoPrimitiveVertex * v2,
+ const SoPrimitiveVertex * v3)
+{
+ assert(closure); assert(v1); assert(v2); assert(v3);
+ stl_writer * writer = (stl_writer *) closure;
+
+ SbVec3f vertex1(v1->getPoint());
+ SbVec3f vertex2(v2->getPoint());
+ SbVec3f vertex3(v3->getPoint());
+
+ SbVec3f vec1(vertex2-vertex1);
+ SbVec3f vec2(vertex3-vertex1);
+ SbVec3f normal(vec1.cross(vec2));
+ float len = normal.length();
+ if ( len > 0 ) normal /= len;
+
+ stl_facet * facet = stl_writer_get_facet(writer);
+ assert(facet);
+ stl_facet_set_vertex1(facet, vertex1[0], vertex1[1], vertex1[2]);
+ stl_facet_set_vertex2(facet, vertex2[0], vertex2[1], vertex2[2]);
+ stl_facet_set_vertex3(facet, vertex3[0], vertex3[1], vertex3[2]);
+ stl_facet_set_normal(facet, normal[0], normal[1], normal[2]);
+ stl_facet_set_padding(facet, 0);
+
+ stl_writer_put_facet(writer, facet);
+}
+
+#undef PRIVATE
+#endif // HAVE_NODEKITS
diff --git a/src/threads/thread.cpp b/src/threads/thread.cpp
index 1111111..2222222 100644
--- a/src/threads/thread.cpp
+++ b/src/threads/thread.cpp
@@ -120,7 +120,7 @@ cc_thread_join(cc_thread * thread,
void
cc_sleep(float seconds)
{
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__MINGW32__)
/* FIXME: 20011107, thammer: create a configure macro to detect
* which sleep function is available */
sleep(floor(seconds));
@@ -154,7 +154,7 @@ cc_thread_id(void)
assert(0 && "unexpected failure");
}
}
- return (unsigned long) val;
+ return static_cast<unsigned long>(reinterpret_cast<intptr_t>(val));
}
static void
diff --git a/src/threads/thread.cpp.orig b/src/threads/thread.cpp.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/src/threads/thread.cpp.orig
@@ -0,0 +1,347 @@
+/**************************************************************************\
+ *
+ * This file is part of the Coin 3D visualization library.
+ * Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * ("GPL") version 2 as published by the Free Software Foundation.
+ * See the file LICENSE.GPL at the root directory of this source
+ * distribution for additional information about the GNU GPL.
+ *
+ * For using Coin with software that can not be combined with the GNU
+ * GPL, and for taking advantage of the additional benefits of our
+ * support services, please contact Kongsberg Oil & Gas Technologies
+ * about acquiring a Coin Professional Edition License.
+ *
+ * See http://www.coin3d.org/ for more information.
+ *
+ * Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ * http://www.sim.no/ sales@sim.no coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+#include <Inventor/C/threads/thread.h>
+
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <Inventor/C/errors/debugerror.h>
+
+#include "threads/threadp.h"
+#include "threads/mutexp.h"
+#include "threads/recmutexp.h"
+#include "threads/syncp.h"
+#include "tidbitsp.h"
+
+
+/* ********************************************************************** */
+
+/*
+ FIXME:
+ - copy struct malloc/free/init/clean setup scheme from cc_string
+ - use static table of cc_thread structures?
+ - use cc_storage to reference self-structure for cc_thread_get_self()?
+*/
+
+/* ********************************************************************** */
+
+#ifdef USE_PTHREAD
+#include "threads/thread_pthread.icc"
+#endif /* USE_PTHREAD */
+
+#ifdef USE_W32THREAD
+#include "threads/thread_win32.icc"
+#endif /* USE_W32THREAD */
+
+/*
+*/
+
+cc_thread *
+cc_thread_construct(cc_thread_f * func, void * closure)
+{
+ cc_thread * thread;
+ int ok;
+
+ thread = (cc_thread*) malloc(sizeof(cc_thread));
+ assert(thread != NULL);
+ thread->func = func;
+ thread->closure = closure;
+
+ ok = internal_init(thread);
+ if (ok) return thread;
+ assert(0 && "unable to create thread");
+ free(thread);
+ return NULL;
+}
+
+/* ********************************************************************** */
+
+/*
+*/
+
+void
+cc_thread_destruct(cc_thread * thread)
+{
+ int ok;
+ assert(thread != NULL);
+ ok = internal_clean(thread);
+ assert(ok == CC_OK);
+ free(thread);
+}
+
+/* ********************************************************************** */
+
+/*
+*/
+
+int
+cc_thread_join(cc_thread * thread,
+ void ** retvalptr)
+{
+ int ok;
+ assert(thread != NULL);
+
+ ok = internal_join(thread, retvalptr);
+ assert(ok == CC_OK);
+ return ok;
+}
+
+/* ********************************************************************** */
+
+void
+cc_sleep(float seconds)
+{
+#ifndef _WIN32
+ /* FIXME: 20011107, thammer: create a configure macro to detect
+ * which sleep function is available */
+ sleep(floor(seconds));
+#else
+ Sleep((int)(seconds*1000.0));
+#endif
+};
+
+#ifdef USE_PTHREAD
+unsigned long
+cc_thread_id(void)
+{
+ return (unsigned long) pthread_self();
+}
+#endif /* USE_PTHREAD */
+
+#ifdef USE_W32THREAD
+
+static DWORD win32_threadid_idx;
+
+unsigned long
+cc_thread_id(void)
+{
+ static unsigned long currentidx = 1;
+ LPVOID val = TlsGetValue(win32_threadid_idx);
+ if (val == 0) { /* not set yet */
+ cc_mutex_global_lock();
+ val = (LPVOID) currentidx++;
+ cc_mutex_global_unlock();
+ if (!TlsSetValue(win32_threadid_idx, (LPVOID)val)) {
+ assert(0 && "unexpected failure");
+ }
+ }
+ return (unsigned long) val;
+}
+
+static void
+win32_threadid_idx_cleanup(void)
+{
+ TlsFree(win32_threadid_idx);
+}
+
+#endif /* USE_WIN32THREAD */
+
+
+void
+cc_thread_init(void)
+{
+ cc_mutex_init();
+ cc_sync_init();
+#ifdef USE_W32THREAD
+ /* needed to quickly generate a thread-id for each thread */
+ win32_threadid_idx = TlsAlloc();
+ assert(win32_threadid_idx != TLS_OUT_OF_INDEXES);
+ /* clean-up priority for the thread sub-system in Coin is set so it
+ is done very late at exit */
+ /* FIXME: not sure if this really needs the "- 2", but I added it
+ to keep the same order wrt the other thread-related clean-up
+ functions, since before I changed hard-coded numbers for
+ enumerated values for coin_atexit() invocations. 20060301 mortene. */
+ coin_atexit(win32_threadid_idx_cleanup, CC_ATEXIT_THREADING_SUBSYSTEM_VERYLOWPRIORITY);
+#endif /* USE_WIN32THREAD */
+ cc_recmutex_init();
+}
+
+/* ********************************************************************** */
+
+/* maybe use static table of thread structures, reference counted, to be
+ able to implement something like this, if needed */
+/* cc_thread * cc_thread_get_self(void); */
+
+/* ********************************************************************** */
+
+/*
+ * We don't really want to expose internal id types, which would mean we
+ * must include threads-implementation-specific headers in the header files.
+ * It's therefore better to implement the missing/needed functionality for
+ * the cc_thread type, so id peeking won't be necessary.
+ */
+
+/* <id> cc_thread_get_id(cc_thread * thread); */
+/* <id> cc_thread_get_current_id(void); */
+
+/* ********************************************************************** */
+
+/*!
+ \page multithreading_support Multithreading Support in Coin
+
+ The support in Coin for using multiple threads in application
+ programs and the Coin library itself, consists of two main features:
+
+ <ul>
+
+ <li>
+ Coin provides platform-independent thread-handling abstraction
+ classes. These are classes that the application programmer can
+ freely use in her application code to start new threads, control
+ their execution, work with mutexes and do other tasks related to
+ handling multiple threads.
+
+ The classes in question are SbThread, SbMutex, SbStorage, SbBarrier,
+ SbCondVar, SbFifo, SbThreadAutoLock, SbRWMutex, and
+ SbTypedStorage. See their respective documentation for the detailed
+ information.
+
+ The classes fully hides the system-specific implementation, which is
+ either done on top of native Win32 (if on Microsoft Windows), or
+ over POSIX threads (on UNIX and UNIX-like systems).
+ </li>
+
+ <li>
+ The other aspect of our multi-threading support is that Coin can be
+ specially configured so that rendering traversals of the scene graph
+ are done in a thread-safe manner. This means e.g. that it is
+ possible to have Coin render the scene in parallel on multiple CPUs
+ for multiple rendering pipes, to better take advantage of such
+ high-end systems (like CAVE environments, for instance).
+
+ Thread-safe render traversals are \e off by default, because there
+ is a small overhead involved which would make rendering (very)
+ slightly slower on single-threaded invocations.
+
+ To get a Coin library built with thread-safe rendering, one must
+ actively re-configure Coin and build a special, local version. For
+ configure-based builds (UNIX and UNIX-like systems, or with Cygwin
+ on Microsoft Windows) this is done with the option
+ "--enable-threadsafe" to Autoconf configure. For how to change the
+ configuration and re-build with Visual Studio, get in touch with us
+ at "coin-support@coin3d.org".
+ </li>
+
+ </ul>
+
+ There are some restrictions and other issues which it is important
+ to be aware of:
+
+ <ul>
+
+ <li> We do not yet provide any support for binding the
+ multi-threaded rendering support into the SoQt / SoWin / etc GUI
+ bindings, and neither do we provide bindings against any specific
+ library that handles multi-pipe rendering. This means the
+ application programmer will have to possess some expertise, and put
+ in some effort, to be able to utilize multi-pipe rendering with
+ Coin. </li>
+
+ <li> Rendering traversals is currently the only operation which we
+ publicly support to be thread-safe. There are other aspects of Coin
+ that we know are thread-safe, like most other action traversals
+ beside just rendering, but we make no guarantees in this
+ regard. </li>
+
+ <li> Be careful about using a separate thread for changing Coin
+ structures versus what is used for the application's GUI event
+ thread.
+
+ We are aware of at least issues with Qt (and thereby SoQt), where
+ you should not modify the scene graph in any way in a thread
+ separate from the main Qt thread. This because it will trigger
+ operations where Qt is not thread-safe. </li>
+
+ </ul>
+
+ \since Coin 2.0
+*/
+
+/* ********************************************************************** */
+
+/*!
+ \class SbThread Inventor/threads/SbThread.h
+ \brief A class for managing threads.
+ \ingroup threads
+
+ This class provides a portable framework around the tasks of
+ instantiating, starting, stopping and joining threads.
+
+ It wraps the underlying native thread-handling toolkit in a
+ transparent manner, to make multiplatform threads programming
+ straightforward for the application programmer.
+*/
+
+/*!
+ \fn static SbThread * SbThread::create(void *(*func)(void *), void * closure)
+
+ This function creates a new thread, or returns NULL on failure.
+*/
+
+/*!
+ \fn static void SbThread::destroy(SbThread * thread)
+
+ This function destroys a thread.
+*/
+
+/*!
+ \fn static int SbThread::join(SbThread * thread, void ** retval)
+
+ This function waits on the death of the given thread, returning the thread's
+ return value at the location pointed to by \c retval.
+*/
+
+/*!
+ \fn int SbThread::join(void ** retval)
+
+ This function waits on the death of the given thread, returning the thread's
+ return value at the location pointed to by \c retval.
+*/
+
+/*!
+ \fn SbThread::SbThread(cc_thread * thread)
+
+ Protected constructor handling the internal thread ADT.
+
+ \sa SbThread::create
+*/
+
+/*!
+ \fn SbThread::~SbThread(void)
+
+ Destructor.
+
+ \sa SbThread::destroy
+*/
+
+/* ********************************************************************** */
diff --git a/src/threads/thread_win32.icc b/src/threads/thread_win32.icc
index 1111111..2222222 100644
--- a/src/threads/thread_win32.icc
+++ b/src/threads/thread_win32.icc
@@ -29,7 +29,7 @@ static DWORD WINAPI
cc_w32thread_thread_proc(LPVOID lpParameter)
{
cc_thread *thread = (cc_thread *)lpParameter;
- return (DWORD) thread->func(thread->closure);
+ return static_cast<DWORD>(reinterpret_cast<intptr_t>(thread->func(thread->closure)));
}
static int
diff --git a/src/threads/thread_win32.icc.orig b/src/threads/thread_win32.icc.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/src/threads/thread_win32.icc.orig
@@ -0,0 +1,110 @@
+/**************************************************************************\
+ *
+ * This file is part of the Coin 3D visualization library.
+ * Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * ("GPL") version 2 as published by the Free Software Foundation.
+ * See the file LICENSE.GPL at the root directory of this source
+ * distribution for additional information about the GNU GPL.
+ *
+ * For using Coin with software that can not be combined with the GNU
+ * GPL, and for taking advantage of the additional benefits of our
+ * support services, please contact Kongsberg Oil & Gas Technologies
+ * about acquiring a Coin Professional Edition License.
+ *
+ * See http://www.coin3d.org/ for more information.
+ *
+ * Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ * http://www.sim.no/ sales@sim.no coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+/* this file should only be included from thread.c */
+
+#include "glue/win32api.h"
+
+static DWORD WINAPI
+cc_w32thread_thread_proc(LPVOID lpParameter)
+{
+ cc_thread *thread = (cc_thread *)lpParameter;
+ return (DWORD) thread->func(thread->closure);
+}
+
+static int
+internal_init(cc_thread * thread)
+{
+ DWORD threadid_unused;
+
+ thread->w32thread.threadhandle = CreateThread(NULL, 0,
+ cc_w32thread_thread_proc, (LPVOID) thread, 0, &threadid_unused);
+
+ /* threadid_unused - see PlatformSDK doc. for CreateThread */
+
+ /* FIXME: thammer 20011108, check PlatformSDK doc for
+ * _beginthreadex, _endthreadex, and note about using these with
+ * LIBCMT.LIB "A thread that uses functions from the C run-time
+ * libraries should use the beginthread and endthread C run-time
+ * functions for thread management rather than CreateThread and
+ * ExitThread. Failure to do so results in small memory leaks when
+ * ExitThread is called. " */
+
+ if (thread->w32thread.threadhandle == NULL) {
+ if (COIN_DEBUG) {
+ cc_win32_print_error("internal_init", "CreateThread()", GetLastError());
+ }
+ return CC_ERROR;
+ }
+ return CC_OK;
+}
+
+static int
+internal_clean(cc_thread * thread_struct)
+{
+ /* FIXME: Is there really nothing to do here? pederb, 2001-12-10 */
+ return CC_OK;
+}
+
+static int
+internal_join(cc_thread * thread,
+ void ** retvalptr)
+{
+ DWORD status;
+ BOOL bstatus;
+ DWORD exitcode;
+
+ status = WaitForSingleObject(thread->w32thread.threadhandle, INFINITE);
+ if (status == WAIT_FAILED) {
+ if (COIN_DEBUG) {
+ cc_win32_print_error("internal_join", "WaitForSingleObject()",
+ GetLastError());
+ }
+ return CC_ERROR;
+ }
+ else if (status != WAIT_OBJECT_0) {
+ if (COIN_DEBUG) {
+ cc_debugerror_post("internal_join",
+ "WaitForSingleObject() - unknown return value: %d\n",
+ status);
+ }
+ return CC_ERROR;
+ }
+ bstatus = GetExitCodeThread(thread->w32thread.threadhandle, &exitcode);
+ if (bstatus == FALSE) {
+ if (COIN_DEBUG) {
+ cc_win32_print_error("internal_join", "GetExitCodeThread()",
+ GetLastError());
+ }
+ }
+ else if (retvalptr) {
+ *retvalptr = (void *)exitcode;
+ }
+ /* termination could be forced with TerminateThread() - but this
+ * will result in memory leaks - or bigger problems - see Platform
+ * SDK doc. */
+ CloseHandle(thread->w32thread.threadhandle);
+ thread->w32thread.threadhandle = NULL;
+
+ return bstatus ? CC_OK : CC_ERROR;
+}
diff --git a/src/vrml97/JS_VRMLClasses.cpp b/src/vrml97/JS_VRMLClasses.cpp
index 1111111..2222222 100644
--- a/src/vrml97/JS_VRMLClasses.cpp
+++ b/src/vrml97/JS_VRMLClasses.cpp
@@ -100,8 +100,11 @@ struct CoinVrmlJs {
struct CoinVrmlJs_SensorInfo {
SbList <JSObject *> objects;
};
+#if defined(_WIN64)
+SbHash <void *, unsigned long long> * CoinVrmlJs_sensorinfohash = NULL;
+#else
SbHash <void *, unsigned long> * CoinVrmlJs_sensorinfohash = NULL;
-
+#endif
const char * CoinVrmlJs_SFColorAliases[] = {"r", "g", "b"};
const char * CoinVrmlJs_SFRotationAliases[] = {"x", "y", "z", "angle"};
@@ -664,7 +667,11 @@ static void SFNode_deleteCB(void * data, SoSensor * sensor)
{
SoNode * node = ((SoNodeSensor *) sensor)->getAttachedNode();
void * tmp;
+#if defined(_WIN64)
+ if(!CoinVrmlJs_sensorinfohash->get((unsigned long long) node, tmp)) {
+#else
if(!CoinVrmlJs_sensorinfohash->get((unsigned long) node, tmp)) {
+#endif
assert(FALSE && "Trying to delete an unregistered SoNodeSensor. Internal error.");
return;
}
@@ -680,7 +687,11 @@ static void SFNode_deleteCB(void * data, SoSensor * sensor)
// Store the sensor-pointer so that it can be properly deleted later
nodesensorstobedeleted->append((SoNodeSensor *) sensor);
+#if defined(_WIN64)
+ CoinVrmlJs_sensorinfohash->remove((unsigned long long) node);
+#else
CoinVrmlJs_sensorinfohash->remove((unsigned long) node);
+#endif
delete si;
}
@@ -1418,13 +1429,21 @@ static void attachSensorToNode(SoNode * node, JSObject * obj)
{
// Has the hash-table been initialized?
if (!CoinVrmlJs_sensorinfohash) {
+#if defined(_WIN64)
+ CoinVrmlJs_sensorinfohash = new SbHash <void *, unsigned long long>;
+#else
CoinVrmlJs_sensorinfohash = new SbHash <void *, unsigned long>;
+#endif
coin_atexit(deleteSensorInfoHash, CC_ATEXIT_NORMAL);
}
// Is a sensor already attached to this SoNode?
void * tmp;
+#if defined(_WIN64)
+ if (CoinVrmlJs_sensorinfohash->get((unsigned long long) node, tmp)) {
+#else
if (CoinVrmlJs_sensorinfohash->get((unsigned long) node, tmp)) {
+#endif
CoinVrmlJs_SensorInfo * si = (CoinVrmlJs_SensorInfo *) tmp;
si->objects.append(obj);
}
@@ -1434,7 +1453,11 @@ static void attachSensorToNode(SoNode * node, JSObject * obj)
ns->attach(node);
CoinVrmlJs_SensorInfo * si = new CoinVrmlJs_SensorInfo;
si->objects.append(obj);
+#if defined(_WIN64)
+ CoinVrmlJs_sensorinfohash->put((unsigned long long) node, si);
+#else
CoinVrmlJs_sensorinfohash->put((unsigned long) node, si);
+#endif
}
}
diff --git a/src/vrml97/JS_VRMLClasses.cpp.orig b/src/vrml97/JS_VRMLClasses.cpp.orig
new file mode 100644
index 1111111..2222222
--- /dev/null
+++ b/src/vrml97/JS_VRMLClasses.cpp.orig
@@ -0,0 +1,2099 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#ifdef HAVE_VRML97
+
+/**************************************************************************\
+ *
+ * This file is part of the Coin 3D visualization library.
+ * Copyright (C) by Kongsberg Oil & Gas Technologies.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * ("GPL") version 2 as published by the Free Software Foundation.
+ * See the file LICENSE.GPL at the root directory of this source
+ * distribution for additional information about the GNU GPL.
+ *
+ * For using Coin with software that can not be combined with the GNU
+ * GPL, and for taking advantage of the additional benefits of our
+ * support services, please contact Kongsberg Oil & Gas Technologies
+ * about acquiring a Coin Professional Edition License.
+ *
+ * See http://www.coin3d.org/ for more information.
+ *
+ * Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
+ * http://www.sim.no/ sales@sim.no coin-support@coin3d.org
+ *
+\**************************************************************************/
+
+#include "JS_VRMLClasses.h"
+
+#include <Inventor/actions/SoWriteAction.h>
+#include <Inventor/misc/SoJavaScriptEngine.h>
+#include <Inventor/C/glue/spidermonkey.h>
+#include <Inventor/fields/SoSFBool.h>
+#include <Inventor/fields/SoSFInt32.h>
+#include <Inventor/fields/SoSFEnum.h>
+#include <Inventor/fields/SoSFFloat.h>
+#include <Inventor/fields/SoSFString.h>
+#include <Inventor/fields/SoSFTime.h>
+#include <Inventor/fields/SoSFColor.h>
+#include <Inventor/fields/SoSFNode.h>
+#include <Inventor/fields/SoSFImage.h>
+#include <Inventor/fields/SoSFVec2f.h>
+#include <Inventor/fields/SoSFVec3f.h>
+#include <Inventor/fields/SoSFVec3d.h>
+#include <Inventor/fields/SoSFRotation.h>
+#include <Inventor/fields/SoMFInt32.h>
+#include <Inventor/fields/SoMFFloat.h>
+#include <Inventor/fields/SoMFString.h>
+#include <Inventor/fields/SoMFTime.h>
+#include <Inventor/fields/SoMFColor.h>
+#include <Inventor/fields/SoMFNode.h>
+#include <Inventor/fields/SoMFVec2f.h>
+#include <Inventor/fields/SoMFVec3f.h>
+#include <Inventor/fields/SoMFVec3d.h>
+#include <Inventor/fields/SoMFRotation.h>
+#include <Inventor/nodes/SoGroup.h>
+#include <Inventor/nodes/SoSeparator.h>
+#include <Inventor/SoDB.h>
+#include <Inventor/SoInput.h>
+#include <Inventor/SoOutput.h>
+#include <Inventor/VRMLnodes/SoVRMLGroup.h>
+#include <Inventor/errors/SoDebugError.h>
+#include <Inventor/sensors/SoNodeSensor.h>
+
+#include "misc/SbHash.h"
+
+// FIXME: toString() missing for all classes
+
+// "namespace" for all vrml classes
+struct CoinVrmlJs {
+ struct ClassDescriptor {
+ JSClass cls;
+ JSFunctionSpec * functions;
+
+ };
+
+ static ClassDescriptor SFColor;
+ static ClassDescriptor SFNode;
+ static ClassDescriptor SFRotation;
+ static ClassDescriptor SFVec2f;
+ static ClassDescriptor SFVec3f;
+ static ClassDescriptor SFVec3d;
+
+ static ClassDescriptor MFColor;
+ static ClassDescriptor MFFloat;
+ static ClassDescriptor MFInt32;
+ static ClassDescriptor MFNode;
+ static ClassDescriptor MFRotation;
+ static ClassDescriptor MFString;
+ static ClassDescriptor MFTime;
+ static ClassDescriptor MFVec2f;
+ static ClassDescriptor MFVec3f;
+ static ClassDescriptor MFVec3d;
+};
+
+// Struct and SbHash for keeping track of SoNodeSensors for recycling
+// purposes.
+struct CoinVrmlJs_SensorInfo {
+ SbList <JSObject *> objects;
+};
+SbHash <void *, unsigned long> * CoinVrmlJs_sensorinfohash = NULL;
+
+
+const char * CoinVrmlJs_SFColorAliases[] = {"r", "g", "b"};
+const char * CoinVrmlJs_SFRotationAliases[] = {"x", "y", "z", "angle"};
+float CoinVrmlJs_SFdefaultValues[] = {0.0, 0.0, 0.0, 0.0};
+double CoinVrmlJs_SFdefaultValuesDouble[] = {0.0, 0.0, 0.0, 0.0};
+float CoinVrmlJs_SFRotationDefaultValues[] = {0.0, 1.0, 0.0, 0.0};
+
+// Macros for instance checking
+#define JSVAL_IS_SFVEC2F(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFVec2f.cls, NULL))
+#define JSVAL_IS_SFVEC3F(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFVec3f.cls, NULL))
+#define JSVAL_IS_SFVEC3D(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFVec3d.cls, NULL))
+#define JSVAL_IS_SFCOLOR(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFColor.cls, NULL))
+#define JSVAL_IS_SFROTATION(cx, jsval) (JSVAL_IS_OBJECT(jsval) && spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(jsval), &CoinVrmlJs::SFRotation.cls, NULL))
+
+// Handlers
+#define SFColorHandler CoinVrmlJsSFHandler<SbColor, 3, CoinVrmlJs_SFColorAliases, float, CoinVrmlJs_SFdefaultValues>
+#define SFRotationHandler CoinVrmlJsSFHandler<SbVec4f, 4, CoinVrmlJs_SFRotationAliases, float, CoinVrmlJs_SFRotationDefaultValues>
+#define SFVec2fHandler CoinVrmlJsSFHandler<SbVec2f, 2, CoinVrmlJs_SFRotationAliases, float, CoinVrmlJs_SFdefaultValues>
+#define SFVec3fHandler CoinVrmlJsSFHandler<SbVec3f, 3, CoinVrmlJs_SFRotationAliases, float, CoinVrmlJs_SFdefaultValues>
+#define SFVec3dHandler CoinVrmlJsSFHandler<SbVec3d, 3, CoinVrmlJs_SFRotationAliases, double, CoinVrmlJs_SFdefaultValuesDouble>
+
+#define MFColorHandler CoinVrmlJsMFHandler<SoMFColor, SoSFColor, &CoinVrmlJs::MFColor>
+#define MFFloatHandler CoinVrmlJsMFHandler<SoMFFloat, SoSFFloat, &CoinVrmlJs::MFFloat>
+#define MFInt32Handler CoinVrmlJsMFHandler<SoMFInt32, SoSFInt32, &CoinVrmlJs::MFInt32>
+#define MFNodeHandler CoinVrmlJsMFHandler<SoMFNode, SoSFNode, &CoinVrmlJs::MFNode>
+#define MFRotationHandler CoinVrmlJsMFHandler<SoMFRotation, SoSFRotation, &CoinVrmlJs::MFRotation>
+#define MFStringHandler CoinVrmlJsMFHandler<SoMFString, SoSFString, &CoinVrmlJs::MFString>
+#define MFTimeHandler CoinVrmlJsMFHandler<SoMFTime, SoSFTime, &CoinVrmlJs::MFTime>
+#define MFVec2fHandler CoinVrmlJsMFHandler<SoMFVec2f, SoSFVec2f, &CoinVrmlJs::MFVec2f>
+#define MFVec3fHandler CoinVrmlJsMFHandler<SoMFVec3f, SoSFVec3f, &CoinVrmlJs::MFVec3f>
+#define MFVec3dHandler CoinVrmlJsMFHandler<SoMFVec3d, SoSFVec3d, &CoinVrmlJs::MFVec3d>
+
+static JSFunctionSpec MFFunctions[] = {
+// {"toString", MF_toString, 0, 0, 0},
+ {NULL, NULL, 0, 0, 0}
+};
+
+static JSBool SFRotationConstructor(JSContext * cx, JSObject * obj,
+ uintN argc, jsval * argv, jsval * rval);
+
+// Factory methods for converting to javascript objects
+static JSObject * SFColorFactory(JSContext * cx, const SbColor & self);
+static JSObject * SFNodeFactory(JSContext * cx, SoNode * container);
+static JSObject * SFRotationFactory(JSContext * cx, const SbRotation & self);
+static JSObject * SFVec2fFactory(JSContext * cx, const SbVec2f & self);
+static JSObject * SFVec3fFactory(JSContext * cx, const SbVec3f & self);
+static JSObject * SFVec3dFactory(JSContext * cx, const SbVec3d & self);
+
+static SbList <JSObject *> * garbagecollectedobjects = NULL;
+static SbList <SoNodeSensor *> * nodesensorstobedeleted = NULL;
+
+// getIndex returns -1 if id is not an alias or in range 0-max
+static JSBool getIndex(JSContext * cx, jsval id, const char * aliases[], int max)
+{
+ int index;
+
+ if (JSVAL_IS_INT(id)) {
+ index = JSVAL_TO_INT(id);
+ if (index < 0 || index >= max) {
+ spidermonkey()->JS_ReportError(cx, "index must be between 0 and %d", max);
+ return -1;
+ }
+ return index;
+ }
+ else {
+ JSString * jsstr = spidermonkey()->JS_ValueToString(cx, id);
+ const char * str = spidermonkey()->JS_GetStringBytes(jsstr);
+
+ for (index=0; index<max; ++index) {
+ if (strcmp(str, aliases[index]) == 0) {
+ return index;
+ }
+ }
+ return -1;
+ }
+}
+
+// *************************************************************************
+// handlers
+bool jsval2int(JSContext *cx, const jsval v, int32_t &value)
+{
+ if (JSVAL_IS_NULL(v)) return false;
+ int32_t tempval;
+ if (!spidermonkey()->JS_ValueToECMAInt32(cx, v, &tempval)) {
+ return false;
+ }
+ value = tempval;
+ return true;
+}
+
+bool jsval2double(JSContext *cx, const jsval v, double &value)
+{
+ if (JSVAL_IS_NULL(v)) return false;
+ double tempval;
+ if (!spidermonkey()->JS_ValueToNumber(cx, v, &tempval)) {
+ return false;
+ }
+ value = tempval;
+ return true;
+}
+
+
+// FIXME: number of aliases must not be lower than max. This may lead to
+// unsafe programming. 20050721 erikgors.
+template <class Base, int max, const char * aliases[], class basetype, basetype defaultValues[]>
+struct CoinVrmlJsSFHandler {
+ static JSBool get(JSContext * cx, JSObject * obj, jsval id, jsval * rval)
+ {
+ int index = getIndex(cx, id, aliases, max);
+ if (index == -1) {
+ return JS_TRUE;
+ }
+
+ Base * data = (Base *)spidermonkey()->JS_GetPrivate(cx, obj);
+ assert(data != NULL);
+ basetype var = (*data)[index];
+ SbBool ok = spidermonkey()->JS_NewDoubleValue(cx, (double)var, rval);
+ assert(ok && "JS_NewDoubleValue failed");
+ return JS_TRUE;
+ }
+
+ static JSBool set(JSContext * cx, JSObject * obj, jsval id, jsval * val)
+ {
+ int index = getIndex(cx, id, aliases, max);
+ if (index == -1) {
+ return JS_FALSE;
+ }
+
+ Base * data = (Base *)spidermonkey()->JS_GetPrivate(cx, obj);
+ assert(data != NULL);
+
+ // FIXME: number may be NaN, PositiveInfinity and NegativeInfinity.
+ // Should be checked for every time we run JS_ValueToNumber.
+ // ie: "blipp" will become NaN. 20050720 erikgors.
+ double number;
+ spidermonkey()->JS_ValueToNumber(cx, *val, &number);
+ (*data)[index] = (basetype)number;
+ return JS_TRUE;
+ }
+
+ static JSBool constructor(JSContext * cx, JSObject * obj,
+ uintN argc, jsval * argv, jsval * rval)
+ {
+ basetype vals[max];
+
+ // convert all arguments to numbers or use defaultValues if missing
+ uint32_t i;
+ for (i=0; i<max; ++i) {
+ vals[i] = defaultValues[i];
+ if (i<argc) {
+ double val;
+ if (spidermonkey()->JS_ValueToNumber(cx, argv[i], &val)) {
+ vals[i] = (basetype)val;
+ }
+ else {
+ spidermonkey()->JS_ReportError(cx, "WARNING: failed converting argument %d "
+ "to a double", i + 1);
+ }
+ }
+ }
+
+ Base * data = new Base(vals);
+ spidermonkey()->JS_SetPrivate(cx, obj, data);
+ *rval = OBJECT_TO_JSVAL(obj);
+ return JS_TRUE;
+ }
+ static void destructor(JSContext * cx, JSObject * obj)
+ {
+ Base * data = (Base *)spidermonkey()->JS_GetPrivate(cx, obj);
+ // FIXME: We cannot assume this since the class object itself is an
+ // instance of this JSClass. kintel 20050804.
+ // assert(data != NULL);
+ delete data;
+ }
+};
+
+template <class MFFieldClass, class SFFieldClass, CoinVrmlJs::ClassDescriptor * desc>
+struct CoinVrmlJsMFHandler {
+ static JSBool constructor(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
+ {
+ jsval * val = new jsval;
+ JSObject * array = spidermonkey()->JS_NewArrayObject(cx, 0, NULL);
+ *val = OBJECT_TO_JSVAL(array);
+ SbBool ok = spidermonkey()->JS_AddRoot(cx, val);
+ assert(ok && "JS_AddRoot failed");
+ spidermonkey()->JS_SetPrivate(cx, obj, val);
+
+ SFFieldClass * field = (SFFieldClass *)SFFieldClass::createInstance();
+ uintN i;
+
+ for (i=0; i<argc; ++i) {
+ if (SoJavaScriptEngine::getEngine(cx)->jsval2field(argv[i], field)) {
+ SbBool ok = spidermonkey()->JS_SetElement(cx, array, i, &argv[i]);
+ assert(ok && "JS_SetElement failed");
+ }
+ else {
+ // FIXME: should we insert a default value? 20050727 erikgors.
+ spidermonkey()->JS_ReportError(cx, "argv %d is of wrong type", i);
+ }
+ }
+ delete field;
+ return JS_TRUE;
+ }
+
+ static void destructor(JSContext * cx, JSObject * obj)
+ {
+ jsval * val = (jsval *)spidermonkey()->JS_GetPrivate(cx, obj);
+ if (val != NULL) {
+ SbBool ok = spidermonkey()->JS_RemoveRoot(cx, val);
+ assert(ok && "JS_RemoveRoot failed");
+ delete val;
+ }
+ }
+
+ static JSObject * init(JSContext * cx, JSObject * obj)
+ {
+ return spidermonkey()->JS_InitClass(cx, obj, NULL, &desc->cls,
+ constructor, 0,
+ NULL, MFFunctions, NULL, NULL);
+ }
+
+ static void resize(JSContext * cx, JSObject * array, uint32_t newLength)
+ {
+ uint32_t length;
+ SbBool ok = spidermonkey()->JS_GetArrayLength(cx, array, &length);
+ assert(ok && "JS_GetArrayLength failed");
+
+ if (length > newLength) {
+ spidermonkey()->JS_SetArrayLength(cx, array, newLength);
+ }
+ else {
+ SoType type = MFFieldClass::getClassTypeId();
+
+ // expand and fill with new objects
+ for (; length<newLength; ++length) {
+ jsval val;
+
+ if (type == SoMFInt32::getClassTypeId() ||
+ type == SoMFFloat::getClassTypeId()) {
+ val = INT_TO_JSVAL(0);
+ }
+ else if (type == SoMFString::getClassTypeId()) {
+ JSString * str = spidermonkey()->JS_NewStringCopyZ(cx, "");
+ val = STRING_TO_JSVAL(str);
+ }
+ else if (type == SoMFNode::getClassTypeId()) {
+ // All elements not explicitly initialized are set to NULL
+ val = JSVAL_VOID;
+ }
+ else if (type == SoMFColor::getClassTypeId()) {
+ JSObject * newObj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFColor.cls, NULL, NULL);
+ assert(newObj != NULL);
+ SFColorHandler::constructor(cx, newObj, 0, NULL, &val);
+ val = OBJECT_TO_JSVAL(newObj);
+ }
+ else if (type == SoMFRotation::getClassTypeId()) {
+ JSObject * newObj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFRotation.cls, NULL, NULL);
+ assert(newObj != NULL);
+ SFRotationConstructor(cx, newObj, 0, NULL, &val);
+ val = OBJECT_TO_JSVAL(newObj);
+ }
+ else if (type == SoMFVec2f::getClassTypeId()) {
+ JSObject * newObj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec2f.cls, NULL, NULL);
+ assert(newObj != NULL);
+ SFVec2fHandler::constructor(cx, newObj, 0, NULL, &val);
+ val = OBJECT_TO_JSVAL(newObj);
+ }
+ else if (type == SoMFVec3f::getClassTypeId()) {
+ JSObject * newObj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec3f.cls, NULL, NULL);
+ assert(newObj != NULL);
+ SFVec3fHandler::constructor(cx, newObj, 0, NULL, &val);
+ val = OBJECT_TO_JSVAL(newObj);
+ }
+ else if (type == SoMFVec3d::getClassTypeId()) {
+ JSObject * newObj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec3d.cls, NULL, NULL);
+ assert(newObj != NULL);
+ SFVec3dHandler::constructor(cx, newObj, 0, NULL, &val);
+ val = OBJECT_TO_JSVAL(newObj);
+ }
+ else {
+ assert(0 && "this should not happen");
+ }
+ SbBool ok = spidermonkey()->JS_SetElement(cx, array, length, &val);
+ assert(ok && "JS_SetElement failed");
+ }
+ }
+ }
+
+ static JSBool get(JSContext * cx, JSObject * obj, jsval id, jsval * rval)
+ {
+
+ jsval * array = (jsval *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (JSVAL_IS_INT(id)) {
+ assert(array != NULL);
+ int index = JSVAL_TO_INT(id);
+ return spidermonkey()->JS_GetElement(cx, JSVAL_TO_OBJECT(*array), index, rval);
+ }
+ else if (JSVAL_IS_STRING(id)) {
+ const char * str = spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id));
+ if (SbName("length") == str) {
+ assert(array != NULL);
+ uint32_t length;
+ SbBool ok = spidermonkey()->JS_GetArrayLength(cx, JSVAL_TO_OBJECT(*array), &length);
+ assert(ok && "JS_GetArrayLength failed");
+ *rval = INT_TO_JSVAL(length);
+ return JS_TRUE;
+ }
+ }
+
+ return JS_TRUE;
+ }
+
+ static JSBool set(JSContext * cx, JSObject * obj, jsval id, jsval * val)
+ {
+ jsval * array = (jsval *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (JSVAL_IS_INT(id)) {
+ int index = JSVAL_TO_INT(id);
+
+ // check for bounds
+ if (index < 0) {
+ return JS_FALSE;
+ }
+
+ // resize if necessary
+ uint32_t length;
+ SbBool ok = spidermonkey()->JS_GetArrayLength(cx, JSVAL_TO_OBJECT(*array), &length);
+ assert(ok && "JS_GetArrayLength failed");
+ if (index >= (int)length) {
+ resize(cx, JSVAL_TO_OBJECT(*array), index+1);
+ }
+
+ SFFieldClass * field = (SFFieldClass *)SFFieldClass::createInstance();
+ // Check if val is not of wrong type
+ if (SoJavaScriptEngine::getEngine(cx)->jsval2field(*val, field)) {
+ // assign it
+ SbBool ok = spidermonkey()->JS_SetElement(cx, JSVAL_TO_OBJECT(*array), index, val);
+ assert(ok && "JS_SetElement failed");
+ return JS_TRUE;
+ }
+ delete field;
+ }
+ else if (JSVAL_IS_STRING(id)) {
+ const char * str = spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id));
+ if (SbName("length") == str) {
+ double number;
+ spidermonkey()->JS_ValueToNumber(cx, *val, &number);
+ if (number < 0) {
+ spidermonkey()->JS_ReportError(cx, "RangeError: invalid array length");
+ }
+ else {
+ resize(cx, JSVAL_TO_OBJECT(*array), (uint32_t)number);
+ }
+ return JS_TRUE;
+ }
+ }
+
+ return JS_FALSE;
+ }
+
+
+ static SbBool jsval2field(JSContext * cx, const jsval v, SoField * f)
+ {
+ if (JSVAL_IS_OBJECT(v) &&
+ spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(v), &desc->cls, NULL)) {
+ JSObject * obj = JSVAL_TO_OBJECT(v);
+ jsval * array = (jsval *)spidermonkey()->JS_GetPrivate(cx, obj);
+ assert(array != NULL);
+
+ jsval element;
+ uint32_t i;
+ uint32_t num;
+ JSBool ok = spidermonkey()->JS_GetArrayLength(cx, JSVAL_TO_OBJECT(*array), &num);
+
+ SFFieldClass * field = (SFFieldClass *)SFFieldClass::createInstance();
+
+ for (i=0; i<num; ++i) {
+ ok = spidermonkey()->JS_GetElement(cx, obj, i, &element);
+ assert(ok);
+
+ ok = SoJavaScriptEngine::getEngine(cx)->jsval2field(element, field);
+ assert(ok && "jsval2field failed");
+ ((MFFieldClass *)f)->set1Value(i, field->getValue());
+ }
+ delete field;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ static void field2jsval(JSContext * cx, const SoField * f, jsval * v)
+ {
+ JSObject * obj = spidermonkey()->JS_NewObject(cx, &desc->cls, NULL, NULL);
+ spidermonkey()->JS_DefineFunctions(cx, obj, desc->functions);
+
+ int num = ((SoMField *)f)->getNum();
+ jsval * vals = new jsval[num];
+
+ MFFieldClass & mf = *(MFFieldClass *)f;
+
+ SFFieldClass * field = (SFFieldClass *)SFFieldClass::createInstance();
+ for (int i=0; i<num; ++i) {
+ field->setValue(mf[i]);
+ SbBool ok = SoJavaScriptEngine::getEngine(cx)->field2jsval(field, &vals[i]);
+ assert(ok && "field2jsval failed");
+ }
+
+ jsval rval;
+ constructor(cx, obj, num, vals, &rval);
+ *v = OBJECT_TO_JSVAL(obj);
+ delete field;
+ delete [] vals;
+ }
+};
+
+// *************************************************************************
+// constructors
+
+static JSBool SFRotationConstructor(JSContext * cx, JSObject * obj,
+ uintN argc, jsval * argv, jsval * rval)
+{
+ if (argc == 2) {
+ if (JSVAL_IS_SFVEC3F(cx, argv[0])) {
+ SbVec3f & vec =
+ *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+
+ SbVec4f * data = new SbVec4f();
+ spidermonkey()->JS_SetPrivate(cx, obj, data);
+ *rval = OBJECT_TO_JSVAL(obj);
+ // new SFRotation(SFVec3f fromVector, SFVec3f toVector)
+ if (JSVAL_IS_SFVEC3F(cx, argv[1])) {
+ SbVec3f & vec2 =
+ *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[1]));
+
+ SbRotation rot(vec, vec2);
+ SbVec3f axis;
+ float rad;
+ rot.getValue(axis, rad);
+
+ data->setValue(axis[0], axis[1], axis[2], rad);
+ return JS_TRUE;
+ }
+ // new SFRotation(SFVec3f axis, numeric angle)
+ else {
+ SbVec4f * data = new SbVec4f();
+ spidermonkey()->JS_SetPrivate(cx, obj, data);
+ *rval = OBJECT_TO_JSVAL(obj);
+
+ double number = 0.0;
+ spidermonkey()->JS_ValueToNumber(cx, argv[1], &number);
+
+ data->setValue(vec[0], vec[1], vec[2], (float)number);
+ return JS_TRUE;
+ }
+ }
+ }
+ // new SFRotation(numeric x, numeric y, numeric z, numeric angle)
+ // Missing values default to 0.0, except y, which defaults to 1.0.
+ //
+ // SbRotation will default to 0.0, 0.0, 1.0, when angle is 0.0
+ // So we use SbVec4f to hold values for SFRotation, since we need to support
+ // patterns like this:
+ // var colors = new MFColor();
+ // colors.length = 10;
+ // colors[0].x = 1
+ // colors[0].y = 0
+ // colors[0].z = 0
+ // colors[0].angle = 1.8
+ //
+ // This will not work when SbRotation holds the values. 20050714 erikgors.
+
+ return SFRotationHandler::constructor(cx, obj, argc, argv, rval);
+}
+
+// *************************************************************************
+// functions
+
+static JSBool SFNode_ref(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ // Check if the JS object has already been garbage collected. This
+ // must be done to prevent a Java script from crashing the
+ // application.
+ if (garbagecollectedobjects->find(obj) != -1) {
+ if (SoJavaScriptEngine::debug())
+ SoDebugError::postInfo("SFNode_ref", "WARNING! Trying to ref a deleted node.");
+ return JSVAL_FALSE;
+ }
+
+ SoNode & node = *(SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+ node.ref();
+ return JSVAL_TRUE;
+}
+
+static JSBool SFNode_unref(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ // Check if the JS object has already been garbage collected. This
+ // must be done to prevent a Java script from crashing the
+ // application.
+ if (garbagecollectedobjects->find(obj) != -1) {
+ if (SoJavaScriptEngine::debug())
+ SoDebugError::postInfo("SFNode_unref", "WARNING! Trying to unref an already deleted node.");
+ return JSVAL_FALSE;
+ }
+
+ SoNode & node = *(SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+ node.unref();
+ return JSVAL_TRUE;
+}
+
+static void *
+buffer_realloc(void * bufptr, size_t size)
+{
+ char *buffer = (char *)realloc(bufptr, size);
+ return buffer;
+}
+
+static JSBool SFNode_toString(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ // Check if the JS object has already been garbage collected. This
+ // must be done to prevent a Java script from crashing the
+ // application.
+ if (garbagecollectedobjects->find(obj) != -1) {
+ if (SoJavaScriptEngine::debug())
+ SoDebugError::postInfo("SFNode_toString", "WARNING! Trying to access "
+ "an already deleted node.");
+ return JSVAL_FALSE;
+ }
+
+ SoNode *node = (SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ SoOutput out;
+ out.setHeaderString("#VRML V2.0 utf8");
+ size_t buffer_size = 1024;
+ void *buffer = (void *)malloc(buffer_size);
+ out.setBuffer(buffer, buffer_size, buffer_realloc);
+
+ SoWriteAction wa(&out);
+ wa.apply(node);
+
+ out.getBuffer(buffer, buffer_size);
+
+ *rval = STRING_TO_JSVAL(spidermonkey()->JS_NewStringCopyZ(cx,
+ (char *)buffer));
+
+ free(buffer);
+
+ return JSVAL_TRUE;
+}
+
+static void SFNode_deleteCB(void * data, SoSensor * sensor)
+{
+ SoNode * node = ((SoNodeSensor *) sensor)->getAttachedNode();
+ void * tmp;
+ if(!CoinVrmlJs_sensorinfohash->get((unsigned long) node, tmp)) {
+ assert(FALSE && "Trying to delete an unregistered SoNodeSensor. Internal error.");
+ return;
+ }
+
+ CoinVrmlJs_SensorInfo * si = (CoinVrmlJs_SensorInfo *) tmp;
+
+ // Delete all JSObjects which were connected to this SoNode
+ while (si->objects.getLength()) {
+ JSObject * obj = si->objects[0];
+ garbagecollectedobjects->append(obj);
+ si->objects.removeFast(0);
+ }
+
+ // Store the sensor-pointer so that it can be properly deleted later
+ nodesensorstobedeleted->append((SoNodeSensor *) sensor);
+ CoinVrmlJs_sensorinfohash->remove((unsigned long) node);
+ delete si;
+}
+
+static void cleanupObsoleteNodeSensors(void)
+{
+ // Delete all SoNodeSensors which no longer have a node attached.
+ while(nodesensorstobedeleted->getLength() > 0) {
+ SoNodeSensor * ns = (SoNodeSensor *) (*nodesensorstobedeleted)[0];
+ nodesensorstobedeleted->removeItem(ns);
+ delete ns;
+ }
+}
+
+static JSBool SFVec2f_add(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec2f & vec1 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC2F(cx, argv[0])) {
+ SbVec2f & vec2 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ SbVec2f result = vec1 + vec2;
+ *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, result));
+ return JS_TRUE;
+ }
+
+ return JS_FALSE;
+}
+
+static JSBool SFVec3f_add(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3f & vec1 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+ SbVec3f & vec2 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ SbVec3f result = vec1 + vec2;
+ *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, result));
+ return JS_TRUE;
+ }
+
+ return JS_FALSE;
+}
+
+static JSBool SFVec3d_add(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3d & vec1 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC3D(cx, argv[0])) {
+ SbVec3d & vec2 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ SbVec3d result = vec1 + vec2;
+ *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, result));
+ return JS_TRUE;
+ }
+
+ return JS_FALSE;
+}
+
+static JSBool SFVec2f_divide(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec2f & vec = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ double number;
+ if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+ SbVec2f newVec = vec / (float)number;
+ *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, newVec));
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec3f_divide(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3f & vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ double number;
+ if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+ SbVec3f newVec = vec / (float)number;
+ *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, newVec));
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec3d_divide(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3d & vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ double number;
+ if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+ SbVec3d newVec = vec / number;
+ *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, newVec));
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec2f_dot(JSContext *cx, JSObject *obj, uintN argc,
+ jsval *argv, jsval *rval)
+{
+ SbVec2f & vec1 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC2F(cx, argv[0])) {
+ SbVec2f & vec2 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+
+ float dot = vec1.dot(vec2);
+ JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, dot, rval);
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec3f_dot(JSContext *cx, JSObject *obj, uintN argc,
+ jsval *argv, jsval *rval)
+{
+ SbVec3f & vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+
+ SbVec3f & vec2 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+
+ float dot = vec.dot(vec2);
+ JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, dot, rval);
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec3d_dot(JSContext *cx, JSObject *obj, uintN argc,
+ jsval *argv, jsval *rval)
+{
+ SbVec3d & vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC3D(cx, argv[0])) {
+
+ SbVec3d & vec2 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+
+ double dot = vec.dot(vec2);
+ JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, dot, rval);
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec2_length(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec2f * vec = (SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+ JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, vec->length(), rval);
+ return JS_TRUE;
+}
+
+static JSBool SFVec3f_length(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3f * vec = (SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+ JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, vec->length(), rval);
+ return JS_TRUE;
+}
+
+static JSBool SFVec3d_length(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3d * vec = (SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+ JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, vec->length(), rval);
+ return JS_TRUE;
+}
+
+static JSBool SFVec2f_multiply(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+
+ SbVec2f & vec = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_NUMBER(argv[0])) {
+ double number;
+ spidermonkey()->JS_ValueToNumber(cx, argv[0], &number);
+
+ SbVec2f newVec = vec * (float)number;
+
+ *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, newVec));
+
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec3f_multiply(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3f & vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ double number;
+ if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+ SbVec3f newVec = vec * (float)number;
+ *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, newVec));
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec3d_multiply(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3d & vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ double number;
+ if (argc >= 1 && jsval2double(cx, argv[0], number)) {
+ SbVec3d newVec = vec * number;
+ *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, newVec));
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec2f_normalize(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec2f vec = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+ vec.normalize();
+ *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, vec));
+ return JS_TRUE;
+}
+
+static JSBool SFVec3f_normalize(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3f vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+ vec.normalize();
+ *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, vec));
+ return JS_TRUE;
+}
+
+static JSBool SFVec3d_normalize(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3d vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+ vec.normalize();
+ *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, vec));
+ return JS_TRUE;
+}
+
+static JSBool SFVec3f_negate(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3f vec = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+ vec.negate();
+ *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, vec));
+ return JS_TRUE;
+}
+
+static JSBool SFVec3d_negate(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3d vec = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+ vec.negate();
+ *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, vec));
+ return JS_TRUE;
+}
+
+static JSBool SFVec2f_subtract(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec2f & vec1 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC2F(cx, argv[0])) {
+ SbVec2f & vec2 = *(SbVec2f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ SbVec2f result = vec1 - vec2;
+ *rval = OBJECT_TO_JSVAL(SFVec2fFactory(cx, result));
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFVec3f_subtract(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3f & vec1 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+ SbVec3f & vec2 = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ SbVec3f result = vec1 - vec2;
+ *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, result));
+ return JS_TRUE;
+ }
+
+ return JS_FALSE;
+}
+
+static JSBool SFVec3d_subtract(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec3d & vec1 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC3D(cx, argv[0])) {
+ SbVec3d & vec2 = *(SbVec3d *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ SbVec3d result = vec1 - vec2;
+ *rval = OBJECT_TO_JSVAL(SFVec3dFactory(cx, result));
+ return JS_TRUE;
+ }
+
+ return JS_FALSE;
+}
+
+static JSBool SFColor_setHSV(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ if (argc != 3) {
+ return JS_FALSE;
+ }
+ SbColor & color = *(SbColor *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ float vals[3];
+ int i;
+
+ for (i=0; i<3; ++i) {
+ double number;
+ spidermonkey()->JS_ValueToNumber(cx, argv[i], &number);
+ vals[i] = (float)number;
+ }
+
+ color.setHSVValue(vals);
+
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool SFColor_getHSV(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbColor & color = *(SbColor *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ float vals[3];
+ color.getHSVValue(vals);
+
+ jsval vector[3];
+ for (int i=0; i<3; ++i) {
+ spidermonkey()->JS_NewDoubleValue(cx, vals[i], &vector[i]);
+ }
+
+ *rval = OBJECT_TO_JSVAL(spidermonkey()->JS_NewArrayObject(cx, 3, vector));
+
+ return JS_TRUE;
+}
+
+static JSBool SFRotation_getAxis(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec4f & rot = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+ SbVec3f axis(rot[0], rot[1], rot[2]);
+ *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, axis));
+ return JS_TRUE;
+}
+
+static JSBool SFRotation_inverse(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec4f & rot = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ SbVec3f axis(rot[0], rot[1], rot[2]);
+ SbRotation newRot(axis, rot[3]);
+ newRot.invert();
+
+ *rval = OBJECT_TO_JSVAL(SFRotationFactory(cx, newRot));
+ return JS_TRUE;
+}
+
+static JSBool SFRotation_multiply(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec4f & vec1 = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFROTATION(cx, argv[0])) {
+ SbVec4f & vec2 = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ SbVec3f axis1(vec1[0], vec1[1], vec1[2]);
+ SbVec3f axis2(vec2[0], vec2[1], vec2[2]);
+ SbRotation result = SbRotation(axis1, vec1[3]) * SbRotation(axis2, vec2[3]);
+
+ *rval = OBJECT_TO_JSVAL(SFRotationFactory(cx, result));
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFRotation_multVec(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec4f & vec = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+ SbVec3f axis(vec[0], vec[1], vec[2]);
+ SbRotation rot(axis, vec[3]);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+ SbVec3f & src = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ SbVec3f dst;
+ rot.multVec(src, dst);
+
+ *rval = OBJECT_TO_JSVAL(SFVec3fFactory(cx, dst));
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFRotation_setAxis(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec4f & rot = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (argc >= 1 && JSVAL_IS_SFVEC3F(cx, argv[0])) {
+ SbVec3f & axis = *(SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ rot[0] = axis[0];
+ rot[1] = axis[1];
+ rot[2] = axis[2];
+
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSBool SFRotation_slerp(JSContext * cx, JSObject * obj, uintN argc,
+ jsval * argv, jsval * rval)
+{
+ SbVec4f & vec = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, obj);
+ SbVec3f axis(vec[0], vec[1], vec[2]);
+ SbRotation rot(axis, vec[3]);
+
+ double number;
+ if (argc >= 2 && JSVAL_IS_SFROTATION(cx, argv[0]) && jsval2double(cx, argv[1], number)) {
+ SbVec4f & vec2 = *(SbVec4f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[0]));
+ SbVec3f axis2(vec2[0], vec2[1], vec2[2]);
+ SbRotation dest(axis2, vec2[3]);
+
+ SbRotation result = SbRotation::slerp(rot, dest, (float)number);
+
+ *rval = OBJECT_TO_JSVAL(SFRotationFactory(cx, result));
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSFunctionSpec SFNodeFunctions[] = {
+ {"ref", SFNode_ref, 0, 0, 0},
+ {"unref", SFNode_unref, 0, 0, 0},
+ {"toString", SFNode_toString, 0, 0, 0},
+ {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFVec2fFunctions[] = {
+ {"add", SFVec2f_add, 1, 0, 0},
+ {"divide", SFVec2f_divide, 1, 0, 0},
+ {"dot", SFVec2f_dot, 1, 0, 0},
+ {"length", SFVec2_length, 0, 0, 0},
+ {"multiply", SFVec2f_multiply, 1, 0, 0},
+ {"normalize", SFVec2f_normalize, 0, 0, 0},
+ {"subtract", SFVec2f_subtract, 1, 0, 0},
+ {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFVec3fFunctions[] = {
+ {"add", SFVec3f_add, 1, 0, 0},
+ {"divide", SFVec3f_divide, 1, 0, 0},
+ {"dot", SFVec3f_dot, 1, 0, 0},
+ {"length", SFVec3f_length, 0, 0, 0},
+ {"multiply", SFVec3f_multiply, 1, 0, 0},
+ {"normalize", SFVec3f_normalize, 0, 0, 0},
+ {"negate", SFVec3f_negate, 0, 0, 0},
+ {"subtract", SFVec3f_subtract, 1, 0, 0},
+ {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFVec3dFunctions[] = {
+ {"add", SFVec3d_add, 1, 0, 0},
+ {"divide", SFVec3d_divide, 1, 0, 0},
+ {"dot", SFVec3d_dot, 1, 0, 0},
+ {"length", SFVec3d_length, 0, 0, 0},
+ {"multiply", SFVec3d_multiply, 1, 0, 0},
+ {"normalize", SFVec3d_normalize, 0, 0, 0},
+ {"negate", SFVec3d_negate, 0, 0, 0},
+ {"subtract", SFVec3d_subtract, 1, 0, 0},
+ {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFColorFunctions[] = {
+ {"setHSV", SFColor_setHSV, 3, 0, 0},
+ {"getHSV", SFColor_getHSV, 0, 0, 0},
+ {NULL, NULL, 0, 0, 0}
+};
+
+static JSFunctionSpec SFRotationFunctions[] = {
+ {"getAxis", SFRotation_getAxis, 0, 0, 0},
+ {"inverse", SFRotation_inverse, 0, 0, 0},
+ {"multiply", SFRotation_multiply, 1, 0, 0},
+ {"multVec", SFRotation_multVec, 1, 0, 0},
+ {"setAxis", SFRotation_setAxis, 1, 0, 0},
+ {"slerp", SFRotation_slerp, 2, 0, 0},
+ {NULL, NULL, 0, 0, 0}
+};
+
+// *************************************************************************
+// factory
+
+static JSObject * SFColorFactory(JSContext * cx, const SbColor & self)
+{
+ JSObject * obj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFColor.cls, NULL, NULL);
+ spidermonkey()->JS_DefineFunctions(cx, obj, SFColorFunctions);
+
+ SbColor * color = new SbColor(self);
+ spidermonkey()->JS_SetPrivate(cx, obj, color);
+
+ return obj;
+}
+
+static JSObject * SFRotationFactory(JSContext * cx, const SbRotation & self)
+{
+ JSObject * obj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFRotation.cls, NULL, NULL);
+ spidermonkey()->JS_DefineFunctions(cx, obj, SFRotationFunctions);
+
+ SbVec3f axis;
+ float angle;
+ self.getValue(axis, angle);
+ SbVec4f * data = new SbVec4f(axis[0], axis[1], axis[2], angle);
+ spidermonkey()->JS_SetPrivate(cx, obj, data);
+
+ return obj;
+}
+
+static JSObject * SFVec2fFactory(JSContext * cx, const SbVec2f & self)
+{
+ JSObject * obj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec2f.cls, NULL, NULL);
+ spidermonkey()->JS_DefineFunctions(cx, obj, SFVec2fFunctions);
+
+ SbVec2f * data = new SbVec2f(self);
+ spidermonkey()->JS_SetPrivate(cx, obj, data);
+ return obj;
+}
+
+static JSObject * SFVec3fFactory(JSContext * cx, const SbVec3f & self)
+{
+ JSObject * obj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec3f.cls, NULL, NULL);
+ spidermonkey()->JS_DefineFunctions(cx, obj, SFVec3fFunctions);
+
+ SbVec3f * data = new SbVec3f(self);
+ spidermonkey()->JS_SetPrivate(cx, obj, data);
+
+ return obj;
+}
+
+static JSObject * SFVec3dFactory(JSContext * cx, const SbVec3d & self)
+{
+ JSObject * obj =
+ spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFVec3d.cls, NULL, NULL);
+ spidermonkey()->JS_DefineFunctions(cx, obj, SFVec3dFunctions);
+
+ SbVec3d * data = new SbVec3d(self);
+ spidermonkey()->JS_SetPrivate(cx, obj, data);
+
+ return obj;
+}
+
+static JSObject * SFVec2f_init(JSContext * cx, JSObject * obj)
+{
+ return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFVec2f.cls,
+ SFVec2fHandler::constructor, 0,
+ NULL, SFVec2fFunctions, NULL, NULL);
+}
+
+static JSObject * SFVec3f_init(JSContext * cx, JSObject * obj)
+{
+ return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFVec3f.cls,
+ SFVec3fHandler::constructor, 0,
+ NULL, SFVec3fFunctions, NULL, NULL);
+}
+
+static JSObject * SFVec3d_init(JSContext * cx, JSObject * obj)
+{
+ return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFVec3d.cls,
+ SFVec3dHandler::constructor, 0,
+ NULL, SFVec3dFunctions, NULL, NULL);
+}
+
+static JSObject * SFColor_init(JSContext * cx, JSObject * obj)
+{
+ return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFColor.cls,
+ SFColorHandler::constructor, 0,
+ NULL, SFColorFunctions, NULL, NULL);
+}
+
+static JSObject * SFRotation_init(JSContext * cx, JSObject * obj)
+{
+ return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFRotation.cls,
+ SFRotationConstructor, 0,
+ NULL, SFRotationFunctions, NULL, NULL);
+}
+
+// *************************************************************************
+// SFNode
+
+static JSBool SFNode_get(JSContext * cx, JSObject * obj, jsval id, jsval * rval)
+{
+
+ if (garbagecollectedobjects->find(obj) != -1) {
+ spidermonkey()->JS_ReportError(cx, "Trying to access an object with refcount=0.");
+ return JS_FALSE;
+ }
+
+ SoNode * container = (SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (container == NULL) {
+ // this will only happen when JS_NewObject calls "constructor"
+ // or the node is "undefined"
+
+ if (JSVAL_IS_STRING(id)) {
+ const char * str = spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id));
+ if (SbName("constructor") == str) {
+ return JS_TRUE;
+ }
+ }
+ spidermonkey()->JS_ReportError(cx, "node is undefined");
+ return JS_FALSE;
+ }
+
+ if (JSVAL_IS_STRING(id)) {
+ SbString str(spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id)));
+
+ SoField * out = container->getField(SbName(str));
+
+ int len = str.getLength();
+ static const char post[] = "_changed";
+ static const size_t postLen = sizeof(post) - 1;
+
+ if (out == NULL && len > (int)postLen &&
+ str.getSubString(len - postLen) == post) {
+ out = container->getField(SbName(str.getSubString(0, len - postLen - 1)));
+ }
+
+ if (out != NULL) {
+ SoJavaScriptEngine::getEngine(cx)->field2jsval(out, rval);
+ return JS_TRUE;
+ }
+ }
+
+ /* Note: If we're unable to find the field, we return JS_TRUE
+ instead of JS_FALSE, which might seem as the logical choice
+ for indicating a failure. If we return JS_FALSE, execution of
+ the script will halt. One side-effect of this is that it is not
+ possible to extend the SFNode JavaScript object by adding
+ properties, which can be very useful in some cases. This is also
+ more in line with the JavaScript philosophy that one can
+ dynamically add and remove properties for any object at any time.
+
+ 2005-11-23 thammer.
+
+ Update: We should look more closely into the return values
+ JS_TRUE / JS_FALSE for all getters and setters, and possibly for
+ other functions as well. It might be more robust to report the
+ error (using JS_ReportError) and return JS_TRUE to allow the
+ script to continue running than to abort the script.
+
+ 2006-06-21 thammer.
+ */
+ return JS_TRUE;
+}
+
+static JSBool SFNode_set(JSContext * cx, JSObject * obj, jsval id, jsval * rval)
+{
+ SoNode * container = (SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+
+ if (container == NULL) {
+ spidermonkey()->JS_ReportError(cx, "node is undefined");
+ return JS_FALSE;
+ }
+
+ if (JSVAL_IS_STRING(id)) {
+ SbString str(spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(id)));
+
+ SoField * in = container->getField(SbName(str));
+
+ int len = str.getLength();
+ static const char pre[] = "set_";
+ static const size_t preLen = sizeof(pre) - 1;
+
+ if (in == NULL && len > (int)preLen &&
+ str.getSubString(0, preLen - 1) == pre) {
+ in = container->getField(SbName(str.getSubString(preLen)));
+ }
+
+ if (in != NULL) {
+ SoJavaScriptEngine::getEngine(cx)->jsval2field(*rval, in);
+ if (SoJavaScriptEngine::debug()) {
+ SoDebugError::postInfo("SFNode_set", "setting field %s", str.getString());
+ }
+ } else if (SoJavaScriptEngine::debug())
+ SoDebugError::postWarning("SFNode_set", "no such field %s", str.getString());
+ }
+
+ // See note in SFNode_get() about return value. 2005-11-23 thammer.
+ return JS_TRUE;
+}
+
+static void SFNodeDestructor(JSContext * cx, JSObject * obj)
+{
+ // Delete all SoNodeSensors which no longer has a node attached.
+ cleanupObsoleteNodeSensors();
+ if(garbagecollectedobjects->find(obj) != -1) { // Pointer is marked as garbage-collected
+ garbagecollectedobjects->removeItem(obj);
+ }
+
+ SoNode * container = (SoNode *)spidermonkey()->JS_GetPrivate(cx, obj);
+ // FIXME: We cannot assume this since the class object itself is an
+ // instance of this JSClass. kintel 20050804.
+ // assert(container != NULL);
+ if (SoJavaScriptEngine::getEngine(cx)->getAutoNodeUnrefState())
+ if (container) container->unref();
+}
+
+// Called via coin_atexit() when Coin exits.
+static void deleteSensorInfoHash(void)
+{
+ CoinVrmlJs_sensorinfohash->clear();
+ delete CoinVrmlJs_sensorinfohash;
+}
+
+/*
+ Attach an SoNodeSensor to node. Adds a 'delete callback' to the
+ sensor which includes the 'obj' parameter.
+*/
+static void attachSensorToNode(SoNode * node, JSObject * obj)
+{
+ // Has the hash-table been initialized?
+ if (!CoinVrmlJs_sensorinfohash) {
+ CoinVrmlJs_sensorinfohash = new SbHash <void *, unsigned long>;
+ coin_atexit(deleteSensorInfoHash, CC_ATEXIT_NORMAL);
+ }
+
+ // Is a sensor already attached to this SoNode?
+ void * tmp;
+ if (CoinVrmlJs_sensorinfohash->get((unsigned long) node, tmp)) {
+ CoinVrmlJs_SensorInfo * si = (CoinVrmlJs_SensorInfo *) tmp;
+ si->objects.append(obj);
+ }
+ else {
+ SoNodeSensor * ns = new SoNodeSensor();
+ ns->setDeleteCallback(SFNode_deleteCB, obj);
+ ns->attach(node);
+ CoinVrmlJs_SensorInfo * si = new CoinVrmlJs_SensorInfo;
+ si->objects.append(obj);
+ CoinVrmlJs_sensorinfohash->put((unsigned long) node, si);
+ }
+}
+
+static JSObject * SFNodeFactory(JSContext * cx, SoNode * container)
+{
+ // Delete all SoNodeSensors which no longer has a node attached.
+ cleanupObsoleteNodeSensors();
+
+ JSObject * obj = spidermonkey()->JS_NewObject(cx, &CoinVrmlJs::SFNode.cls, NULL, NULL);
+
+ if(garbagecollectedobjects->find(obj) != -1) // Pointer has been used before. Remove from list.
+ garbagecollectedobjects->removeItem(obj);
+
+ spidermonkey()->JS_SetPrivate(cx, obj, container);
+ spidermonkey()->JS_DefineFunctions(cx, obj, SFNodeFunctions);
+
+ // FIXME: If the node has enums, define them here. 2007-03-08 thammer.
+
+ attachSensorToNode(container, obj);
+
+ if (SoJavaScriptEngine::getEngine(cx)->getAutoNodeUnrefState())
+ container->ref();
+
+ return obj;
+}
+
+static JSBool SFNodeConstructor(JSContext * cx, JSObject * obj,
+ uintN argc, jsval * argv, jsval *rval)
+{
+ // Delete all SoNodeSensors which no longer has a node attached.
+ cleanupObsoleteNodeSensors();
+
+ // spidermonkey ignores the return value
+ if (argc >= 1 && JSVAL_IS_STRING(argv[0])) {
+ JSString * js = JSVAL_TO_STRING(argv[0]);
+ char * str = spidermonkey()->JS_GetStringBytes(js);
+ size_t len = spidermonkey()->JS_GetStringLength(js);
+
+ // FIXME: what about UTF8? 20050701 erikgors.
+
+ if (SoJavaScriptEngine::debug()) {
+ SoDebugError::postInfo("SFNodeConstructor",
+ "creating new node with str = '%s'", str);
+ }
+
+ SoInput input;
+ const char * array[2];
+ array[0] = str;
+ array[1] = NULL;
+ input.setStringArray(array);
+
+ SoGroup * group;
+
+ if (input.isFileVRML2())
+ group = SoDB::readAllVRML(&input);
+ else
+ group = SoDB::readAll(&input);
+
+ if (group == NULL) {
+ spidermonkey()->JS_ReportError(cx, "input is not legal VRML string");
+ return JS_FALSE;
+ }
+ if (group->getNumChildren() == 0) {
+ spidermonkey()->JS_ReportError(cx, "no top-level node, result is undefined");
+ *rval = JSVAL_VOID;
+ return JS_FALSE;
+ }
+
+ if(garbagecollectedobjects->find(obj) != -1) { // Pointer has been used before. Remove from list.
+ garbagecollectedobjects->removeItem(obj);
+ }
+
+ attachSensorToNode(group, obj);
+
+ if (SoJavaScriptEngine::getEngine(cx)->getAutoNodeUnrefState())
+ group->ref();
+
+ spidermonkey()->JS_SetPrivate(cx, obj, group);
+ spidermonkey()->JS_DefineFunctions(cx, obj, SFNodeFunctions);
+
+ return JS_TRUE;
+ }
+ return JS_FALSE;
+}
+
+static JSObject * SFNode_init(JSContext * cx, JSObject * obj)
+{
+ return spidermonkey()->JS_InitClass(cx, obj, NULL, &CoinVrmlJs::SFNode.cls,
+ SFNodeConstructor, 0,
+ NULL, NULL, NULL, NULL);
+}
+
+
+// *************************************************************************
+// jsval2field
+
+static SbBool SFBool_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ if (JSVAL_IS_BOOLEAN(v)) {
+ const SbBool b = JSVAL_TO_BOOLEAN(v);
+ ((SoSFBool *)f)->setValue(b);
+ return TRUE;
+ }
+ else {
+ JSBool b;
+ if (spidermonkey()->JS_ValueToBoolean(cx, v, &b)) {
+ ((SoSFBool *)f)->setValue(b);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static SbBool SFColor_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ if (JSVAL_IS_SFCOLOR(cx, v)) {
+ SbColor * color = (SbColor *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ assert(color != NULL);
+ ((SoSFColor *)f)->setValue(*color);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFFloat_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ double number;
+ if (jsval2double(cx, v, number)) {
+ ((SoSFFloat *)f)->setValue((float)number);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFInt32_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ int32_t val;
+ if (jsval2int(cx, v, val)) {
+ ((SoSFInt32 *)f)->setValue(val);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFEnum_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ int32_t val;
+ if (jsval2int(cx, v, val)) {
+ ((SoSFInt32 *)f)->setValue(val);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFNode_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ if (JSVAL_IS_NULL(v)) {
+ ((SoSFNode *)f)->setValue(NULL);
+ return TRUE;
+ }
+ if (JSVAL_IS_OBJECT(v) &&
+ spidermonkey()->JS_InstanceOf(cx, JSVAL_TO_OBJECT(v), &CoinVrmlJs::SFNode.cls, NULL)) {
+ SoNode * node = (SoNode *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ ((SoSFNode *)f)->setValue(node);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFRotation_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ if (JSVAL_IS_SFROTATION(cx, v)) {
+ SbVec4f * rot = (SbVec4f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ assert(rot != NULL);
+ SbVec3f axis((*rot)[0], (*rot)[1], (*rot)[2]);
+ ((SoSFRotation *)f)->setValue(SbRotation(axis, (*rot)[3]));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFString_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ if (JSVAL_IS_STRING(v)) {
+ const char * str = spidermonkey()->JS_GetStringBytes(JSVAL_TO_STRING(v));
+ ((SoSFString *)f)->setValue(str);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFTime_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ double number;
+ if (jsval2double(cx, v, number)) {
+ spidermonkey()->JS_ValueToNumber(cx, v, &number);
+ ((SoSFTime*)f)->setValue(SbTime(number));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFVec2f_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ if (JSVAL_IS_SFVEC2F(cx, v)) {
+ SbVec2f * vec = (SbVec2f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ assert(vec != NULL);
+ ((SoSFVec2f *)f)->setValue(*vec);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFVec3f_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ if (JSVAL_IS_SFVEC3F(cx, v)) {
+ SbVec3f * vec = (SbVec3f *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ assert(vec != NULL);
+ ((SoSFVec3f *)f)->setValue(*vec);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static SbBool SFVec3d_jsval2field(JSContext * cx, const jsval v, SoField * f)
+{
+ if (JSVAL_IS_SFVEC3D(cx, v)) {
+ SbVec3d * vec = (SbVec3d *)spidermonkey()->JS_GetPrivate(cx, JSVAL_TO_OBJECT(v));
+ assert(vec != NULL);
+ ((SoSFVec3d *)f)->setValue(*vec);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// *************************************************************************
+// field2jsval
+
+static void SFBool_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+ const SbBool val = ((SoSFBool *)f)->getValue();
+ *v = BOOLEAN_TO_JSVAL(val);
+}
+
+static void SFColor_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+ const SbColor & val = ((SoSFColor *)f)->getValue();
+ JSObject * obj = SFColorFactory(cx, val);
+ *v = OBJECT_TO_JSVAL(obj);
+}
+
+static void SFFloat_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+ const float val = ((SoSFFloat *)f)->getValue();
+ JSBool ok = spidermonkey()->JS_NewDoubleValue(cx, val, v);
+}
+
+static void SFInt32_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+ const int32_t val = ((SoSFInt32 *)f)->getValue();
+ *v = INT_TO_JSVAL(val);
+}
+
+static void SFEnum_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+ const int32_t val = ((SoSFInt32 *)f)->getValue();
+ *v = INT_TO_JSVAL(val);
+}
+
+static void SFNode_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+ SoNode * node = ((SoSFNode *)f)->getValue();
+ if (node == NULL)
+ *v = JSVAL_NULL;
+ else {
+ JSObject * obj = SFNodeFactory(cx, node);
+ *v = OBJECT_TO_JSVAL(obj);
+ }
+}
+
+static void SFRotation_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+ const SbRotation & val = ((SoSFRotation *)f)->getValue();
+ JSObject * obj = SFRotationFactory(cx, val);
+ *v = OBJECT_TO_JSVAL(obj);
+}
+
+static void SFString_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+ const SbString & val = ((SoSFString *)f)->getValue();
+ JSString * str = spidermonkey()->JS_NewStringCopyZ(cx, val.getString());
+ *v = STRING_TO_JSVAL(str);
+}
+
+static void SFTime_field2jsval(JSContext * cx, const SoField * f, jsval * v)
+{
+ const SbTime & time = ((SoSFTime *)f)->getValue();
+ spidermonkey()->JS_NewDoubleValue(cx, time.getValue(), v);
+}
+
+static void SFVec2f_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+ const SbVec2f & val = ((SoSFVec2f *)f)->getValue();
+ JSObject * obj = SFVec2fFactory(cx, val);
+ *v = OBJECT_TO_JSVAL(obj);
+}
+
+static void SFVec3f_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+ const SbVec3f & val = ((SoSFVec3f *)f)->getValue();
+ JSObject * obj = SFVec3fFactory(cx, val);
+ *v = OBJECT_TO_JSVAL(obj);
+}
+
+static void SFVec3d_field2jsval(JSContext * cx, const SoField * f, jsval *v)
+{
+ const SbVec3d & val = ((SoSFVec3d *)f)->getValue();
+ JSObject * obj = SFVec3dFactory(cx, val);
+ *v = OBJECT_TO_JSVAL(obj);
+}
+
+// *************************************************************************
+// classes
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFColor = {
+ {
+ "SFColor", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ SFColorHandler::get, SFColorHandler::set,
+ NULL, NULL, NULL,
+ SFColorHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ SFColorFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFNode = {
+ {
+ "SFNode", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ SFNode_get, SFNode_set,
+ NULL, NULL, NULL,
+ SFNodeDestructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ NULL
+};
+
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFRotation = {
+ {
+ "SFRotation", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ SFRotationHandler::get, SFRotationHandler::set,
+ NULL, NULL, NULL,
+ SFRotationHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ SFRotationFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFVec2f = {
+ {
+ "SFVec2f", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ SFVec2fHandler::get, SFVec2fHandler::set,
+ NULL, NULL, NULL,
+ SFVec2fHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ SFVec2fFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFVec3f = {
+ {
+ "SFVec3f", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ SFVec3fHandler::get, SFVec3fHandler::set,
+ NULL, NULL, NULL,
+ SFVec3fHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ SFVec3fFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::SFVec3d = {
+ {
+ "SFVec3d", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ SFVec3dHandler::get, SFVec3dHandler::set,
+ NULL, NULL, NULL,
+ SFVec3dHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ SFVec3dFunctions
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFColor = {
+ {
+ "MFColor", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFColorHandler::get, MFColorHandler::set,
+ NULL, NULL, NULL,
+ MFColorHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFFloat = {
+ {
+ "MFFloat", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFFloatHandler::get, MFFloatHandler::set,
+ NULL, NULL, NULL,
+ MFFloatHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFInt32 = {
+ {
+ "MFInt32", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFInt32Handler::get, MFInt32Handler::set,
+ NULL, NULL, NULL,
+ MFInt32Handler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFNode = {
+ {
+ "MFNode", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFNodeHandler::get, MFNodeHandler::set,
+ NULL, NULL, NULL,
+ MFNodeHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFRotation = {
+ {
+ "MFRotation", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFRotationHandler::get, MFRotationHandler::set,
+ NULL, NULL, NULL,
+ MFRotationHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFString = {
+ {
+ "MFString", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFStringHandler::get, MFStringHandler::set,
+ NULL, NULL, NULL,
+ MFStringHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFTime = {
+ {
+ "MFTime", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFTimeHandler::get, MFTimeHandler::set,
+ NULL, NULL, NULL,
+ MFTimeHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFVec2f = {
+ {
+ "MFVec2f", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFVec2fHandler::get, MFVec2fHandler::set,
+ NULL, NULL, NULL,
+ MFVec2fHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFVec3f = {
+ {
+ "MFVec3f", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFVec3fHandler::get, MFVec3fHandler::set,
+ NULL, NULL, NULL,
+ MFVec3fHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+CoinVrmlJs::ClassDescriptor CoinVrmlJs::MFVec3d = {
+ {
+ "MFVec3d", JSCLASS_HAS_PRIVATE, NULL, NULL,
+ MFVec3dHandler::get, MFVec3dHandler::set,
+ NULL, NULL, NULL,
+ MFVec3dHandler::destructor,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ MFFunctions,
+};
+
+
+CoinVrmlJs::ClassDescriptor * CLASSDESCRIPTORS[] = {
+ &CoinVrmlJs::SFColor, &CoinVrmlJs::SFNode, &CoinVrmlJs::SFRotation,
+ &CoinVrmlJs::SFVec2f, &CoinVrmlJs::SFVec3f, &CoinVrmlJs::SFVec3d,
+ &CoinVrmlJs::MFColor,
+ &CoinVrmlJs::MFFloat, &CoinVrmlJs::MFInt32, &CoinVrmlJs::MFNode,
+ &CoinVrmlJs::MFRotation, &CoinVrmlJs::MFString, &CoinVrmlJs::MFTime,
+ &CoinVrmlJs::MFVec2f, &CoinVrmlJs::MFVec3f, &CoinVrmlJs::MFVec3d
+};
+
+// *************************************************************************
+
+// cleans up static / one-off resource allocations
+static void
+js_vrmlclasses_cleanup(void)
+{
+ delete garbagecollectedobjects;
+ delete nodesensorstobedeleted;
+
+ garbagecollectedobjects = NULL;
+ nodesensorstobedeleted = NULL;
+}
+
+// *************************************************************************
+// helper function to add all classes to engine
+
+void
+JS_addVRMLclasses(SoJavaScriptEngine * engine)
+{
+ // init static data
+ if (garbagecollectedobjects == NULL) {
+ garbagecollectedobjects = new SbList <JSObject *>;
+ nodesensorstobedeleted = new SbList <SoNodeSensor *>;
+ coin_atexit((coin_atexit_f *)js_vrmlclasses_cleanup, CC_ATEXIT_NORMAL);
+
+ // set up default function stubs for Spidermonkey classes we
+ // make. must be done at run-time to avoid calling spidermonkey()
+ // early (i.e. not on demand).
+ const size_t NRELEMENTS = sizeof(CLASSDESCRIPTORS) / sizeof(CLASSDESCRIPTORS[0]);
+ for (size_t i=0; i < NRELEMENTS; i++) {
+ CoinVrmlJs::ClassDescriptor * desc = CLASSDESCRIPTORS[i];
+ desc->cls.addProperty = spidermonkey()->JS_PropertyStub;
+ desc->cls.delProperty = spidermonkey()->JS_PropertyStub;
+ desc->cls.enumerate = spidermonkey()->JS_EnumerateStub;
+ desc->cls.resolve = spidermonkey()->JS_ResolveStub;
+ desc->cls.convert = spidermonkey()->JS_ConvertStub;
+ }
+ }
+
+ // Bool
+ engine->addHandler(
+ SoSFBool::getClassTypeId(), NULL,
+ SFBool_field2jsval, SFBool_jsval2field);
+
+ // Color
+ engine->addHandler(
+ SoSFColor::getClassTypeId(), SFColor_init,
+ SFColor_field2jsval, SFColor_jsval2field);
+ engine->addHandler(
+ SoMFColor::getClassTypeId(),
+ MFColorHandler::init,
+ MFColorHandler::field2jsval,
+ MFColorHandler::jsval2field);
+
+ // Float
+ engine->addHandler(
+ SoSFFloat::getClassTypeId(), NULL,
+ SFFloat_field2jsval, SFFloat_jsval2field);
+ engine->addHandler(
+ SoMFFloat::getClassTypeId(),
+ MFFloatHandler::init,
+ MFFloatHandler::field2jsval,
+ MFFloatHandler::jsval2field);
+
+ // Int32
+ engine->addHandler(
+ SoSFInt32::getClassTypeId(), NULL,
+ SFInt32_field2jsval, SFInt32_jsval2field);
+ engine->addHandler(
+ SoMFInt32::getClassTypeId(),
+ MFInt32Handler::init,
+ MFInt32Handler::field2jsval,
+ MFInt32Handler::jsval2field);
+
+ // Enum
+ engine->addHandler(
+ SoSFEnum::getClassTypeId(), NULL,
+ SFEnum_field2jsval, SFEnum_jsval2field);
+
+ // Node
+ engine->addHandler(
+ SoSFNode::getClassTypeId(), SFNode_init,
+ SFNode_field2jsval, SFNode_jsval2field);
+ engine->addHandler(
+ SoMFNode::getClassTypeId(),
+ MFNodeHandler::init,
+ MFNodeHandler::field2jsval,
+ MFNodeHandler::jsval2field);
+
+ // Rotation
+ engine->addHandler(
+ SoSFRotation::getClassTypeId(), SFRotation_init,
+ SFRotation_field2jsval, SFRotation_jsval2field);
+ engine->addHandler(
+ SoMFRotation::getClassTypeId(),
+ MFRotationHandler::init,
+ MFRotationHandler::field2jsval,
+ MFRotationHandler::jsval2field);
+
+ // String
+ engine->addHandler(
+ SoSFString::getClassTypeId(), NULL,
+ SFString_field2jsval, SFString_jsval2field);
+ engine->addHandler(
+ SoMFString::getClassTypeId(),
+ MFStringHandler::init,
+ MFStringHandler::field2jsval,
+ MFStringHandler::jsval2field);
+
+ // Time
+ engine->addHandler(
+ SoSFTime::getClassTypeId(), NULL,
+ SFTime_field2jsval, SFTime_jsval2field);
+ engine->addHandler(
+ SoMFTime::getClassTypeId(),
+ MFTimeHandler::init,
+ MFTimeHandler::field2jsval,
+ MFTimeHandler::jsval2field);
+
+ // Vec2f
+ engine->addHandler(
+ SoSFVec2f::getClassTypeId(), SFVec2f_init,
+ SFVec2f_field2jsval, SFVec2f_jsval2field);
+ engine->addHandler(
+ SoMFVec2f::getClassTypeId(),
+ MFVec2fHandler::init,
+ MFVec2fHandler::field2jsval,
+ MFVec2fHandler::jsval2field);
+
+ // Vec3f
+ engine->addHandler(
+ SoSFVec3f::getClassTypeId(), SFVec3f_init,
+ SFVec3f_field2jsval, SFVec3f_jsval2field);
+ engine->addHandler(
+ SoMFVec3f::getClassTypeId(),
+ MFVec3fHandler::init,
+ MFVec3fHandler::field2jsval,
+ MFVec3fHandler::jsval2field);
+
+ // Vec3d
+ engine->addHandler(
+ SoSFVec3d::getClassTypeId(), SFVec3d_init,
+ SFVec3d_field2jsval, SFVec3d_jsval2field);
+ engine->addHandler(
+ SoMFVec3d::getClassTypeId(),
+ MFVec3dHandler::init,
+ MFVec3dHandler::field2jsval,
+ MFVec3dHandler::jsval2field);
+}
+
+#endif // HAVE_VRML97
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tony Theodore <tonyt@logyst.com>
Date: Sat, 18 Nov 2017 20:45:31 +1100
Subject: [PATCH 2/2] gcc 4.7 fixes
This patch was taken from Gentoo:
https://gitweb.gentoo.org/repo/gentoo.git/tree/media-libs/coin/files/coin-3.1.3-gcc-4.7.patch?id=17d7c853393ff83e3422e48e9ad2810f23889bbf
diff --git a/include/Inventor/SbBasic.h b/include/Inventor/SbBasic.h
index 1111111..2222222 100644
--- a/include/Inventor/SbBasic.h
+++ b/include/Inventor/SbBasic.h
@@ -24,6 +24,7 @@
*
\**************************************************************************/
+#include <Inventor/C/errors/debugerror.h>
#include <Inventor/C/basic.h>
/* ********************************************************************** */