I ended up writing a simple wrapper for my ES6 classes. Here is the code:
var wrapper = function(obj) {
var instance = new obj()
var script = pc.createScript(instance.name);
var attributes = [];
if(instance.attributes) {
for (var attr in instance.attributes) {
attributes.push(attr)
script.attributes.add(attr, instance.attributes[attr])
}
}
for (var prop in instance) {
if (prop === 'attributes' || prop === 'name' || attributes.includes(prop)) {
// do nothing
} else {
script.prototype[prop] = instance[prop];
}
}
}
It allows us to write our scripts like this:
wrapper(class {
name = 'wassup';
num = 13;
word = 'donkey';
attributes = {
word: {
type: 'string',
default: 'donkey'
}
}
initialize() {
console.log(this);
}
update(dt) {
console.log(`the word of the day is ${this.word} and the number is ${this.num}.`)
}
});
And if your really want to go all in with recent ES features instead of wrapping the class in the wrapper function, use a decorator:
@wrapper
class Wassup {
...
}
Notice the use of this in console.log()… it works.
I haven’t tested it extensively yet but so far it all seems to work as intended. I’d love to hear what you think. Let me know if you find a bug or have any ideas to improve the wrapper.
Ok, I can access instance properties and script properties now. The only problem is that I don’t know how to access static properties…
Here is my code:
export function script(ScriptConstructor) {
return function (app) {
let scriptInstance = new ScriptConstructor();
let script = pc.createScript(scriptInstance.name, app);
for (let prop in scriptInstance) {
if (prop === 'name' || prop === 'attributes') continue;
script.prototype[prop] = scriptInstance[prop];
}
for (let staticProp in ScriptConstructor) {
if (staticProp === 'extendsFrom') continue;
script[staticProp] = ScriptConstructor[staticProp];
}
return scriptInstance;
}
}
@script
export class OrbitCamera {
name = 'orbitCamera';
static x = 1;
initialize() {
// I can not access the static properties...
// OrbitCamera.x do not work...
}
}
What kind of error are you getting? Have you tried testing it without your if statement in the for loop? It’s the only difference I see between your code and mine and I can access static properties just fine.
Alright, I think I figured out what your problem was. It looks like you incorrectly implemented the decorator factory. The app param needs to be passed to the outer factory function and the ScriptConstructor to the inner closure function. Like so:
export function script(app) {
return function (ScriptConstructor) {
let scriptInstance = new ScriptConstructor();
let script = pc.createScript(scriptInstance.name, app);
for (let prop in scriptInstance) {
if (prop === 'name' || prop === 'attributes') continue;
script.prototype[prop] = scriptInstance[prop];
}
for (let staticProp in ScriptConstructor) {
if (staticProp === 'extendsFrom') continue;
script[staticProp] = ScriptConstructor[staticProp];
}
return scriptInstance;
}
}
Also, when using the decorator, since it is a factory, you need to add parenthesis:
@script()
export class OrbitCamera {
name = 'orbitCamera';
static x = 1;
initialize() {
// I can not access the static properties...
// OrbitCamera.x do not work...
}
}
Try it and let me know if this fixes your problem.
Because I want to create the script base on the specific app, so I write as ScriptConstructor => app => ... , so that I can use it by:
var app = new pc.Application(canvas);
var orbitCamera = new OrbitCamera(app); // pass the specific app to the script
var cameraEntity = new pc.Entity();
cameraEntity.addComponent('script');
cameraEntity.script.create(orbitCamera.name);
I finally find a workaround. Just do not use it as decorator, use it as high order function.
export function createScript(ScriptConstructor) {
return function (app) {
var scriptInstance = new ScriptConstructor();
var script = pc.createScript(scriptInstance.name, app);
// do stuffs
return scriptInstance;
}
}
// in orbtiCamera.js
class OrbitCamera {
// ...
}
export default createScript(OrbitCamera);
// app.js
var app = new pc.Application();
var orbitCamera = new OrbitCamera(app);
var cameraEntity = new pc.Entity();
cameraEntity.addComponent('script');
cameraEntity.script.create(orbitCamera.name);
Does this still work? I’m trying it and while my script is getting added to the reg and I am able to attach it using create, it never echos the console call from it’s initialize.