Stage¶
The stage is what ties all the separate systems together. Subclasses of a base stage are used for different scenes in the game (title screen, levels, inter-chapter screen). Roughly, the structure is as follows:
- The stage specifies input handlers (via
TouchRecord, see below). - Input handlers call helper methods on the stage.
- Helper methods use semantics functions to decide what to change/how to change expressions, and may provide callbacks to these semantics functions.
- Helper methods dispatch Redux actions to the store to update the game state, or modify views to update the UI state.
Rendering¶
Reduct-Redux does not have a scenegraph, and so you need to explicitly
specify what to render. This should be done by overriding
drawContents. There are helper functions to render a view for a
given expression, like drawProjection.
The rendering lifecycle is as follows:
- Redux store/animation is updated
stage.draw()is calledstage.drawusesrequestAnimationFramerequestAnimationFramecallback fires, callingstage.drawImplstage.drawImplcallsstage.drawContents
This allows Redux to avoid re-rendering when nothing is happening, saving CPU.
Effects¶
Input Handling: TouchRecord¶
Unlike most UI/GUI frameworks, where events are processed by handler
functions attached to particular UI widgets, Reduct-Redux handles most
events in a centralized location, the TouchRecord. This is a class
with callbacks for when a touch/mouse is pressed, moved, or released,
and keeps track of related state. Based on this state, it dispatches
lower-level callbacks or changes as appropriate (reducing expressions,
dragging them around, activating buttons, etc.). You specify the
desired TouchRecord to use by overriding the touchRecordClass
property getter of BaseStage.
Stages Reference¶
import BaseStage from "./stage/basestage";
import BaseTouchRecord from "./stage/touchrecord";
-
class
module:BaseStage()¶ Handle drawing responsibilites for Reduct.
There’s a lot more stuff here, but I’m too lazy to document it all.
-
module:BaseStage.addEffect(fx)¶ Add an effect to the stage.
-
module:BaseStage.allocate(projection)¶ Allocate an ID for the given projection.
Used for projections that don’t directly correspond to nodes and are static (e.g. the text view for the arow in a lambda), but still need an ID.
-
module:BaseStage.allocateInternal(projection)¶ Note
This function is deprecated. Use
allocate()instead.
-
module:BaseStage.color¶ The background color.
-
module:BaseStage.computeDimensions()¶ Compute and resize the canvas when the window is resized.
-
module:BaseStage.ctx¶ The canvas drawing context.
-
module:BaseStage.draw()¶ Request that the stage be redrawn. (Multiple calls have no effect if no redraw happens in between.)
-
module:BaseStage.drawContents()¶ Draw the contents of the stage. Override to customize.
-
module:BaseStage.drawInternalProjection(state, nodeId, exprId, offset)¶ Note
This function is deprecated. Use
BaseStage.drawProjection()instead.
-
module:BaseStage.drawProjection(state, nodeId, offset)¶ Helper to draw a given view.
-
module:BaseStage.findSafePosition(x, y, w, h)¶ Given a rectangular area, move it minimally to fit within the stage bounds.
-
module:BaseStage.getMousePos(e)¶ Convert a mouse/touch event into an { x, y } position, accounting for scaling.
-
module:BaseStage.getNodeAtPos(pos, selectedId)¶ Get the node at the given position.
TODO: return all possible nodes?
-
module:BaseStage.getState()¶ Get the current Redux state.
-
module:BaseStage.getView(id)¶ Get the view with the given ID.
-
module:BaseStage.height¶ The usable width of the stage. (Things like the sidebar can change this.)
-
module:BaseStage.internalViews¶ Note
This attribute is deprecated.
A set of views.
-
module:BaseStage.isHovered(id)¶ Check whether the given view ID is hovered by any touch/mouse.
-
module:BaseStage.isSelected(id)¶ Check whether the given view ID is selected by any touch/mouse.
-
module:BaseStage.makeBaseOffset(opt)¶ Create a basic offset object for rendering.
-
module:BaseStage.semantics¶ The semantics module.
-
module:BaseStage.setCursor(cursor)¶ Set the mouse cursor.
-
module:BaseStage.store¶ The Redux store.
-
module:BaseStage.touchRecordClass¶ The TouchRecord class to use for touch/mouse events. Override to customize input handling.
-
module:BaseStage.updateCursor(touchRecord, moved)¶ Update the cursor based on the mouse/touch state.
-
module:BaseStage.views¶ A dictionary of view ID to view object.
-
module:BaseStage.width¶ The usable width of the stage. (Things like the sidebar can change this.)
-
-
class
module:BaseTouchRecord()¶ Handle input for Reduct.
-
module:BaseTouchRecord.dragged¶ A flag indicating whether the user has dragged the selected view yet.
-
module:BaseTouchRecord.findHoverNode(pos)¶ Helper method to find the view under the current mouse position. Defers to
BaseStage.getNodeAtPos(), but also tracks the previously hovered node (for things like mouse enter/exit events).
-
module:BaseTouchRecord.fromToolbox¶ A flag indicating whether the selected view came from the toolbox.
-
module:BaseTouchRecord.hoverNode¶ The ID of the view currently under the mouse (if any).
-
module:BaseTouchRecord.isExpr¶ A flag indicating whether the selected view belongs to an expression.
-
module:BaseTouchRecord.onend(state, mousePos)¶ Called when the mouse is released.
-
module:BaseTouchRecord.onmove(mouseDown, mousePos)¶ Called when the mouse is moved.
Arguments: - mouseDown – whether the mouse was pressed
- mousePos –
-
module:BaseTouchRecord.onstart(mousePos)¶ Called when the mouse is pressed.
-
module:BaseTouchRecord.prevHoverNode¶ The ID of the view previously under the mouse (if any).
-
module:BaseTouchRecord.reset()¶ Reset this TouchRecord. (The record for the mouse is not recreated, as it can have move events with not pressed.)
-
module:BaseTouchRecord.stage¶ The current stage.
-
module:BaseTouchRecord.targetNode¶ The targeted view ID that was clicked (if any). This may be the same as the top-level view. The Stage controls how these work.
-
module:BaseTouchRecord.topNode¶ The top-level view ID that was clicked (if any).
-