From 5d8c5510d8f04138eb88434d39c70c28d58c98d1 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Wed, 3 Jul 2019 16:51:23 -0700 Subject: [PATCH] Draw Lines Visualizing Doodad Links in Edit Mode * If the current edit tool is Actor or Link, use the new drawtool.Stroke object to draw visual lines connecting every pair of linked actors in the level. The lines are hidden during normal editing and gameplay and only appear when you're possibly manipulating your actors and links. --- pkg/scripting/scripting.go | 8 +++++ pkg/uix/canvas_strokes.go | 66 +++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) 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