MCPcopy Index your code
hub / github.com/decentraland/decentraland-ecs-utils

github.com/decentraland/decentraland-ecs-utils @1.7.5

Chat with this repo
repository ↗ · DeepWiki ↗ · release 1.7.5 ↗ · + Follow
225 symbols 373 edges 23 files 17 documented · 8% updated 22d ago1.7.5 · 2021-09-24★ 333 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

decentraland-ecs-utils

This library includes a number of helpful pre-built tools that include components, methods, and systems. They offer simple solutions to common scenarios that you're likely to run into.

Using the Utils library

To use any of the helpers provided by the utils library

  1. Install it as an npm package. Run this command in your scene's project folder:
npm install @dcl/ecs-scene-utils -B
  1. Run dcl start or dcl build so the dependencies are correctly installed.

3) Import the library into the scene's script. Add this line at the start of your game.ts file, or any other TypeScript files that require it:

import * as utils from '@dcl/ecs-scene-utils'
  1. In your TypeScript file, write utils. and let the suggestions of your IDE show the available helpers.

Gradual Movement

Move an entity

To move an entity over a period of time, from one position to another, use the MoveTransformComponent component.

MoveTransformComponent has three required arguments:

  • start: Vector3 for the start position
  • end: Vector3 for the end position
  • duration: duration (in seconds) of the translation

This example moves an entity from one position to another over 2 seconds:

import * as utils from '@dcl/ecs-scene-utils'

// Create entity
const box = new Entity()

// Give entity a shape and transform
box.addComponent(new BoxShape())
box.addComponent(new Transform())

//Define start and end positions
let StartPos = new Vector3(1, 1, 1)
let EndPos = new Vector3(15, 1, 15)

// Move entity
box.addComponent(new utils.MoveTransformComponent(StartPos, EndPos, 2))

// Add entity to engine
engine.addEntity(box)

Follow a path

To move an entity over several points of a path over a period of time, use the FollowPathComponent component.

FollowPathComponent has two required arguments:

  • points: An array of Vector3 positions that form the path.
  • duration: The duration (in seconds) of the whole path.

This example moves an entity over through four points over 5 seconds:

import * as utils from '@dcl/ecs-scene-utils'

// Create entity
const box = new Entity()

// Give entity a shape and transform
box.addComponent(new BoxShape())
box.addComponent(new Transform())

//Define the positions of the path
let path = []
path[0] = new Vector3(1, 1, 1)
path[1] = new Vector3(1, 1, 15)
path[2] = new Vector3(15, 1, 15)
path[3] = new Vector3(15, 1, 1)

// Move entity
box.addComponent(new utils.FollowPathComponent(path, 2))

// Add entity to engine
engine.addEntity(box)

Follow a curved path

To move an entity following a curved path over a period of time, use the FollowCurvedPathComponent component.

The curved path is composed of multiple straight line segments put together. You only need to supply a series of fixed path points and a smooth curve is drawn to pass through all of these.

FollowCurvedPathComponent has three required arguments:

  • points: An array of Vector3 positions that the curve must pass through.
  • duration: The duration (in seconds) of the whole path.
  • numberOfSegments: How many straight-line segments to use to construct the curve.

Tip: Each segment takes at least one frame to complete. Avoid using more than 30 segments per second in the duration of the path, or the entity will move significantly slower while it stops for each segment.

This example moves an entity over through a curve that's subdivided into 40 segments, over a period of 5 seconds. The curve passes through four key points.

import * as utils from '@dcl/ecs-scene-utils'

// Create entity
const box = new Entity()

// Give entity a shape and transform
box.addComponent(new BoxShape())
box.addComponent(new Transform())

//Define the positions of the path
let path = []
path[0] = new Vector3(1, 1, 1)
path[1] = new Vector3(1, 1, 15)
path[2] = new Vector3(15, 1, 15)
path[3] = new Vector3(15, 1, 1)

// Move entity
box.addComponent(new utils.FollowCurvedPathComponent(path, 5, 40))

// Add entity to engine
engine.addEntity(box)

The FollowCurvedPathComponent also lets you set:

  • turnToFaceNext: If true, the entity will rotate on each segment of the curve to always face forward.
  • closedCircle: If true, traces a circle that starts back at the beginning, keeping the curvature rounded in the seams too

Rotate an entity

To rotate an entity over a period of time, from one direction to another, use the rotateTransformComponent component, which works very similarly to the MoveTransformComponent component.

rotateTransformComponent has three required arguments:

  • start: Quaternion for the start rotation
  • end: Quaternion for the end rotation
  • duration: duration (in seconds) of the rotation

This example rotates an entity from one rotation to another over 2 seconds:

import * as utils from '@dcl/ecs-scene-utils'

// Create entity
const box = new Entity()

// Give entity a shape and transform
box.addComponent(new BoxShape())
box.addComponent(new Transform())

//Define start and end directions
let StartRot = Quaternion.Euler(90, 0, 0)
let EndRot = Quaternion.Euler(270, 0, 0)

// Rotate entity
box.addComponent(new utils.RotateTransformComponent(StartRot, EndRot, 2))

// Add entity to engine
engine.addEntity(box)

Sustain rotation

To rotates an entity continuously, use KeepRotatingComponent. The entity will keep rotating forever until it's explicitly stopped or the component is removed.

KeepRotatingComponent has one required argument:

  • rotationVelocity: A quaternion describing the desired rotation to perform each second second. For example Quaternion.Euler(0, 45, 0) rotates the entity on the Y axis at a speed of 45 degrees per second, meaning that it makes a full turn every 8 seconds.

The component also contains the following method:

  • stop(): stops rotation and removes the component from any entities its added to.

In the following example, a cube rotates continuously until clicked:

import * as utils from '@dcl/ecs-scene-utils'

// Create entity
const box = new Entity()

// Give entity a shape and transform
box.addComponent(new BoxShape())
box.addComponent(new Transform({ position: new Vector3(1, 1, 1) }))

// Rotate entity
box.addComponent(new utils.KeepRotatingComponent(Quaternion.Euler(0, 45, 0)))

// Listen for click
box.addComponent(
  new OnClick(() => {
    box.getComponent(utils.KeepRotatingComponent).stop()
  })
)

// Add entity to engine
engine.addEntity(box)

Change scale

To adjust the scale of an entity over a period of time, from one size to another, use the ScaleTransformComponent component, which works very similarly to the MoveTransformComponent component.

ScaleTransformComponent has three required arguments:

  • start: Vector3 for the start scale
  • end: Vector3 for the end scale
  • duration: duration (in seconds) of the scaling

This example scales an entity from one size to another over 2 seconds:

import * as utils from '@dcl/ecs-scene-utils'

// Create entity
const box = new Entity()

// Give entity a shape and transform
box.addComponent(new BoxShape())
box.addComponent(new Transform())

//Define start and end positions
let StartSize = new Vector3(1, 1, 1)
let EndSize = new Vector3(0.75, 2, 0.75)

// Move entity
box.addComponent(new utils.ScaleTransformComponent(StartSize, EndSize, 2))

// Add entity to engine
engine.addEntity(box)

Non-linear changes

All of the translation components, the MoveTransformComponent, rotateTransformComponent, ScaleTransformComponent, and FollowPathComponent have an optional argument to set the rate of change. By default, the movement, rotation, or scaling occurs at a linear rate, but this can be set to other options.

The following values are accepted:

  • Interpolation.LINEAR
  • Interpolation.EASEINQUAD
  • Interpolation.EASEOUTQUAD
  • Interpolation.EASEQUAD
  • Interpolation.EASEINSINE
  • Interpolation.EASEOUTSINE
  • Interpolation.EASESINE
  • Interpolation.EASEINEXPO
  • Interpolation.EASEOUTEXPO
  • Interpolation.EASEEXPO
  • Interpolation.EASEINELASTIC
  • Interpolation.EASEOUTELASTIC
  • Interpolation.EASEELASTIC
  • Interpolation.EASEINBOUNCE
  • Interpolation.EASEOUTEBOUNCE
  • Interpolation.EASEBOUNCE

The following example moves a box following an ease-in rate:

box.addComponent(
  new utils.MoveTransformComponent(
    StartPos,
    EndPos,
    2,
    null,
    utils.InterpolationType.EASEINQUAD
  )
)

Callback on finish

All of the translation components, the MoveTransformComponent, rotateTransformComponent, ScaleTransformComponent, FollowPathComponent, and FollowCurvedPathComponent have an optional argument that executes a function when the translation is complete.

  • onFinishCallback: function to execute when movement is done.

The following example logs a message when the box finishes its movement. The example uses MoveTransformComponent, but the same applies to rotateTransformComponent and ScaleTransformComponent.

box.addComponent(
  new utils.MoveTransformComponent(StartPos, EndPos, 2, () => {
    log('finished moving box')
  })
)

The FollowPathComponent has a two optional arguments that execute functions when a section of the path is complete and when the whole path is complete.

  • onFinishCallback: function to execute when movement is complete.

  • onPointReachedCallback: function to execute when each section of the path is done.

The following example logs a messages when the box finishes each segment of the path, and another when the entire path is done.

box.addComponent(
  new utils.FollowPathComponent(
    path,
    2,
    () => {
      log('finished moving box')
    },
    () => {
      log('finished a segment of the path')
    }
  )
)

Toggle

Use the ToggleComponent to switch an entity between two possible states, running a same function on every transition.

The ToggleComponent has the following arguments:

  • startingState: Starting state of the toggle (ON or OFF)
  • onValueChangedCallback: Function to call every time the toggle state changed.

It exposes three methods:

  • toggle(): switches the state of the component between ON and OFF
  • isOn(): reads the current state of the component, without altering it. It returns a boolean, where true means ON.
  • setCallback(): allows you to change the function to be executed by onValueChangedCallback, for the next time it's toggled.

The following example switches the color of a box between two colors each time it's clicked.

import * as utils from '@dcl/ecs-scene-utils'

// Create entity
const box = new Entity()

// Give entity a shape and transform
box.addComponent(new BoxShape())
box.addComponent(new Transform())

//Define two different materials
let greenMaterial = new Material()
greenMaterial.albedoColor = Color3.Green()
let redMaterial = new Material()
redMaterial.albedoColor = Color3.Red()

// Add a Toggle component
box.addComponent(
  new utils.ToggleComponent(utils.ToggleState.Off, value => {
    if (value == utils.ToggleState.On) {
      //set color to green
      box.addComponentOrReplace(greenMaterial)
    } else {
      //set color to red
      box.addComponentOrReplace(redMaterial)
    }
  })
)

//listen for click on the box and toggle it's state
box.addComponent(
  new OnClick(event => {
    box.getComponent(utils.ToggleComponent).toggle()
  })
)

// Add entity to engine
engine.addEntity(box)

Combine Toggle with Translate

This example combines a toggle component with a move component to switch an entity between two positions every time it's clicked.

import * as utils from '@dcl/ecs-scene-utils'

// Create entity
const box = new Entity()

// Give entity a shape and transform
box.addComponent(new BoxShape())
box.addComponent(new Transform())

//Define two positions for toggling
let Pos1 = new Vector3(1, 1, 1)
let Pos2 = new Vector3(1, 1, 2)

//toggle for wine bottle
box.addComponent(
  new utils.ToggleComponent(utils.ToggleState.Off, value => {
    if (value == utils.ToggleState.On) {
      box.addComponentOrReplace(
        new utils.MoveTransformComponent(Pos1, Pos2, 0.5)
      )
    } else {
      box.addComponentOrReplace(
        new utils.MoveTransformComponent(Pos2, Pos1, 0.5)
      )
    }
  })
)

//listen for click on the box and toggle it's state
box.addComponent(
  new OnClick(event => {
    box.getComponent(utils.ToggleComponent).toggle()
  })
)

// Add entity to engine
engine.addEntity(box)

Time

These tools are all related to the passage of time in the scene.

Delay a function

Use the setTimeout function to delay the execution of a function by a given amount of milliseconds.

This function requires two fields:

  • ms: How many milliseconds to delay the

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Method 139
Class 52
Function 29
Interface 3
Enum 2

Languages

TypeScript100%

Modules by API surface

src/triggers/triggerSystem.ts59 symbols
src/actionsSequenceSystem/actionsSequenceSystem.ts58 symbols
src/transform/math/interpolation.ts19 symbols
src/transform/component/followpath.ts12 symbols
src/transform/system/transfromSystem.ts8 symbols
src/toggle/toggleComponent.ts8 symbols
src/timer/system/timerSystem.ts8 symbols
src/transform/component/keeprotating.ts7 symbols
src/transform/component/scale.ts6 symbols
src/transform/component/rotate.ts6 symbols
src/transform/component/move.ts6 symbols
src/transform/component/itransformcomponent.ts4 symbols

For agents

$ claude mcp add decentraland-ecs-utils \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page