83 lines
2.5 KiB
Go
83 lines
2.5 KiB
Go
|
package vthree
|
||
|
|
||
|
import (
|
||
|
"github.com/divan/three"
|
||
|
"github.com/gopherjs/gopherjs/js"
|
||
|
"github.com/gopherjs/vecty"
|
||
|
"github.com/gopherjs/vecty/elem"
|
||
|
)
|
||
|
|
||
|
type WebGLRenderer struct {
|
||
|
vecty.Core
|
||
|
opts WebGLOptions `vecty:"prop"`
|
||
|
markup []vecty.MarkupOrChild `vecty:"prop"`
|
||
|
|
||
|
canvas *vecty.HTML
|
||
|
renderer *three.WebGLRenderer
|
||
|
}
|
||
|
|
||
|
// Mount implements the vecty.Mounter interface.
|
||
|
func (r *WebGLRenderer) Mount() {
|
||
|
r.renderer = newWebGLRenderer(&webGLRendererParameters{Canvas: r.canvas.Node()})
|
||
|
r.opts.Init(r.renderer)
|
||
|
}
|
||
|
|
||
|
// Unmount implements the vecty.Unmounter interface.
|
||
|
func (r *WebGLRenderer) Unmount() {
|
||
|
if r.opts.Shutdown != nil {
|
||
|
r.opts.Shutdown(r.renderer)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Render implements the vecty.Component interface.
|
||
|
func (r *WebGLRenderer) Render() vecty.ComponentOrHTML {
|
||
|
r.canvas = elem.Canvas(r.markup...)
|
||
|
return r.canvas
|
||
|
}
|
||
|
|
||
|
// WebGLOptions represent options for the WebGLRenderer component.
|
||
|
type WebGLOptions struct {
|
||
|
// Init is called when the three.js WebGLRenderer has been created.
|
||
|
//
|
||
|
// This can happen multiple times during the lifecycle of an application
|
||
|
// if the Vecty WebGLRenderer component was unmounted and mounted again,
|
||
|
// e.g. due to navigating to a different page and back again.
|
||
|
Init func(r *three.WebGLRenderer)
|
||
|
|
||
|
// Shutdown is called before the canvas associated with the three.js
|
||
|
// WebGLRenderer will be destroyed. For example, when your Vecty
|
||
|
// application no longer renders the WebGLRenderer component and it is
|
||
|
// being unmounted.
|
||
|
Shutdown func(r *three.WebGLRenderer)
|
||
|
|
||
|
// TODO(slimsag): allow specifying other parameters like context, precision,
|
||
|
// etc. from three.js WebGLRenderer constructor here:
|
||
|
// https://threejs.org/docs/#api/renderers/WebGLRenderer
|
||
|
}
|
||
|
|
||
|
// NewWebGLRenderer returns a Vecty component that initializes a three.js WebGL renderer for
|
||
|
// use in a Vecty application.
|
||
|
func NewWebGLRenderer(opts WebGLOptions, markup ...vecty.MarkupOrChild) *WebGLRenderer {
|
||
|
if opts.Init == nil {
|
||
|
panic("vthree: Renderer: must specify opts.Init")
|
||
|
}
|
||
|
return &WebGLRenderer{
|
||
|
opts: opts,
|
||
|
markup: markup,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type webGLRendererParameters struct {
|
||
|
Canvas *js.Object
|
||
|
}
|
||
|
|
||
|
// Note: We can't use three.NewWebGLRenderer because it doesn't allow
|
||
|
// specifying any parameters yet. Easy enough to just call ourself, though.
|
||
|
func newWebGLRenderer(parameters *webGLRendererParameters) *three.WebGLRenderer {
|
||
|
return &three.WebGLRenderer{
|
||
|
Object: js.Global.Get("THREE").Get("WebGLRenderer").New(map[string]interface{}{
|
||
|
"canvas": parameters.Canvas,
|
||
|
}),
|
||
|
}
|
||
|
}
|