concord-consortium/lab — pull request #43 by rklancer (2013-09-25 04:30:39+00:00)
Title: Separate rendering layers

I've got the separate-rendering-layers branch working pretty well. This branch divides up the svg container into separate svg elements which all live inside a div. This was done so that canvas-based, Pixi.js layers could be sandwiched between svg-based layers. This way we don't have to reimplement the whole rendering system all at once in order to deliver a benefit.

The way the generic "SVGContainer" works in separate-rendering-layers is to implement an appendViewport method. This creates and appends an svg element to the root div of the (now (misnamed?) SVGContainer. These svgs are all drawn on top of each other.

Renderers, such as the MD2D renderer, call `appendViewport` when they need an svg to render into. At the moment I have the MD2D create 3 such svgs: the "below-atoms" layer, the "atoms" layer, and the "above-atoms" layer. Each of these can be subdivided into layers by appending g elements to it, at the whim of the renderer. But the point of the separate "atoms" layer is that it will be possible to replace it with the Pixi.js canvas.

The major missing feature is touch support. When all our view layers are inside a single svg, the browser natively does hit testing for us (it allows us to click on elements in lower layers if there are no elements in the layers above it at the click coordinates). When there are multiple "root" svgs, the topmost one always gets the click. However we can simulate hit testing with some fancy footwork: https://github.com/concord-consortium/lab/blob/c79550e3c4996f84776c83ce3b01f04b384b1216/src/lab/common/views/svg-container.js#L404-L521

Touch events are just a little bit more subtle to hit-test (see TODO comment in the above code). I'll probably give that a shot tomorrow morning.

However, even without touch support, I think it's worth merging this branch into pixijs-rendering now.

The branch isn't ready to merge automatically, but the work needed to be done to combine the branches is relatively simple. (I could also give that a shot tomorrow morning if nobody's done it by then :)

Specifically, we'd need to augment appendViewport with something like appendPixiViewport. Then pixi.js can render into that.

We'd need to implement viewport scrolling in the canvas viewport, and then we'd need to modify `setupHitTesting` to always dispatch an event to the Pixi canvas when it reaches that layer, and to ask the Pixi view after the fact if its hit test succeeded.(If Pixi doesn't issue a mouseDown to the atomsRenderer, that means the click didn't hit an atom, and setupHitTesting should keep looking at layers below the canvas element.)

A simple way to do this is to set a flag on the atomsRenderer when it gets a mouseDown or mouseUp callback from Pixi's "InteractionManager", and have setupHitTest query this flag.