Connectable Tabs - Rendering Hackathon - Blockly Summit 2019

103 views
Skip to first unread message

Mark Gibson

unread,
Oct 13, 2019, 1:38:44 PM10/13/19
to Blockly
Hi all,
First I'd just like to thank all of the Blockly team and everyone else attending for such a great time at the Blockly Summit 2019 - we learnt of lot tips and great ideas.

Anyway, here is my write up of our hackathon hack.

Its goal is to indicate which inputs the selected block can be connected to.

It does this with a custom shapeFor fn on the renderer, by getting the output connection of the selected block and checking whether it can connect to the input being rendered.

Here is a little demo video... https://www.youtube.com/watch?v=ZAc5JOq4NXA

The shapeFor fn...

Blockly.minimalist.ConstantProvider.prototype.shapeFor = function (connection) {

    switch (connection.type) {
        case Blockly.INPUT_VALUE:
            var reason = Blockly.selected && Blockly.selected.outputConnection && Blockly.selected.outputConnection.canConnectWithReason_(connection)

            if (reason === Blockly.Connection.CAN_CONNECT) {
                return this.makeTriangleTab()
            } else {
                return this.PUZZLE_TAB
            }

        case Blockly.OUTPUT_VALUE:
            var here = Blockly.selected === connection.getSourceBlock()

            if (here) {
                return this.makeTriangleTab()
            }

            var shape = connection.targetConnection && this.shapeFor(connection.targetConnection)

            return shape || this.PUZZLE_TAB

        case Blockly.PREVIOUS_STATEMENT:
        case Blockly.NEXT_STATEMENT:
            return this.NOTCH
        default:
            throw Error('Unknown connection type')
    }
}

and the makeTriangle is exactly the same as the makePuzzleTab fn but with the follow makeMainPath...

    function makeMainPath(up) {
        return Blockly.utils.svgPaths.line(
            [
                Blockly.utils.svgPaths.point(-width, -1 * up * height / 2),
                Blockly.utils.svgPaths.point(width, -1 * up * height / 2)
            ])
    }

also had to hack the playground.html to force a rerender of all blocks when something is selected, this is by far the hackiest part, i wouldn't recommend this in real life :D ...

function logger(e) {
  console.log(e);

  Blockly.mainWorkspace.getAllBlocks().forEach(b => b.render(false))
}

this definitely needs a lot of work to be generally useful.


Uwe K

unread,
Oct 14, 2019, 4:51:33 AM10/14/19
to Blockly
Nice, this looks very useful. Even though many of those render calls at the end can be avoided, this would still require checking all connections and re-rendering a lot of blocks when a new block is selected. Is that feasible in terms of performance?

Beka Westberg

unread,
Oct 14, 2019, 10:19:25 AM10/14/19
to Blockly
Hi Mark,

Really cool hackathon project! Such an elegant solution to the type problems you're running into.

I was wondering what your desired solution to the re-rendering problem would be. My first instinct is to just cache all blocks based on the types of their inputs, using something like #2619, but I was wondering what you were thinking.

Thanks for sharing your rad hackathon project!
--Beka

Rachel Fenichel

unread,
Oct 14, 2019, 12:24:52 PM10/14/19
to Blockly
Another option (that we've seen before) is to add a connection highlight over every single allowable connection on the workspace, instead of just on the one that you're currently closest to.  This has the advantage of being layered on top, so it doesn't cause such extreme rerenders.

Mark Gibson

unread,
Oct 14, 2019, 12:26:03 PM10/14/19
to Blockly
I've not had chance to think about this in detail yet.

Ideally I'd still like to use canConnectWithReason to determine the connection ability to ensure total consistency with drag'n'drop connection behaviour.
I'm always wary of premature optimisation though - so I think to begin with I'd still iterate over all blocks and use canConnectWithReason, but cache the outcome of that, and also limit the event under which this happens, eg. just on a Ui selected event and only if the selection actually changes. So I think that could work well with your idea for a general block tagging system too.

For the rest of this week, we are continuing with our own Blockly hackathon, rolling with some of the ideas from the summit. First things we are looking at are your flyout in a field, and copy/paste as png with the embedded xml as Evan demo'd. I think we may revisit this rendering idea later in the week if we get time. Your input on any of this would great.

Mark Gibson

unread,
Oct 14, 2019, 12:28:47 PM10/14/19
to Blockly
Reply all
Reply to author
Forward
0 new messages