diff --git a/pkg/scripting/scripting.go b/pkg/scripting/scripting.go index 910a21b..3bad626 100644 --- a/pkg/scripting/scripting.go +++ b/pkg/scripting/scripting.go @@ -53,6 +53,14 @@ func (s *Supervisor) InstallScripts(level *level.Level) error { for _, id := range actor.Links { // Assign this target actor's Inbound channel to the source // actor's array of Outbound channels. + if _, ok := s.scripts[id]; !ok { + log.Error("scripting.InstallScripts: actor %s is linked to %s but %s was not found", + actor.ID(), + id, + id, + ) + continue + } thisVM.Outbound = append(thisVM.Outbound, s.scripts[id].Inbound) } } diff --git a/pkg/uix/canvas_strokes.go b/pkg/uix/canvas_strokes.go index dac3a7d..4872eca 100644 --- a/pkg/uix/canvas_strokes.go +++ b/pkg/uix/canvas_strokes.go @@ -86,12 +86,76 @@ func (w *Canvas) RedoStroke() bool { // presentStrokes is called as part of Present() and draws the strokes whose // pixels are currently visible within the viewport. func (w *Canvas) presentStrokes(e render.Engine) { + // Turn stroke map into a list. + var strokes []*drawtool.Stroke + for _, stroke := range w.strokes { + strokes = append(strokes, stroke) + } + w.drawStrokes(e, strokes) + + // Dynamic actor links visible in the ActorTool and LinkTool. + if w.Tool == ActorTool || w.Tool == LinkTool { + w.presentActorLinks(e) + } +} + +// presentActorLinks draws strokes connecting actors together by their links. +// TODO: the strokes are computed dynamically every tick in here, might be a +// way to better optimize later. +func (w *Canvas) presentActorLinks(e render.Engine) { + var ( + strokes = []*drawtool.Stroke{} + actorMap = map[string]*Actor{} + ) + + // Loop over actors and collect linked ones into the map. + for _, actor := range w.actors { + if len(actor.Actor.Links) > 0 { + actorMap[actor.ID()] = actor + } + } + + // Loop over the linked actors and draw stroke lines. + for _, actor := range actorMap { + for _, linkID := range actor.Actor.Links { + if _, ok := actorMap[linkID]; !ok { + continue + } + + var ( + aP = actor.Position() + aS = actor.Size() + bP = actorMap[linkID].Position() + bS = actorMap[linkID].Size() + ) + + // Draw a line connecting the centers of each actor together. + stroke := drawtool.NewStroke(drawtool.Line, render.Magenta) + stroke.PointA = render.Point{ + X: aP.X + (aS.W / 2), + Y: aP.Y + (aS.H / 2), + } + stroke.PointB = render.Point{ + X: bP.X + (bS.W / 2), + Y: bP.Y + (bS.H / 2), + } + + strokes = append(strokes, stroke) + } + } + + w.drawStrokes(e, strokes) +} + +// drawStrokes is the common base function behind presentStrokes and +// presentActorLinks to actually draw the lines to the canvas. +func (w *Canvas) drawStrokes(e render.Engine, strokes []*drawtool.Stroke) { var ( P = ui.AbsolutePosition(w) // w.Point() // Canvas point in UI VP = w.ViewportRelative() // Canvas scroll viewport ) - for _, stroke := range w.strokes { + for _, stroke := range strokes { for point := range stroke.IterPoints() { if !point.Inside(VP) { continue