Scripting the PlayCanvas Editor

@max

So this might seem like a stupid question, but is it possible to write a script that can run in the editor and use the editor’s functionality when the parse button is pressed (the parse button does run the code, doesn’t it?)

No that’s not possible. The only way to run Editor code at the moment is either though the browser console or by writing a browser extension.

Thanks! Saved me a lot of time researching workers :slight_smile:

Reviving the thread just to show how scriptable the PlayCanvas editor can be.

Using the Tiled Terrain Manager to generate a runtime terrain from heightmaps … I was amazed how simple it was to re-use the same codebase in the editor, with minor changes, and generate the exact same terrain for the level designers to use.

The open nature of Javascript combined with the awesomeness the PlayCanvas guys have built in the editor is powerful.

6 Likes

Here is an example script that will position all of your selected entities in the X axis in a sequence.

  1. Select a number of entities in the editor.
  2. Open the browser console.
  3. Adjust the step in the first line, paste the code and execute.
translateChildrenToGrid(3);

function translateChildrenToGrid(step) {
  const type = editor.call("selector:type");

  if (type !== "entity") {
    return false;
  }

  const items = editor.call("selector:items");

  if (!items || items.length === 0) {
    return false;
  }

  items.forEach((item, index) => {
    editor.call("selector:set", "entity", [item]);
    item.set("position", [index * step, 0, 0]);
  });

  console.log("--- Finished execution ---");
}

3 Likes

And another one, I found a missing action in editor: I am unable to assign a material on a Mesh Instance of multiple model assets at the same time. I would have to assign them one after the other.

  1. Select a number of Model assets.
  2. Open the browser console.
  3. Set your Material asset id and Mesh Instance slot, paste the code and execute.

assetModelSetMaterial(15325478, 0);

function assetModelSetMaterial(assetId, slot) {
  const type = editor.call("selector:type");

  if (type !== "asset") {
    return false;
  }

  const items = editor.call("selector:items");

  if (!items || items.length === 0) {
    return false;
  }

  items.forEach((item, index) => {
    item.set("data.mapping." + slot + ".material", assetId);
  });

  console.log("--- Finished execution ---");
}
3 Likes

It’s never too dead to bump the thread.

Generating the terrain in editor is exactly what we’re looking for! Would you still happen to have the modified script?

Not exactly, but I may have something to help you out with that. I’ll get back to you tomorrow on that.

2 Likes

So here is a very easy way to get any script to execute and run inside the PlayCanvas editor. This is an open source framework that enables editor scripting:

With a minimal change in the default runtime terrain script we get it to run and render in the editor:

3 Likes

Marry me!

I was wondering how collision work out with that. Is it created by default? Or does it throw you the map in to assets so you can put it in mesh collider ?

The Uranus Editor SDK loads and executes Ammo.js if it’s included in the project. If the entity uses a collision and rigidbody component, physics will work in editor as well:

2 Likes

Do anyone know how to add a script (not the script component) to an entity via the Editor API?

My question was in thread Scripting the PlayCanvas Editor. I was asking about how to use the editor api to add a script to an entity. for just the script component, i have figured out it’s “editor.call(‘entities:addComponent’, (entity), ‘script’)”, but i can’t figure out how to add script

Hi @SunnyChow, I have some code to showcase that. I am not on desk currently, I’ll post it later today.

Here you go, the following code will add a script component to the selected, in the hierarchy, entity, attach a script type (orbitCamera) and at the same time set the value of an attribute:

var selectedEntity = editor.call('entities:selectedFirst');

editor.call('entities:addComponent', [selectedEntity], 'script');

var script = 'orbitCamera';
selectedEntity.set(`components.script.scripts.${script}`, {
    enabled: true,
    attributes: {
        distanceMax: 90
    }
});
selectedEntity.insert('components.script.order', script);
1 Like

Hi Leonidas,
I’m trying to set the entity attribute through editor code in a script attached to the current selected item.
But I’m getting observer errors, how can i set the entity into my entity attribute field/variable?
For context: in this example i wanted the script to link to itself just for testing, but I’m not sure what type of value it is expecting.

async function setLinkedEntity() {
      const type = editor.call("selector:type");

      if (type !== "entity") {
        return false;
      }

      const items = editor.call("selector:items");

      if (!items || items.length === 0) {
        return false;
      }
      //console.log('items:', editor.call('selector:items')[0].json());

      items.forEach(async (item, index) => {
         editor.call("selector:set", "entity", [item]);
        item.set('components.script.scripts.linkEntity',{
          enabled: true,
          attributes: {
            linked: item
          }
        });    
      });

      console.log("--- Finished execution 7 ---");
    }

Hi @fcsa,

I gave it a try on a project, to reference an entity to an attribute you only need to pass the entity guid.

Example code for a script type named myScript and an attribute named linkEntity:

item.set('components.script.scripts.myScript.attributes.linkEntity', item.get('resource_id'));

This will reference itself.

1 Like

Thank you!

Is there a way to use “drawLine” in the editor viewport?
I have installed violentmonkey’s extension and I find it quite usefull, I was wondering if there was a way to draw helper lines, like we do using this.app.drawLine but in the editor.