Coder Social home page Coder Social logo

threejs / three-devtools Goto Github PK

View Code? Open in Web Editor NEW
602.0 602.0 80.0 5.46 MB

three.js devtools

Home Page: https://chrome.google.com/webstore/detail/threejs-developer-tools/ebpnegggocnnhleeicgljbedjkganaek

License: MIT License

CSS 0.84% HTML 0.05% JavaScript 98.94% Shell 0.18%

three-devtools's People

Contributors

dependabot[bot] avatar jacobcoughenour avatar jsantell avatar mrdoob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

three-devtools's Issues

[meta] Geometry view

Broadly this is unimplemented. We could should a preview of the mesh as well.

Support scene backgrounds

Reproducible on model-viewer examples: https://googlewebcomponents.github.io/model-viewer/examples/lighting-and-environment.html

This prevents loading additional scene content AFAICT and results in an inaccurate view of the scene.

5CD06464-8015-40EC-B682-7BD3368967A4 does not appear to be serializable. TypeError: this.background.toJSON is not a function
    at ModelScene.toJSON (three.module.js:25345)
    at Object.serializeEntity (<anonymous>:77:50)
    at EventTarget.__requestEntity (<anonymous>:234:20)
    at <anonymous>:1:15

Filter/search

There should be an easy way to filter scene/resource views by name/type; a search against a handful of entity properties. Potentially its dependents as well, e.g. a "MeshStandardMaterial" search could reveal objects in the scene graph that use a standard material.

Tools are unusable if any unserializable objects are in the scene

Adjacent to #16, any scene with an object that cannot be serialized (WebGLRenderTarget, DataTexture, InterleavedBufferAttribute) throws an error during serialization, preventing any information from the scene being parseable without reimplementing toJSON(), which is something I'd like to avoid.

While a stretch goal would be to somehow interpret these dynamic objects, the minimum needed in order for a scene to be debugged would be for these unserializable objects to return stubs (e.g. { width, height, type } for WebGLRenderTarget maybe), or less preferably, skipped during serialization (I'd rather be aware of the objects and not be able to represent them fully).

Requires a handful of fixes upstream:

Add preview value element for geometry.

In the Parameters view, geometry should show a preview(?) and click through to select the corresponding geometry. It does not have to update if the underlying geometry is updated. Upon object selection, the geometry will be fetched and accessible via ContentBridge.

Injection mechanism/API Design

More information on current injection mechanism and proposals documented in DEVELOPMENT.md:

Why is injection so weird?

Content scripts have access to the DOM, but cannot access any globals from user-land script (e.g. code from script elements on a page). In order to access the three.js entities on the page, an additional script needs to be injected as if it were regular user-land script, by literally injecting a <script> element with our injection code.

There are a few options to handle this.

  • Synchronous injection at document_start
    • This is the current implementation. Non-ideal as this is evaluated on every page load, and injecting content on every page load. This is what redux-devtools does, with a rather large content script. The challenge here is defining some object in the user context immediately (window.ThreeDevTools) so that content can access it, even if it's defined in the <head>.
    • I attempted a system where opening devtools lands a cookie allowing that domain to inject content for the next few minutes, as cookies can be checked synchronously to determine if injection is needed. Was flaky, but due to extension confusion I think.
    • The global indicates that the extension is installed, not open, if that matters to the content.
    • Need to set text content rather than src of injection script to guarantee sync inject (#1).
  • Port messaging
    • Something like window.postMessage({ type: 'three-devtools-connect' }) that doesn't need to exist in global space before content runs, so synchronous code injection no longer needed.
    • Could have a purely postMessage API and no global.
    • Less inspectable than a singleton
    • Moves code from injected code to content script code -- could the extra content script be lazily brought in on first sign of a post message?

Opening this issue for discussion on alternatives to this injection mechanism, as well as API design.

Support textures from WebGLRenderTarget in TextureView

We'll need to dump this out from the render target itself since it doesn't have an image value with an Image, but instead references a texture on the GPU. We'll need to render this out in content before sending it over the wire

Screenshot from 2019-05-23 09-53-28

Manually refresh a view

It should be possible to manually refresh a view. Currently when opening a view of some entity, most views will request the latest data. If the object updates, the user should be able to manually request an update.

This could be helpful for the scene, resource and entity views

[meta] Resources View

What changes are needed here?

Currently resources will show all resources from all scenes, as entities can be shared across scenes. We could make resources a child of a scene, and possibly toggling between the 'graph' view and the 'resources' view.

Opening this issue for general discussion/ideas.

Broken chrome web store link

For me the link to the chrome web store is broken. I don't find the extension either by manually searching for "three.js".

"Uncaught Error: Extension context invalidated."

src/extensions/contentScript.js:57 throws "Uncaught Error: Extension context invalidated." after the devtools are reloaded. Maybe a nice way to handle this other than wrap in a try/catch. Probably only happens to folks developing on the extension itself. But this pollutes up the console, as well as warnings in chrome://extensions

Tool leads to memory leakage

Please see mrdoob/three.js#18759 (comment)

TL;DR just by installing and enabling this tool AND NOT using API in the app code in any way memory leakage is created. That leads to false assumptions when developing app based on Three.js. My assumption was first that my code leaks, then that Three.js lib has bug - based on latest tests leakage occurs when this tool is installed in Chrome.

[meta] Handle large assets/scenes

This broadly needs more investigation.

  • An object with many children can jank the tree view
  • Refreshing some objects may cause a new toJSON() cycle in content, potentially causing large amounts of jank from serializing and sending giant strings of textures or buffers
  • Right now an entire scene is serialized on first request; should there be a difference between requesting the "overview" of an entity and the "data" (e.g. potentially very large base64 strings or buffers), and access the larger data lazily when needed?
  • If we wanted to modify the built in toJSON method for some type, like to only serialize the first n children, is there a way to do that without having to duplicate/rewrite the serialization logic for objects, materials, textures, etc...
  • Are we conservative in sending data over the wire? I think there's a duplicate request somewhere at least.
  • In the devtools, a comparison occurs to determine whether or not to emit an 'update' event -- can this be moved to the content and get rid of unnecessary wire transfers?

Downloading objects/scenes

An option for downloading objects or scenes for further inspection in the editor would be nice.

I'm currently using this snippet in the inspector that I run every time I want to download the scene.

let main = window.g_main || window.main;
let scene = main.game.scene;
scene.traverse(obj => obj.updateMatrix());
let str = JSON.stringify(scene.toJSON());
let aEl = document.createElement('a');
aEl.setAttribute("href", window.URL.createObjectURL(new Blob([str], {type: 'text/plain'})));
aEl.setAttribute("download", "scene.json");
aEl.click();

But it depends on g_main.game.scene existing. It would be nice to have a more general solution.

[meta] Renderer View

Right now this is not styled at all, and polls for data every second on the current renderer. Some things that are needed:

  • Styling
  • Select current renderer
  • [stretch goals] control animation loop (stop/play) and provide a new camera for something like a debugging third-person-view for a scene

Handle changes to the scene after initial serialization

Reproducible on many model-viewer demos since everything is loaded magically, need to determine when to reserialize and flush new data. Right now, content can be stale.

The early abort in __requestEntity in content is a part of the culprit at least.

We don't want to be over eager and push any changes, but it's easy to be in a scenario viewing a scene and something is added to it after the initial load. Adding a manual refresh would be great, but that seems like a bit much for some cases where it'll be the default. Maybe something like, for new scenes, we poll for changes for the first n seconds? Changing the current scene for example will refresh.

Remember selection/position upon reload

Reloading is a part of the development cycle, requiring reloading the tools often. It should return to the previous layout, and attempt to select the previously selected entity.

Potential issues:

  • The previously selected entity may not yet exist at tool load time
    • Need some kind of heuristic, like select previous entity if no selection has yet been made at time the previously selected entity was discovered
  • There's no unique mapping between reloads
    • More heuristics: If entity is tagged with a name, that may be used, but still not guaranteed to be unique. Can determine similarity via serialization, although that's dynamic as well. How consistently are objects IDs the same between reloads?
    • For resources (materials, textures) these are probably going to be easier than with Object3Ds.
    • Developer communication: could encourage devs to always use

This is an important but tricky one.

WebGLInfo display is inaccurate for effects pass

Using composer/effects pass and other renders requires manually setting reset on renderer.info for accurate draw counts. It'd be useful to provide information pointing to that in the docs if the numbers don't look right, or maybe if there's only 2 triangles being rendered as a common pattern.

Lazily request renderer data

Right now it's being streamed during render, nonstop. Once moving renderer to a new view, this should only be pulled when in use (e.g. debugging rendering/perf, not viewing the scene graph)

Resizable panels

Tool should allow resizing, and the remembering, of the main panels in the tool.

[meta] Support all object types in Object View

Currently the Object View supports values from Object3D and Mesh; Lights, lines, helpers, and skeleton/bones are not yet supported. Could possibly implement these as subclasses of the Object View, or pile it all in the view, like Material View.

Key value view not displaying some types in some cases

For example, here, the materials' wireframe property is not properly rendering as a boolean (checkbox) and other wireframe properties, but not limited to those. Same with environment values (which I know there were some changes recently, but these values are still supported in standard materials).

Screenshot from 2020-06-30 09-56-51

Add preview value element for Materials

In the Parameters view, the material should show a preview and click through to select the corresponding material. It does not have to update if the underlying material is updated. Upon object selection, the material will be fetched and accessible via ContentBridge.

Vestigial MaterialValueElement lives at src/app/values/MaterialValueElement.js.

Content should have a way of defining a selected scene/renderer/entity

If three.js registers all scenes/renderers automatically, or working with many scenes, it should be possible for content to define what the "primary" scene is, or a way to select a new scene, e.g.:

window.ThreeDevTools.select(scene);

Similarly, if I'm debugging some Object that's deeply nested, on page reload I want to select the same object on load. Remembering that object could be handled across page load (inconsistent UUIDs may make that a challenge, but should be doable), but that's a slightly different case of defining it via content, which resets to a specific state on reload, and also provides a way for devs to interface with the tools via console

window.ThreeDevTools.select(myObject);

Add preview value element for textures.

In the Parameters view, the texture should show a preview and click through to select the corresponding texture. It does not have to update if the underlying texture is updated. Upon material (or object) selection containing the texture, the texture will be fetched and accessible via ContentBridge.

CSP breaks injection

Content Security Policy: The page’s settings blocked the loading of a resource at inline (“script-src”).

Because the contentScript.js injects a payload into the user-space to access the Three objects, CSP settings can prevent inline script injections. No immediately solutions come to mind for debugging arbitrary three scenes, although we might be able to tag the script such that site owners can make an exception to the injected code (maybe by not inlining it and instead reference the allowlisted extension source, maybe an SRI attribute although that'd change for every release).

Codify the parameters view

There should be a data structure showing which properties of which types of entities to display. May need to use ObjectLoader, since the serialization process assumes use with ObjectLoader, and leaves out properties otherwise e.g. "foo" is 1 by default for ObjectType, so it's not in the JSON payload, but hydrated as "1" when going through the ObjectLoader.

Mostly refactoring, but will result in a more consistent parameter view since the individual views for these are pretty messy.

[meta] Implement remaining materials in MaterialView

A handful of material types are not yet supported in MaterialView; they're displayed and showed, but any subclass material properties or defaults are not handled for the following types:

  'MeshDistanceMaterial': 'distance',
  'MeshMatcapMaterial': 'matcap',
  'MeshNormalMaterial': 'normal',
  'MeshPhongMaterial': 'phong',
  'PointsMaterial': 'points',
  'ShadowMaterial': 'shadow',
  'SpriteMaterial': 'sprite',
  'RawShaderMaterial': 'raw',
  'ShaderMaterial': 'shader',

Logging management

Right now there are a lot of logs everywhere. It's helpful getting some of that information, even in non-development, and could be helpful displaying some information in the main content window. Either way, the sporadic logging should be cleaned up, and a consistent, smart logging system should be put in its place.

Lazy Serialization

Serialization is what blocks rendering on the content (often twice: once for the toJSON() call and once for the postMessage(), which seems roughly about three times the size of the toJSON()). This can be observed in Chromium's violation warnings. For example, this example with geometry with position, size, and color attributes results in the warning, where 'refresh' is the serialization and 'message' is passing that to the extension:

[Violation] 'refresh' handler took 179ms
[Violation] 'message' handler took 574ms

This may be a prereq for #33, since we'll be able to more aggressively sync with content without incurring long jank times.

Strategies

With circumventing three's serialization in #31, a cache can be injected here for costly objects if the meta object has some flag. That way, when serializing a scene for example, any 'expensive' objects will only return their basic structured data, minus expensive properties.

The objects can be fully serialized as needed when the corresponding object is being inspected.

Expensive items AFAIK:

  • Texture's image
  • Geometry's BufferAttributes
  • Uniforms (which may be textures or buffers)

Pre-emptive Texture Serialization

Since textures aren't generally changing, especially when loaded from an image, we can also serialize these up front. Canvas, WebGLRenderTargets, data textures and video textures are a bit different, but for the most part, serializing once initially should be sufficient, and significantly decrease future serialization costs. For the special texture cases, they can be refreshed when that texture is being inspected. This gives the ability to render texture previews, for example, before a specific texture is inspected.

[meta] Support additional values

The "Value" type elements are inline elements that can display data, and optionally allow edits.

For example, on the right side there are value elements for uneditable strings, enums, boolean, color.
Screenshot from 2019-05-23 09-44-36

More complex data structures can be represented, like a Material (below) or textures. Note that plumbing exists so that the value elements can be used as a preview (e.g. Material right now displays as a block with whatever color the material has set)

Screenshot from 2019-05-23 09-47-19

There is a lot of styling love needed, as well as supporting more complex data structures, like vec2/vec3/vec4 and matrices.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.