1.1.0
A Sinewav3 Plugin consists of:
All of the above are created in the Sinewav3 Plugin editor.
Settings are defined and grouped by the developer, then exposed to the user for modification in the Project editor, both in list mode and while the visualizer runs. Consequently, it is important to watch for changes to Setting values not only in your Plugin's setup() function, but also in render().
Each function belonging to a Plugin has access to:
All of this available via the VisualizerContext, passed to each Plugin function as the argument named context.
The Plugin developer's primary interface to the Sinewav3 visualizer
It solves several problems, including:
1) Your Plugin's setup(), render(), and destroy() methods are just anonymous functions that get invoked when required. They need a way to remember things.
2) The World that your Plugin is a part of may have any number of other Plugins actively manipulating objects in the Scene. You don't want them inadvertently affecting your objects though. Or vice versa.
3) Since the user may enter and exit multiple projects during a Sinewav3 session, we must be wary of memory leaks that occur when things aren't properly destroyed.
For these reasons, rather than permit working directly with the THREE.js Scene, the VisualizerContext acts as a mediator between your Plugin's code and the World it is a part of.
The benefits are:
You can store values and functions and make them available across function invocations, access and modify your own Scene objects, and if you register each Geometry, Material, or Object3D you create in setup() or render(), you can later recall them from the VisualizerContext by name. As a bonus, those registered items will be automatically disposed of by the visualizer, in most cases obviating the need for a destroy() function in your Plugin.
The PluginContext instance.
This is the Plugin developer's interface to the Plugin's settings.
Type: PluginContext
The ModulatorContext instance.
This is the Plugin developer's interface to the modulation sources.
Type: ModulatorContext
Plugin memory object
Because setup(), render(), and destroy() are anonymous functions, invoked as needed, a facility is required for remembering values or functions between invocations.
For instance, a function can be created once in setup(), stored on context.memory, and called within each render() invocation. This is faster than declaring the function inside the render function on each frame.
Similarly, a rotation value could be stored in a variable on context.memory, and then retrieved, used, and incremented within each render() invocation.
Type: Object
Scene Objects
These are just the objects your Plugin instance has added to the World's scene, not all the objects in the scene.
Type: Array
Renderer Dimensions
Has width and height properties representing the current dimensions of the renderer. The renderer dimensions react to browser resize during visualization but are fixed during video rendering.
Type: Object
Get the visualizer's THREE.WebGLRenderer instance
Caution is advised here.
You do not need to set width and height of the renderer, as that's handled by the visualizer. Also, by default, clearColor is set to 0xffffff, and antiAlias to true.
Beyond the basics, there are other things you may need to configure for desired operation of your plugin, e.g., shadowMap, which make it unreasonable for us to restrict access to this important component.
Therefore, make sure you Understand any changes you make to the renderer, as it affects the scene for all plugins.
Get the world's camera
This function is intended for Plugins that exclusively manipulate the camera to perform configurable position, rotation, FOV adjustment, or movement functions such as pan or dolly.
Plugin developers should keep in mind that there is just one camera to view a World with, and so the visibility of other Plugins in that World's Scene may be affected by any camera manipulations you do. Therefore, be sure to mention any camera manipulation that your Plugin does in its description.
CAUTION: You must not store a reference to the camera, because the user can change its type during visualization, causing it to be replaced with a different object. Therefore you must use this method anytime you wish to access the world's camera.
EXAMPLE:
setup(context) { // Store a function to be used each time render() is called context.memory.transform = function(cam) { let x, y, z; if ( context.plugin.getSettingValue('Rotate','Auto Rotate') ) { x = cam.rotation.x + context.plugin.getSettingValue('Rotate','X Rot Speed'); y = cam.rotation.y + context.plugin.getSettingValue('Rotate','Y Rot Speed'); z = cam.rotation.z + context.plugin.getSettingValue('Rotate','Z Rot Speed'); cam.rotation.set(x, y, z); } x = context.plugin.getSettingValue('Translate','X Pos'); y = context.plugin.getSettingValue('Translate','Y Pos'); z = context.plugin.getSettingValue('Translate','Z Pos'); cam.position.set(x, y, z); }; } render(context) { // Fetch the camera and transform it on each frame let cam = context.getCamera(); context.memory.transform(cam); }
Object
:
A
THREE.Camera
instance
Get the world's ambient light
Example:
// Adjust Ambient Light let ambientLight = context.getAmbient(); ambientLight.color = new THREE.Color( 0x808080 ); ambientLight.intensity = .5;
Object
:
An instance of
THREE.AmbientLight
Remove a previously added object from the scene
Register a material
Registered materials can later be retrieved by name and will be automatically disposed of when the visualizer exits.
(string)
A unique name for the material instance, used for retrieval with getMaterial()
Retrieve a previously registered material
(string)
The unique name of the material to retrieve
Object
:
An instance of a subclass of
THREE.Material
i.e., MeshLambertMaterial
Register a texture
Registered textures can later be retrieved by name and will be automatically disposed of when the visualizer exits.
Textures that are configured via Plugin settings will automatically be loaded, created, and registered using the setting name and can be retrieved immediately in setup() or render() using getTexture().
(string)
A unique name for the texture instance, used for retrieval with getTexture()
Retrieve a previously registered texture
(string)
The unique name of the texture to retrieve
Object
:
An instance of a subclass of
THREE.Texture
Register a geometry
Registered geometries can later be retrieved by name and will be automatically disposed of when the visualizer exits.
(string)
A unique name for the geometry instance, used for retrieval with getGeometry()
Get a previously registered geometry
(string)
The unique name of the geometry to retrieve
Object
:
An instance of
THREE.Geometry
or a subclass thereof
Register a 3D object
Registered 3D objects can later be retrieved by name and will be automatically disposed of when the visualizer exits.
3D Objects that are configured (as 3D Models) via Plugin settings and will automatically be loaded, created, and registered using the setting name and can be retrieved immediately in setup() or render() using getObject3D().
(string)
A unique name for the 3D object instance, used for retrieval with getObject3D()
Get a previously registered 3D object
(string)
A unique name of the 3D object instance to retrieve
Object
:
An instance of
THREE.Object3D
or a subclass thereof
Register a font
Registered fonts can later be retrieved by name and will be automatically disposed of when the visualizer exits.
Fonts are always configured via Plugin settings, will automatically be loaded, created, and registered using the setting name, and can be retrieved immediately in setup() or render() using getFont(). Consequently, developers should never have to use this method.
Fonts must be in JSON format.
(string)
A unique name for the font instance, used for retrieval with getFont()
Get a previously registered font
(string)
The unique name of the font instance to retrieve
Object
:
An instance of
THREE.Font
Add a material to all mesh children of the object
Set the background for the scene. Can be set to one of the following:
(Object)
the background for the scene
The Plugin developer's interface to the Plugin's settings.
A reference to the PluginContext is available to all Plugins via the VisualizerContext as context.plugins.
Inside any of the Plugin's functions, you can read the settings and take appropriate action in response.
The Plugin developer's interface to the modulation sources.
A reference to the ModulatorContext is available to all Plugins in a given world via the VisualizerContext as context.modulators.
Modulator values change over time and can be used to modulate various aspects of a Plugin's output.
For instance, rather than decide that an object's scale will be modulated by the audio's bass level as you might in a demo, in Sinewav3, you instead expose a Setting of type Modulator in your Plugin, allowing the user to decide whether to modulate that object's scale with the audio bass level or perhaps the overall volume, if that's more effective based on the audio track they are using.
Available modulation sources that naturally change include the audio bands and channels as well as the frame number.
Another modulation option is customized easers. By specifying the type of ease, beginning value, ending value, number of steps, and optional looping type, you get a customized closure that you can store and then call during each render invocation. An easer returns the next step between the start and end values each time it is called.
For instance, say you have a particle system that emits sparks which get bright (slowly, faster, then slowing again), then dim quickly before disappearing. Create two easers for each spark. Control the 'flash' of brightness using an 'exponential in/out' ease with no loop. When that easer returns the maximum value, remove it and dim the spark with the other easer - a non-looping 'ease out quint' going from the maximum value back to the minimum. When that easer returns the maximum value, you remove the particle from the scene and ditch its second easer.
See http://easings.net/ for examples of the supported types.
Get a modulator value by name.
Modulator values are floating point numbers that fall within the range of 0 to 1.
When a Setting of type Modulator is defined for a Plugin, the user chooses a source of modulation data from a dropdown or accepts the sane selection specified by the developer.
It is usually a good idea to expose a companion multiplier Setting for every modulator Setting your Plugin exposes. Then, in the Plugin's render function, you can retrieve and multiply the two values before applying them. This allows the user to specify how much influence the modulator value will have.
For example, consider a Plugin with a SettingGroup called 'Scale', which contains:
// Get a reference to the mesh to be scaled, in this case from context.memory. let mesh = context.memory.mesh; // Get the name of the currently selected modulation source let mod_name = context.plugin.getSettingValue('Scale', 'Mod Source'); // Get value of the multiplier let mod_amount = context.plugin.getSettingValue('Scale', 'Mod Amount'); // Multiply the selected modulator's value by the multiplier value let product = context.modulators.getModulatorValue( mod_name ) * mod_amount; // Set the scale of the mesh to the product of the modulator and its multiplier mesh.scale.set( product, product, product );
(string)
the name of the modulator value to retrieve
number
:
a floating point number between 0 and 1 that is the current value of the modulator