diff --git a/.eslintignore b/.eslintignore index 2a4f1ab..502c357 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ *.js *.d.ts -tmp \ No newline at end of file +tmp +example-scene/ \ No newline at end of file diff --git a/example-scene/.dclignore b/example-scene/.dclignore new file mode 100644 index 0000000..7499ff3 --- /dev/null +++ b/example-scene/.dclignore @@ -0,0 +1,20 @@ +.* +bin/*.map +package-lock.json +yarn-lock.json +build.json +export +tsconfig.json +tslint.json +node_modules +*.ts +*.tsx +.vscode +Dockerfile +dist +README.md +*.blend +*.fbx +*.zip +*.rar +src diff --git a/example-scene/.gitignore b/example-scene/.gitignore new file mode 100644 index 0000000..24fe526 --- /dev/null +++ b/example-scene/.gitignore @@ -0,0 +1,9 @@ +package-lock.json +*.js +node_modules +bin/ +.DS_Store +**/.DS_Store +npm-debug.log* +yarn-debug.log* +yarn-error.log* \ No newline at end of file diff --git a/example-scene/.vscode/extensions.json b/example-scene/.vscode/extensions.json new file mode 100644 index 0000000..38b0d67 --- /dev/null +++ b/example-scene/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["decentralandfoundation.decentraland-sdk7"] +} diff --git a/example-scene/.vscode/launch.json b/example-scene/.vscode/launch.json new file mode 100644 index 0000000..a3b7699 --- /dev/null +++ b/example-scene/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use the Decentraland Editor extension of VSCode to debug the scene + // in chrome from VSCode + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Debug Decentraland in Chrome", + "url": "${command:decentraland-sdk7.commands.getDebugURL}", + "webRoot": "${workspaceFolder}/bin", + "sourceMapPathOverrides": { + "dcl:///*": "${workspaceFolder}/*" + } + } + ] +} diff --git a/example-scene/README.md b/example-scene/README.md new file mode 100644 index 0000000..f2a400b --- /dev/null +++ b/example-scene/README.md @@ -0,0 +1,265 @@ +# SDK7 Template scene + +## Try it out + +**Previewing the scene** + +1. Download this repository. + +2. Install the [Decentraland Editor](https://docs.decentraland.org/creator/development-guide/sdk7/editor/) + +3. Open a Visual Studio Code window on this scene's root folder. Not on the root folder of the whole repo, but instead on this sub-folder that belongs to the scene. + +4. Open the Decentraland Editor tab, and press **Run Scene** + +Alternatively, you can use the command line. Inside this scene root directory run: + +``` +npm run start +``` + +## What's new on SDK 7 + +Below are some basic concepts about the SDK 7 syntax. For more details, see the [Documentation site](https://docs.decentraland.org/creator/). + +### Entities + +An Entity is just an ID. It is an abstract concept not represented by any data structure. There is no "class Entity". Just a number that is used as a reference to group different components. + +```ts +const myEntity = engine.addEntity() +console.console.log(myEntity) // 100 + +// Remove Entity +engine.removeEntity(myEntity) +``` + +> Note: Note that it's no longer necessary to separately create an entity and then add it to the engine, this is all done in a single act. + +### Components + +The component is just a data container, WITHOUT any functions. + +To add a component to an entity, the entry point is now the component type, not the entity. + +```ts +Transform.create(myEntity, ) +``` + +This is different from how the syntax was in SDK6: + +```ts +// OLD Syntax +myEntity.addComponent(Transform) +``` + +#### Base Components + +Base components already come packed as part of the SDK. Most of them interact directly with the renderer in some way. This is the full list of currently supported base components: + +- Transform +- Animator +- Material +- MeshRenderer +- MeshCollider +- AudioSource +- AudioStream +- AvatarAttach +- AvatarModifierArea +- AvatarShape +- Billboard +- CameraMode +- CameraModeArea +- GltfContainer +- NftShape +- PointerEventsResult +- PointerHoverFeedback +- PointerLock +- Raycast +- RaycastResult +- TextShape +- VisibilityComponent + +```ts +const entity = engine.addEntity() +Transfrom.create(entity, { + position: Vector3.create(12, 1, 12) + scale: Vector3.One(), + rotation: Quaternion.Identity() +}) +GltfContainer.create(zombie, { + withCollisions: true, + isPointerBlocker: true, + visible: true, + src: 'models/zombie.glb' +}) +``` + +#### Custom Components + +Each component must have a unique number ID. If a number is repeated, the engine or another player receiving updates might apply changes to the wrong component. Note that numbers 1-2000 are reserved for the base components. + +When creating a custom component you declare the schema of the data to be stored in it. Every field in a component MUST belong to one of the built-in special schemas provided as part of the SDK. These special schemas include extra functionality that allows them to be serialized/deserialized. + +Currently, the names of these special schemas are: + +##### Primitives + +1. `Schemas.Boolean`: true or false (serialized as a Byte) +2. `Schemas.String`: UTF8 strings (serialized length and content) +3. `Schemas.Float`: single precission float +4. `Schemas.Double`: double precision float +5. `Schemas.Byte`: a single byte, integer with range 0..255 +6. `Schemas.Short`: 16 bits signed-integer with range -32768..32767 +7. `Schemas.Int`: 32 bits signed-integer with range -2³¹..(2³¹-1) +8. `Schemas.Int64`: 64 bits signed-integer +9. `Schemas.Number`: an alias to Schemas.Float + +##### Specials + +10. `Schemas.Entity`: a wrapper to int32 that casts the type to `Entity` +11. `Schemas.Vector3`: a Vector3 with { x, y, z } +12. `Schemas.Quaternion`: a Quaternion with { x, y, z, w} +13. `Schemas.Color3`: a Color3 with { r, g, b } +14. `Schemas.Color4`: a Colo4 with { r, g, b, a } + +##### Schema generator + +15. `Schemas.Enum`: passing the serialization Schema and the original Enum as generic +16. `Schemas.Array`: passing the item Schema +17. `Schemas.Map`: passing a Map with Schemas as values +18. `Schemas.Optional`: passing the schema to serialize + +Below are some examples of how these schemas can be declared. + +```ts +const object = Schemas.Map({ x: Schemas.Int }) // { x: 1 } + +const array = Schemas.Map(Schemas.Int) // [1,2,3,4] + +const objectArray = Schemas.Array(Schemas.Map({ x: Schemas.Int })) // [{ x: 1 }, { x: 2 }] + +const BasicSchemas = Schemas.Map({ + x: Schemas.Int, + y: Schemas.Float, + text: Schemas.String, + flag: Schemas.Boolean +}) // { x: 1, y: 1.412, text: 'ecs 7 text', flag: true } + +const VelocitySchema = Schemas.Map({ + x: Schemas.Float, + y: Schemas.Float, + z: Schemas.Float +}) +``` + +To then create a custom component using one of these schemas, use the following syntax: + +```ts +export const myCustomComponent = engine.defineComponent(MyDataSchema, ComponentID) +``` + +For contrast, below is an example of how components were constructed prior to SDK 7. + +```ts +/** + * OLD SDK + */ + +// Define Component +@Component('velocity') +export class Velocity extends Vector3 { + constructor(x: number, y: number, z: number) { + super(x, y, z) + } +} +// Create entity +const wheel = new Entity() + +// Create instance of component with default values +wheel.addComponent(new WheelSpin()) + +/** + * ECS 7 + */ +// Define Component +const VelocitySchema = Schemas.Map({ + x: Schemas.Float, + y: Schemas.Float, + z: Schemas.Float +}) +const COMPONENT_ID = 2008 +const VelocityComponent = engine.defineComponent(Velocity, COMPONENT_ID) +// Create Entity +const entity = engine.addEntity() + +// Create instance of component +VelocityComponent.create(entity, { x: 1, y: 2.3, z: 8 }) + +// Remove instance of a component +VelocityComponent.deleteFrom(entity) +``` + +### Systems + +Systems are pure & simple functions. +All your logic comes here. +A system might hold data which is relevant to the system itself, but no data about the entities it processes. + +To add a system, all you need to do is define a function and add it to the engine. The function may optionally include a `dt` parameter with the delay since last frame, just like in prior versions of the SDK. + +```ts +// Basic system +function mySystem() { + console.log('my system is running') +} + +engine.addSystem(mySystem) + +// System with dt +function mySystemDT(dt: number) { + console.log('time since last frame: ', dt) +} + +engine.addSystem(mySystemDT) +``` + +#### Query components + +The way to group/query the components inside systems is using the method getEntitiesWith. +`engine.getEntitiesWith(...components)`. + +```ts +function physicsSystem(dt: number) { + for (const [entity, transform, velocity] of engine.getEntitiesWith(Transform, Velocity)) { + // transform & velocity are read only components. + if (transform.position.x === 10) { + // To update a component, you need to call the `.mutable` method + const mutableVelocity = VelocityComponent.getMutable(entity) + mutableVelocity.x += 1 + } + } +} + +// Add system to the engine +engine.addSystem(physicsSystem) + +// Remove system +engine.removeSystem(physicsSystem) +``` + +### Mutability + +Mutability is now an important distinction. We can choose to deal with mutable or with immutable versions of a component. We should use `getMutable` only when we plan to make changes to a component. Dealing with immutable versions of components results in a huge gain in performance. + +The `.get()` function in a component returns an immutable version of the component. You can only read its values, but can't change any of the properties on it. + +```ts +const immutableTransform = Transform.get(myEntity) +``` + +To fetch the mutable version of a component, call it via `ComponentDefinition.getMutable()`. For example: + +```ts +const mutableTransform = Transform.getMutable(myEntity) +``` diff --git a/example-scene/mini-game-assets/images/AtlasGames.png b/example-scene/mini-game-assets/images/AtlasGames.png new file mode 100644 index 0000000..0e15e6e Binary files /dev/null and b/example-scene/mini-game-assets/images/AtlasGames.png differ diff --git a/example-scene/mini-game-assets/images/GameSigns.png b/example-scene/mini-game-assets/images/GameSigns.png new file mode 100644 index 0000000..67b7b8a Binary files /dev/null and b/example-scene/mini-game-assets/images/GameSigns.png differ diff --git a/example-scene/mini-game-assets/models/AtlasGames.png b/example-scene/mini-game-assets/models/AtlasGames.png new file mode 100644 index 0000000..0e15e6e Binary files /dev/null and b/example-scene/mini-game-assets/models/AtlasGames.png differ diff --git a/example-scene/mini-game-assets/models/ui/button_base_rectangle.glb b/example-scene/mini-game-assets/models/ui/button_base_rectangle.glb new file mode 100644 index 0000000..851e91c Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_base_rectangle.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_base_square.glb b/example-scene/mini-game-assets/models/ui/button_base_square.glb new file mode 100644 index 0000000..7d6c8aa Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_base_square.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_rectangle_black.glb b/example-scene/mini-game-assets/models/ui/button_rectangle_black.glb new file mode 100644 index 0000000..18262a0 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_rectangle_black.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_rectangle_green.glb b/example-scene/mini-game-assets/models/ui/button_rectangle_green.glb new file mode 100644 index 0000000..1471315 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_rectangle_green.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_rectangle_purple.glb b/example-scene/mini-game-assets/models/ui/button_rectangle_purple.glb new file mode 100644 index 0000000..15765c5 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_rectangle_purple.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_rectangle_red.glb b/example-scene/mini-game-assets/models/ui/button_rectangle_red.glb new file mode 100644 index 0000000..d5e0df1 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_rectangle_red.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_rectangle_white.glb b/example-scene/mini-game-assets/models/ui/button_rectangle_white.glb new file mode 100644 index 0000000..579b592 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_rectangle_white.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_rectangle_yellow.glb b/example-scene/mini-game-assets/models/ui/button_rectangle_yellow.glb new file mode 100644 index 0000000..1a2b29a Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_rectangle_yellow.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_square_black.glb b/example-scene/mini-game-assets/models/ui/button_square_black.glb new file mode 100644 index 0000000..6dcd975 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_square_black.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_square_green.glb b/example-scene/mini-game-assets/models/ui/button_square_green.glb new file mode 100644 index 0000000..d737529 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_square_green.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_square_purple.glb b/example-scene/mini-game-assets/models/ui/button_square_purple.glb new file mode 100644 index 0000000..a3414eb Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_square_purple.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_square_red.glb b/example-scene/mini-game-assets/models/ui/button_square_red.glb new file mode 100644 index 0000000..b60c0cb Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_square_red.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_square_teal.glb b/example-scene/mini-game-assets/models/ui/button_square_teal.glb new file mode 100644 index 0000000..1064bfa Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_square_teal.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_square_white.glb b/example-scene/mini-game-assets/models/ui/button_square_white.glb new file mode 100644 index 0000000..0b0b76f Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_square_white.glb differ diff --git a/example-scene/mini-game-assets/models/ui/button_square_yellow.glb b/example-scene/mini-game-assets/models/ui/button_square_yellow.glb new file mode 100644 index 0000000..15c19e7 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/button_square_yellow.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_0.glb b/example-scene/mini-game-assets/models/ui/numbers/number_0.glb new file mode 100644 index 0000000..1a64212 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_0.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_1.glb b/example-scene/mini-game-assets/models/ui/numbers/number_1.glb new file mode 100644 index 0000000..98a2a7e Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_1.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_2.glb b/example-scene/mini-game-assets/models/ui/numbers/number_2.glb new file mode 100644 index 0000000..a263ee5 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_2.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_3.glb b/example-scene/mini-game-assets/models/ui/numbers/number_3.glb new file mode 100644 index 0000000..ff38726 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_3.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_4.glb b/example-scene/mini-game-assets/models/ui/numbers/number_4.glb new file mode 100644 index 0000000..e6def33 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_4.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_5.glb b/example-scene/mini-game-assets/models/ui/numbers/number_5.glb new file mode 100644 index 0000000..3feacc9 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_5.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_6.glb b/example-scene/mini-game-assets/models/ui/numbers/number_6.glb new file mode 100644 index 0000000..2b393a5 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_6.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_7.glb b/example-scene/mini-game-assets/models/ui/numbers/number_7.glb new file mode 100644 index 0000000..4a89854 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_7.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_8.glb b/example-scene/mini-game-assets/models/ui/numbers/number_8.glb new file mode 100644 index 0000000..77e926d Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_8.glb differ diff --git a/example-scene/mini-game-assets/models/ui/numbers/number_9.glb b/example-scene/mini-game-assets/models/ui/numbers/number_9.glb new file mode 100644 index 0000000..aa192ac Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/numbers/number_9.glb differ diff --git a/example-scene/mini-game-assets/models/ui/scoreboard_bg.glb b/example-scene/mini-game-assets/models/ui/scoreboard_bg.glb new file mode 100644 index 0000000..7d2976b Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/scoreboard_bg.glb differ diff --git a/example-scene/mini-game-assets/models/ui/scoreboard_bg_dark.glb b/example-scene/mini-game-assets/models/ui/scoreboard_bg_dark.glb new file mode 100644 index 0000000..e730171 Binary files /dev/null and b/example-scene/mini-game-assets/models/ui/scoreboard_bg_dark.glb differ diff --git a/example-scene/mini-game-assets/models/winAnim.glb b/example-scene/mini-game-assets/models/winAnim.glb new file mode 100644 index 0000000..6d91383 Binary files /dev/null and b/example-scene/mini-game-assets/models/winAnim.glb differ diff --git a/example-scene/mini-game-assets/models/winAnimFollow.glb b/example-scene/mini-game-assets/models/winAnimFollow.glb new file mode 100644 index 0000000..098e41a Binary files /dev/null and b/example-scene/mini-game-assets/models/winAnimFollow.glb differ diff --git a/example-scene/mini-game-assets/models/winAnimText.glb b/example-scene/mini-game-assets/models/winAnimText.glb new file mode 100644 index 0000000..e0252bb Binary files /dev/null and b/example-scene/mini-game-assets/models/winAnimText.glb differ diff --git a/example-scene/mini-game-assets/sounds/button_click.mp3 b/example-scene/mini-game-assets/sounds/button_click.mp3 new file mode 100644 index 0000000..b890f47 Binary files /dev/null and b/example-scene/mini-game-assets/sounds/button_click.mp3 differ diff --git a/example-scene/mini-game-assets/sounds/wrong.mp3 b/example-scene/mini-game-assets/sounds/wrong.mp3 new file mode 100644 index 0000000..355684d Binary files /dev/null and b/example-scene/mini-game-assets/sounds/wrong.mp3 differ diff --git a/example-scene/package.json b/example-scene/package.json new file mode 100644 index 0000000..5ef4eb3 --- /dev/null +++ b/example-scene/package.json @@ -0,0 +1,28 @@ +{ + "name": "dcl-project", + "version": "1.0.0", + "description": "SDK7 Template scene", + "scripts": { + "start": "sdk-commands start", + "deploy": "sdk-commands deploy", + "build": "sdk-commands build", + "upgrade-sdk": "npm install --save-dev @dcl/sdk@latest", + "upgrade-sdk:next": "npm install --save-dev @dcl/sdk@next" + }, + "devDependencies": { + "@dcl/js-runtime": "latest", + "@dcl/sdk": "latest" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=6.0.0" + }, + "prettier": { + "semi": false, + "singleQuote": true, + "printWidth": 120, + "trailingComma": "none" + }, + "dependencies": { + } +} diff --git a/example-scene/scene.json b/example-scene/scene.json new file mode 100644 index 0000000..92fa7da --- /dev/null +++ b/example-scene/scene.json @@ -0,0 +1,52 @@ +{ + "ecs7": true, + "runtimeVersion": "7", + "display": { + "title": "SDK7 Scene Template", + "description": "template scene with SDK7", + "navmapThumbnail": "images/scene-thumbnail.png", + "favicon": "favicon_asset" + }, + "owner": "", + "contact": { + "name": "SDK", + "email": "" + }, + "main": "bin/index.js", + "tags": [], + "scene": { + "parcels": [ + "0,0" + ], + "base": "0,0" + }, + "spawnPoints": [ + { + "name": "spawn1", + "default": true, + "position": { + "x": [ + 0, + 3 + ], + "y": [ + 0, + 0 + ], + "z": [ + 0, + 3 + ] + }, + "cameraTarget": { + "x": 8, + "y": 1, + "z": 8 + } + } + ], + "featureToggles": { + "voiceChat": "enabled", + "portableExperiences": "enabled" + } +} \ No newline at end of file diff --git a/example-scene/src/components.ts b/example-scene/src/components.ts new file mode 100644 index 0000000..a3b4e68 --- /dev/null +++ b/example-scene/src/components.ts @@ -0,0 +1,10 @@ +import { Schemas, engine } from '@dcl/sdk/ecs' + + +// We use this component to track and group all spinning entities. +// engine.getEntitiesWith(Spinner) +export const Spinner = engine.defineComponent('spinner', { speed: Schemas.Number }) + +// We use this component to track and group all the cubes. +// engine.getEntitiesWith(Cube) +export const Cube = engine.defineComponent('cube-id', {}) \ No newline at end of file diff --git a/example-scene/src/factory.ts b/example-scene/src/factory.ts new file mode 100644 index 0000000..0a16afd --- /dev/null +++ b/example-scene/src/factory.ts @@ -0,0 +1,42 @@ +import { + Entity, + engine, + Transform, + MeshRenderer, + MeshCollider, + PointerEvents, + PointerEventType, + InputAction, + Material +} from '@dcl/sdk/ecs' +import { Cube, Spinner } from './components' +import { Color4 } from '@dcl/sdk/math' +import { getRandomHexColor } from './utils' + +// Cube factory +export function createCube(x: number, y: number, z: number, spawner = true): Entity { + const entity = engine.addEntity() + + // Used to track the cubes + Cube.create(entity) + + Transform.create(entity, { position: { x, y, z } }) + + // set how the cube looks and collides + MeshRenderer.setBox(entity) + MeshCollider.setBox(entity) + Material.setPbrMaterial(entity, { albedoColor: Color4.fromHexString(getRandomHexColor()) }) + + // Make the cube spin, with the circularSystem + Spinner.create(entity, { speed: 100 * Math.random() }) + + // Create PointerEvent with the hover feedback. + // We are going to check the onClick event on the changeColorSystem. + PointerEvents.create(entity, { + pointerEvents: [ + { eventType: PointerEventType.PET_DOWN, eventInfo: { button: InputAction.IA_POINTER, hoverText: 'Change Color' } } + ] + }) + + return entity +} diff --git a/example-scene/src/index.ts b/example-scene/src/index.ts new file mode 100644 index 0000000..c68f60f --- /dev/null +++ b/example-scene/src/index.ts @@ -0,0 +1,15 @@ +// We define the empty imports so the auto-complete feature works as expected. +import {} from '@dcl/sdk/math' +import { engine } from '@dcl/sdk/ecs' + +import { changeColorSystem, circularSystem } from './systems' +import { setupUi } from './ui' + +export function main() { + // Defining behavior. See `src/systems.ts` file. + engine.addSystem(circularSystem) + engine.addSystem(changeColorSystem) + + // draw UI. Here is the logic to spawn cubes. + setupUi() +} diff --git a/example-scene/src/systems.ts b/example-scene/src/systems.ts new file mode 100644 index 0000000..f98f469 --- /dev/null +++ b/example-scene/src/systems.ts @@ -0,0 +1,40 @@ +import { + engine, + Transform, + inputSystem, + PointerEvents, + InputAction, + PointerEventType, + Material, +} from '@dcl/sdk/ecs' +import { Color4, Quaternion, Vector3 } from '@dcl/sdk/math' +import { Cube, Spinner } from './components' +import { getRandomHexColor } from './utils' + + +/** + * All cubes rotating behavior + */ +export function circularSystem(dt: number) { + const entitiesWithSpinner = engine.getEntitiesWith(Spinner, Transform) + for (const [entity, _spinner, _transform] of entitiesWithSpinner) { + const mutableTransform = Transform.getMutable(entity) + const spinnerData = Spinner.get(entity) + + mutableTransform.rotation = Quaternion.multiply( + mutableTransform.rotation, + Quaternion.fromAngleAxis(dt * spinnerData.speed, Vector3.Up()) + ) + } +} + +/** + * Search for the cubes that has pointerEvents, and when there is a click change the color. + */ +export function changeColorSystem() { + for (const [entity] of engine.getEntitiesWith(Cube, PointerEvents)) { + if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN, entity)) { + Material.setPbrMaterial(entity, { albedoColor: Color4.fromHexString(getRandomHexColor()) }) + } + } +} diff --git a/example-scene/src/ui.tsx b/example-scene/src/ui.tsx new file mode 100644 index 0000000..a2f0fdf --- /dev/null +++ b/example-scene/src/ui.tsx @@ -0,0 +1,79 @@ +import { + engine, + Transform, +} from '@dcl/sdk/ecs' +import { Color4 } from '@dcl/sdk/math' +import ReactEcs, { Button, Label, ReactEcsRenderer, UiEntity } from '@dcl/sdk/react-ecs' +import { Cube } from './components' +import { createCube } from './factory' + +export function setupUi() { + ReactEcsRenderer.setUiRenderer(uiComponent) +} + +const uiComponent = () => ( + + + +