Suggestion: Clearer Loader.Handlers API

Description of the problem

Loader.Handlers is used in four high-level asset loaders (glTF, FBX, MTL, MMD) under examples/js/loaders for providing an API that allows the use of custom texture (or other type of low-level assets) loader in them. For example, users can override regular TextureLoader with custom texture loader supporting ImageBitmap and/or compressed texture.

Example code.

function CustomTextureLoader() {
}

CustomTextureLoader.prototype.load = function ( url, onLoad, onProgress, onError ) {
    ...
};

THREE.Loader.Handlers.add( /\.(png|jpg|jpeg)$/, new CustomTextureLoader() );

var loader = THREE.GLTFLoader();
loader.load( ... ); // CustomTextureLoader used inside instead of regular TextureLoader

I think current Loader.Handlers API has a problem. It’s very unclear for users how and where added handler is used because no clear documents and THREE.Loader.Handlers is global scope. Even if we document, users still need to read through the document and carefully add handler to let only the target high-level asset loader use the custom low-level loader inside. Unless carefully doing that, the custom low-level loader can be unexpectedly used by other high-level asset loaders because Loader.Handler is global scope.

I think loader scope Handlers is better than global scope. Easier to understand and control for users.

Two ideas in my mind.

  1. Move handlers to LoadingManager method. #15935 (comment)

Pros: No need to add new public method to any high-level loaders.
Cons: Users need to read loader’s document to know how added handler is used inside.

// user code
var manager = new THREE.LoadingManager();
manager.addHandler( /\.(png|jpg|jpeg)$/, new CustomTextureLoader() );
var loader = new THREE.FooLoader( manager );
loader.load( ... );

// in FooLoader
FooLoader.prototype.varFunction = function () {
    var textureLoader = this.manager.getHandler( imageUrl );
    if ( textureLoader === null ) textureLoader = new THREE.TextureLoader( this.manager );
    textureLoader.load( ... );
};
  1. Each asset loader explicitly has overriding loader method with clear name. #15919 (comment)

Pros: Easier to understand for users.
Cons: We need to add new public method to each high-level asset loader.

// user code
var loader = new THREE.FooLoader();
loader.setCustomTextureLoader( new CustomTextureLoader() );

// in FooLoader
FooLoader.prototype.setCustomTextureLoader = function ( loader ) {
    this._textureLoader = loader;
};

FooLoader.prototype.varFunction = function () {
    var textureLoader = this._textureLoader || new THREE.TextureLoader( this.manager );
    textureLoader.load( ... );
}

I prefer 2. Any thoughts?

My personal short term goal is having clear API which enables ImageBitmap in GLTFLoader.

Three.js version
  • Dev
  • r102
Browser
  • All of them
  • Chrome
  • Firefox
  • Internet Explorer
OS
  • All of them
  • Windows
  • macOS
  • Linux
  • Android
  • iOS
Hardware Requirements (graphics card, VR Device, …)

Author: Fantashit

1 thought on “Suggestion: Clearer Loader.Handlers API

  1. I vote for option one. Removing Loader.Handlers is definitely a good thing since the respective API feels a bit inconsistent compared to the rest of the engine.

    LoadingManager is a class for managing the loading process. That means counting requests and tracking their status, modifying URLs and probably defining handlers for certain file extensions. Hence, moving the logic of Handlers to LoadingManager by adding the following methods is my preferred approach.

    • .addHandler()
    • .removeHandler()
    • .getHandler()

Comments are closed.