Untitled Block Thing
Contents
Introduction
Untitled Block Thing (UBT) is a dynamic-ish visual scripting environment that allows small software processes to be graphically constructed and run with minimal use of a computer keyboard. UBT is inspired by Scratch and various white-board applications.
The Basics
The UBT interface includes a menu and a scrolling canvas upon which blocks can be arranged. A new UBT project always includes a start block and a console block - these components cannot be duplicated or deleted from a project.
Menu information
blocks menu | is where new blocks can be selected to add to the project. |
---|---|
demo menu | provides a list of examples that can be loaded, run, and modified. |
tools/clear | removes all user-added blocks and start a new project. |
tools/tidy | rearranges all blocks to be equally spaced near the center of the scrollable canvas. |
tools/speed | changes the rate at which the interpreter runs upon pressing start. There are 3 speed modes: 1: normal, 2: turbo, 3: slow. |
tools/flash | toggles the blocks from flashing when the code is being run. |
tools/origin | returns the view to canvas origin. |
tools/share | opens a submenu in which the 'share project' button converts the project into a URI string that can be used as a link and the 'create presentation' button opens an editor to allow the user to create a basic webpage application - see the section 'presentation mode' for more details. |
tools/refactor | rename a variable or block and its references. |
tools/zoom | tries to make things easier on mobile devices and small screens. Tries. |
Blocks
Blocks have clickable square handles arranged in the corners and on some edges. Depending on the type of block, different handles may be available. The handles functions are linked to their position in space.
Beginning at pink handle in the top right corner and moving clockwise around the block, the handle functions are:
- delete
- copy
- resize
- expand/collapse
- mutate
- move
Some block types do not have some handles.
Move
Using the move handle, blocks can be dragged over other blocks. If the blocks are compatible, the inactive block will change color and the dragged block can be dropped to create a parent/child relationship. When two blocks are not compatible, the relationship will not be made. Try it out below!
Dragging and dropping blocks onto other blocks is how processes are created in UBT.
Copy
The copy handle functionality changes depending on the type of block being copied. A data container block (Set Block or Set Variable) will copy to a block referencing this container. A functional or reference block will copy to a duplicate, including any children. Try it out below: press the middle square handle on the right side of the block.
Mutate
The mutate handle allows parent blocks to be quickly swapped out for different blocks with similar functionality. A data container block will not mutate. Try it out below!
Hello, World!
In a new UBT project, select the blocks menu / utilities / print. Drag and drop it onto the start block. The print block initializes with a variable block as child. By clicking the bottom left handle, you can mutate this variable reference block into a green constant block. In the text field, type “hello world”. Press the start button to see ‘hello world’ in the Console block output. Try it out below or find it in the demos menu.
Data Stuff
UBT has two types of data; Variables and Constants.
Data types are dynamic; Variables and Constants can both hold one ‘piece’ of data which can be used in a few different ways.
For example, the word ‘false’ is both a string and the boolean opposite of ‘true’, the number 123 is also a string ‘123’.
Constants only ‘exist’ inside the block they are placed into - they cannot be referenced in another block and cannot be changed or updated.
Variables have a name that can be used to access and update the data at different times during the script execution.
Both data and logic blocks can be collected into a sequence using the Set Block.
Blocks are ordered collections of other data and logic blocks (including references to other Blocks and Variables). They can act as arrays (get, push, set, remove) or be used to define how logic flows. A Block is similar to a Variable in that once it is set, it can be called upon later in the process using a Block reference. Block and Variable definitions cannot be added to other blocks, instead, use a reference block. See blocks, variables and constants in action below:
Blocks and Variables can be renamed in the tools/refactor menu.
Presentation Mode
It is possible to share, save, and bookmark scripting projects using the ‘tools/share/share project’ button.
To share a less visually cluttered version of the project (for using rather than building) the user can select ‘tools/share/create presentation’ and open a presentation editor. The presentation editor provides a list of potentially user-editable blocks from the project source and introduces the layout block which is used to create rows and columns in a webpage application. New layout cells can be added using the buttons located on the block (center-right and center-bottom).
Adding user-editable blocks to a layout block will allow the end-user to change the input in the web-application page.
Once an optimal layout is created, the application can be then be accessed using the ‘share presentation’ button.
An example delay compensation calculator for multitrack drum-set recording is shown below.
Caveats
UBT runs completely in the client browser and uses URI strings to ‘load’ script layouts. Some browsers concatenate the length of URI strings and as such large projects may not load. Layout URI strings can exceed 5000 characters (as above)! I need to look into compression for this to be realistic.
Under The Hood
UBT uses an indexed node graph to create processes.
Graphical elements are rendered using p5.js, leaning on basic html divs and widgets for User I/O.
A stack and variable map are generated every time the process is run. Instructions for each block are very simple javascript methods that are triggered based on their position in the stack. The stack is not exhaustive and may skip some child processes if possible, or shrink itself upon repeated operations.
A stack trace is provided in the browser console after running a process.
A proof of Turing ‘completeness’ is provided here.
Thoughts & Credits
I made a Turing Machine that shows UBT is Turing complete (as much as anything else) so I’m feeling pretty happy. Here are some thoughts…
Implementing array operations (get, set, delete, push, run) has made me appreciate everyone who contributed to Python. When I think about code, I think in Python. It’s my ‘internal dialogue programming language’. My (probably still incomplete) approach to array operations was directly inspired by how easy Python lists work.
If you check the source, you might see some weird non-idiomatic javascript. I learnt javascript to convert some of my Processing PDE sketches to p5.js. I learnt Processing PDE because it appeared similar to Arduino, but unlocked the screen as something I could play with. Most of my coding xp is robot facing - not UI or screen elements. I’m sure there are more structured approaches to writing javascript but I’m doing this for fun and to learn!
Proving this idea out sent me down many Wikipedia rabbit holes, stackoverflow, and reddit posts.
All to say, I built this using tools and knowledge from a lot of different awesome people.
A big thank you to Hamish for being my idea sounding board.