Skip to content
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

Consider supporting user inspector plugins? #523

Open
donmccurdy opened this issue Oct 17, 2017 · 14 comments
Open

Consider supporting user inspector plugins? #523

donmccurdy opened this issue Oct 17, 2017 · 14 comments

Comments

@donmccurdy
Copy link
Member

Hi @fernandojsg

What do you think about letting developers write plugins for the inspector, by having a simple API for attaching their DOM element to a tab?

Some example use cases:

  • Export current scene to glTF or OBJ
  • Search for models from different model libraries
  • Custom animation timeline editor, similar to frame.js
  • Creating and exporting a navmesh derived from the current scene
  • More detailed performance panel, explaining how many entities you have, number of materials, etc.

These all seem like interesting use cases for the inspector, but not necessarily something we'd build and support ourselves. But maybe we could have an API like this?

var el = document.createElement('div');
var btnEl = document.createElement('button');
btnEl.textContent = 'Export Scene';
btnEl.addEventListener('click', () => ...);
el.appendChild(btnEl);

AFRAME.inspector.registerPanel(el, {position: 'bottom'});
@donmccurdy donmccurdy changed the title Consider supporting userland inspector plugins? Consider supporting user inspector plugins? Oct 17, 2017
@dmarcos
Copy link
Member

dmarcos commented Oct 18, 2017

In order for plugins to not be disruptive to the current UI I would probably give them their own panel to render themselves. That panel would be invoked by the user. Idea:

  • A plugins button above the scene graph view (next to the motion capture, save... buttons) that replaces the scene graph view with that of a selected plugin. The drawback would be you could not see multiple plugins or the scene graph and a plugin simultaneously.

@donmccurdy
Copy link
Member Author

Yeah, I think the location is not too critical unless it becomes used for a bunch of fancy stuff. Which would be a good problem to have. Could be a third, new panel that pops up from the bottom of the page as well.

@fernandojsg
Copy link
Member

Actually I started with something called modules a while back when I wanted to create a VR editor mode for the inspector. Basically you register the modules and they can be activated or deactivated. As I didn't continue with the VR editor I've just the dummy module there, but we could use it just as a starting point for something like you propose.
https://github.com/aframevr/aframe-inspector/blob/d3e0a32dfe0a9100386c1e6ec561f3003c48d526/src/lib/modules/dummy/index.js

@fernandojsg
Copy link
Member

@donmccurdy @dmarcos do you have any idea that could be simple enough to use it as an example and as a proof of concept of the plugin system?

@Utopiah
Copy link

Utopiah commented Nov 9, 2017

I'm sure there are quite a few more examples out there so definitely eager to see this.

@donmccurdy
Copy link
Member Author

I think a couple of the ideas in my OP would be simple enough. Namely,

  • Export scene or selected object(s) to glTF
  • More detailed performance panel, explaining how many entities you have, number of materials, etc.

@fernandojsg
Copy link
Member

@donmccurdy I had already added the gltf exporter to the inspector (https://blog.mozvr.com/gltf-exporter-in-three-js-and-a-frame/) but maybe I could just remove it from the main code and use it as a simple use case for the plugin.
I was working also in the inVR inspector mode as a plugin, but it didn't include any panel or UI, just a shortcut to enable/disable it.

I'm not sure how to deal with plugins that will need to include UI as they should be using react instead of plain javascript so it's not something straightforward.

Proposals for implementation welcome :)

@fernandojsg
Copy link
Member

fernandojsg commented Nov 10, 2017

Ok, I'll start checking the @tomas-polach as it seems that it's the only one that it's really implemented without modifying the core (https://github.com/archilogic-com/3dio-inspector-plugins)

@fernandojsg
Copy link
Member

One question, should we have types of plugins and let the editor have a specific behaviour for it? Let's say:

  • tab plugin: the editor will create the tab and handle its visibility, and the plugin will include the component
  • entity: it will add a button probably to the entity panel.
  • component: similar but for component.
  • no visibility: it could modify the viewport, or other things but it doesn't have an UI

Just some quick thoughts about it:

  • pros: User don't need to deal common things like creating or managing the state of the tab, and if we modify something like CSS or so, it will still match. So plugins code will be simplified. And we'll get a better control of them.
  • cons: Probably we'll end up having a use case that we don't have a type of plugin for it, what about raw and you could just do whatever you want at your own responsability?

@donmccurdy
Copy link
Member Author

I had already added the gltf exporter to the inspector

oh, nice! might as well keep it in the main code then.

I'm not sure how to deal with plugins that will need to include UI as they should be using react instead of plain javascript so it's not something straightforward.

IMO that's the only important case; if plugins did not need a UI they wouldn't need to integrate with the inspector.

One question, should we have types of plugins and let the editor have a specific behaviour for it?

My vote would be, all plugins are tab plugins (or some sort of UI panel), and there should be an API so that the plugin can listen for events when the selected entity changes. But I don't think there should be separate types of plugins for entities/components/no-ui.

So really this requires

  1. A DOM element that won't be overwritten by React.
  2. Events when selected entity changes, inspector opens/closes, tab opens/closes, etc.

@tomas-polach
Copy link
Contributor

tomas-polach commented Nov 14, 2017

sry for joining late. this would be a great step forward!! all major editors thrive on community driven plugins. i'm fine with all the proposals as mentioned above and i am looking forward to adapt the 3d.io inspector plugins to fit into the new structure. based on the proposals above, here is my two cents:

Using Plugins

  • could be activated and loaded on demand from separate repos in settings menu: (so that non-coders can activate it easily)

aframe_plugin_menu-01

Writing Plugins

  • exposing the existing module infrastructure (renamed to plugins ?)
  • reducing required params to init and remove
  • providing optional plugin methods like: registerShortcut, registerPanel, registerMenuItem and plugin events
  • an example for a panel performance plugin could then look like this:
AFRAME.inspector.registerPlugin('performance-panel', {

  init: function () {

    // Create Plugin UI

    var myPanel = document.createElement('div');

    function updatePanel () {
      myPanel.innerHTML = AFRAME.inspector.selected.object3D.uuid
    }

    // Regsiter Plugin UI

    this.registerPanel(myPanel, {
      type: 'tab' // might be: 'floating', 'tab', 'tab-widget' ?
    });

    this.registerShortcut(80, () => {
      this.togglePanel();
    }, false);

    this.registerMenuItem('Performance Panel', () => {
      this.showPanel();
    }, false);

    // Plugin Events

    this.on('showpanel', () => {
      updatePanel()
      // bind inspector events when panel becomes visible
      AFRAME.inspector.on('selected', updatePanel)
    }, false);

    this.on('hidepanel', () => {
      // unbind events when panel becomes hidden
      AFRAME.inspector.off('selected', updatePanel)
    }, false);

  },

  // called once when inspetor is closing or plugin has been disabled
  remove: function () {
    // clean up
  }

});

@donmccurdy
Copy link
Member Author

What's the minimum API we can introduce that would let people start experimenting with interesting plugins? I think search/discovery and keybindings might be best left until there are some examples in the wild and plugin authors can perhaps help contribute then.

Suggested:

  1. Fire events on scene when inspector is shown/hidden. (see inspector.js).
  2. Fire events when entity is selected in the LHS sidebar. (perhaps pass the inspector's own events to the scene object?)
  3. Hook to create a persistent DOM element in the inspector's UI. A new bottom panel, perhaps with a named tab for plugins, seems like the easiest place to start.

plugin-mock

@donmccurdy
Copy link
Member Author

Another quick note, more to just keep this in one place... if my plugin needs to scan the scene, filtering the inspector's objects out is a bit of guesswork:

    const content = new THREE.Scene();
    this.sceneEl.object3D.updateMatrixWorld();
    this.sceneEl.object3D.traverse((node) => {
      if (!node.isMesh || node.name.match(/^[XYZE]+|picker$/)) return;
      const clone = node.clone();
      clone.matrix.copy(node.matrixWorld);
      content.add(clone);
    });

... another nice-to-have would be markings (userData, say?) to identify these objects, or a more predictable prefix on the object names.

@donmccurdy
Copy link
Member Author

Also, I'm using a helper component to get around the lack of inspector open/close events, and that's working reasonably well:

AFRAME.registerComponent('inspector-plugin-mything', {
  init: function () {
    const tmpEl = document.createElement('div');
    tmpEl.innerHTML = panelTpl;
    const panelEl = tmpEl.children[0];
    document.body.appendChild(panelEl);
    this.plugin = new MyPlugin(panelEl, this.el);
  },
  pause: function () {
    this.plugin.setVisible(true);
  },
  play: function () {
    this.plugin.setVisible(false);
  }
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants