-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scripts 2.1 (Class support) #5910
Changes from all commits
cbbb9ee
544c6d4
6342d92
2634303
634aa2c
98ac28b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
export * from "./hello-world.mjs"; | ||
export * from "./mini-stats.mjs"; | ||
export * from "./spineboy.mjs"; | ||
export * from "./scripts.mjs"; | ||
export * from "./gizmos.mjs"; | ||
export * from "./multi-app.mjs"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import * as pc from 'playcanvas'; | ||
|
||
/** | ||
* @param {import('../../options.mjs').ExampleOptions} options - The example options. | ||
* @returns {Promise<pc.AppBase>} The example application. | ||
*/ | ||
async function example({ canvas, deviceType, glslangPath, twgslPath }) { | ||
// define script component | ||
class Rotator extends pc.ScriptType { | ||
// name of a script | ||
static name = 'rotator'; | ||
|
||
// property | ||
speed = 42; | ||
|
||
// this method is executed once the object and script becomes | ||
// available for the execution (enabled) | ||
initialize() { | ||
this.entity.rotate(Math.random() * 360, Math.random() * 360, Math.random() * 360); | ||
} | ||
|
||
// this method is executed on every frame | ||
update(dt) { | ||
this.entity.rotate(dt * this.speed, 0, 0); | ||
} | ||
} | ||
|
||
const gfxOptions = { | ||
deviceTypes: [deviceType], | ||
glslangUrl: glslangPath + 'glslang.js', | ||
twgslUrl: twgslPath + 'twgsl.js' | ||
}; | ||
|
||
const device = await pc.createGraphicsDevice(canvas, gfxOptions); | ||
const createOptions = new pc.AppOptions(); | ||
createOptions.graphicsDevice = device; | ||
|
||
createOptions.componentSystems = [ | ||
pc.RenderComponentSystem, | ||
pc.CameraComponentSystem, | ||
pc.LightComponentSystem, | ||
pc.ScriptComponentSystem | ||
]; | ||
|
||
const app = new pc.AppBase(canvas); | ||
app.init(createOptions); | ||
app.start(); | ||
|
||
// add script to script registry | ||
app.scripts.add(Rotator); | ||
|
||
// Set the canvas to fill the window and automatically change resolution to be the same as the canvas size | ||
app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW); | ||
app.setCanvasResolution(pc.RESOLUTION_AUTO); | ||
|
||
// Ensure canvas is resized when window changes size | ||
const resize = () => app.resizeCanvas(); | ||
window.addEventListener('resize', resize); | ||
app.on('destroy', () => { | ||
window.removeEventListener('resize', resize); | ||
}); | ||
|
||
// create box entity | ||
const box = new pc.Entity('cube'); | ||
box.addComponent('render', { | ||
type: 'box' | ||
}); | ||
// add script component | ||
box.addComponent('script'); | ||
// add rotator script to the entity | ||
box.script?.create('rotator'); | ||
|
||
// clone box multiple times | ||
// arranged in a circle | ||
for(let i = 0; i < 16; i++) { | ||
const entity = box.clone(); | ||
const x = Math.sin(Math.PI * 2 * (i / 16)); | ||
const y = Math.cos(Math.PI * 2 * (i / 16)); | ||
entity.setLocalPosition(x * 2, y * 2, 0); | ||
app.root.addChild(entity); | ||
} | ||
|
||
// create camera entity | ||
const camera = new pc.Entity('camera'); | ||
camera.addComponent('camera', { | ||
clearColor: new pc.Color(0.5, 0.6, 0.9) | ||
}); | ||
app.root.addChild(camera); | ||
camera.setPosition(0, 0, 10); | ||
|
||
// create directional light entity | ||
const light = new pc.Entity('light'); | ||
light.addComponent('light'); | ||
app.root.addChild(light); | ||
light.setEulerAngles(45, 0, 0); | ||
|
||
return app; | ||
} | ||
|
||
class ScriptsExample { | ||
static CATEGORY = 'Misc'; | ||
static WEBGPU_ENABLED = true; | ||
static example = example; | ||
} | ||
|
||
export { ScriptsExample }; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -626,6 +626,8 @@ class ScriptComponent extends Component { | |
if (typeof scriptType === 'string') { | ||
scriptType = this.system.app.scripts.get(scriptType); | ||
} else if (scriptType) { | ||
if (scriptType.__name === null) | ||
scriptType.__name = scriptType.name; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One thing; the Mozilla: Minifiers and bundling name prop Ideally we don't rely on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minifier will be impactful when Current: let Test = pc.createScript('test'); Using a static name property: class Test extends pc.ScriptType {
static name = 'test';
} Using class Test extends pc.ScriptType {
}
pc.registerScript(Test, 'test'); And this also works even right now, but not pretty: class Test extends pc.ScriptType {
static __name = 'test';
} We could define a different name for the static property to avoid collision with built-in property There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you can check if the name property was explicitly defined as a static member rather than inferred using |
||
scriptName = scriptType.__name; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use
?.
here? Isn't the script component guaranteed to be present?