Editor Mode: Line Tool and Rectangle Tool
* Add support for the LineTool and RectTool while in the EditorMode to easily draw straight lines and rectangle outlines. * Key bindings were added to toggle tools in lieu of a proper UI to select the tool from a toolbar. * "F" for Pencil (Freehand) Tool (since "P" is for "Playtest") * "L" for Line Tool * "R" for Rectangle Tool
This commit is contained in:
parent
5d8c5510d8
commit
5a1ec156ca
10
README.md
10
README.md
|
@ -69,6 +69,16 @@ Cursor Keys
|
|||
Scroll the view of the map around.
|
||||
"P" Key
|
||||
Playtest the current map you're working on.
|
||||
"F" Key
|
||||
Switch to the Pencil (Freehand) Tool
|
||||
"L" Key
|
||||
Switch to the Line Tool
|
||||
"R" Key
|
||||
Switch to the Rectangle Tool
|
||||
Ctrl-Z
|
||||
Undo
|
||||
Ctrl-Y
|
||||
Redo
|
||||
```
|
||||
|
||||
# Built-In Doodads
|
||||
|
|
|
@ -235,3 +235,44 @@ func IterLine(x1, y1, x2, y2 int32) chan Point {
|
|||
func IterLine2(p1 Point, p2 Point) chan Point {
|
||||
return IterLine(p1.X, p1.Y, p2.X, p2.Y)
|
||||
}
|
||||
|
||||
// IterRect loops through all the points forming a rectangle between the
|
||||
// top-left point and the bottom-right point.
|
||||
func IterRect(p1, p2 Point) chan Point {
|
||||
generator := make(chan Point)
|
||||
|
||||
go func() {
|
||||
var (
|
||||
TopLeft = p1
|
||||
BottomRight = p2
|
||||
TopRight = Point{
|
||||
X: BottomRight.X,
|
||||
Y: TopLeft.Y,
|
||||
}
|
||||
BottomLeft = Point{
|
||||
X: TopLeft.X,
|
||||
Y: BottomRight.Y,
|
||||
}
|
||||
)
|
||||
|
||||
// Trace all four edges and yield it.
|
||||
var edges = []struct {
|
||||
A Point
|
||||
B Point
|
||||
}{
|
||||
{TopLeft, TopRight},
|
||||
{TopLeft, BottomLeft},
|
||||
{BottomLeft, BottomRight},
|
||||
{TopRight, BottomRight},
|
||||
}
|
||||
for _, edge := range edges {
|
||||
for pt := range IterLine2(edge.A, edge.B) {
|
||||
generator <- pt
|
||||
}
|
||||
}
|
||||
|
||||
close(generator)
|
||||
}()
|
||||
|
||||
return generator
|
||||
}
|
||||
|
|
|
@ -61,6 +61,10 @@ func (s *Stroke) IterPoints() chan render.Point {
|
|||
for point := range render.IterLine2(s.PointA, s.PointB) {
|
||||
ch <- point
|
||||
}
|
||||
case Rectangle:
|
||||
for point := range render.IterRect(s.PointA, s.PointB) {
|
||||
ch <- point
|
||||
}
|
||||
}
|
||||
close(ch)
|
||||
}()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package uix
|
||||
package drawtool
|
||||
|
||||
// Tool is a draw mode for an editable Canvas.
|
||||
type Tool int
|
||||
|
@ -6,12 +6,16 @@ type Tool int
|
|||
// Draw modes for editable Canvas.
|
||||
const (
|
||||
PencilTool Tool = iota // draw pixels where the mouse clicks
|
||||
LineTool
|
||||
RectTool
|
||||
ActorTool // drag and move actors
|
||||
LinkTool
|
||||
)
|
||||
|
||||
var toolNames = []string{
|
||||
"Pencil",
|
||||
"Line",
|
||||
"Rectangle",
|
||||
"Doodad", // readable name for ActorTool
|
||||
"Link",
|
||||
}
|
|
@ -9,6 +9,7 @@ import (
|
|||
"git.kirsle.net/apps/doodle/lib/events"
|
||||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/pkg/doodads"
|
||||
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
||||
"git.kirsle.net/apps/doodle/pkg/enum"
|
||||
"git.kirsle.net/apps/doodle/pkg/level"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
|
@ -167,9 +168,18 @@ func (s *EditorScene) Loop(d *Doodle, ev *events.State) error {
|
|||
s.UI.Loop(ev)
|
||||
|
||||
// Switching to Play Mode?
|
||||
if ev.KeyName.Read() == "p" {
|
||||
switch ev.KeyName.Read() {
|
||||
case "p":
|
||||
s.Playtest()
|
||||
return nil
|
||||
case "l":
|
||||
d.Flash("Line Tool selected.")
|
||||
s.UI.Canvas.Tool = drawtool.LineTool
|
||||
case "f":
|
||||
d.Flash("Pencil Tool selected.")
|
||||
s.UI.Canvas.Tool = drawtool.PencilTool
|
||||
case "r":
|
||||
d.Flash("Rectangle Tool selected.")
|
||||
s.UI.Canvas.Tool = drawtool.RectTool
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/branding"
|
||||
"git.kirsle.net/apps/doodle/pkg/doodads"
|
||||
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
||||
"git.kirsle.net/apps/doodle/pkg/enum"
|
||||
"git.kirsle.net/apps/doodle/pkg/level"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
|
@ -311,7 +312,7 @@ func (u *EditorUI) SetupCanvas(d *Doodle) *uix.Canvas {
|
|||
b.Actor.AddLink(idA)
|
||||
|
||||
// Reset the Link tool.
|
||||
drawing.Tool = uix.ActorTool
|
||||
drawing.Tool = drawtool.ActorTool
|
||||
d.Flash("Linked '%s' and '%s' together", a.Doodad.Title, b.Doodad.Title)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ import (
|
|||
"git.kirsle.net/apps/doodle/lib/render"
|
||||
"git.kirsle.net/apps/doodle/lib/ui"
|
||||
"git.kirsle.net/apps/doodle/pkg/balance"
|
||||
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
||||
"git.kirsle.net/apps/doodle/pkg/enum"
|
||||
"git.kirsle.net/apps/doodle/pkg/log"
|
||||
"git.kirsle.net/apps/doodle/pkg/uix"
|
||||
)
|
||||
|
||||
// SetupPalette sets up the palette panel.
|
||||
|
@ -31,11 +31,11 @@ func (u *EditorUI) SetupPalette(d *Doodle) *ui.Window {
|
|||
}))
|
||||
tab.Handle(ui.Click, func(p render.Point) {
|
||||
if u.paletteTab == "Palette" {
|
||||
u.Canvas.Tool = uix.PencilTool
|
||||
u.Canvas.Tool = drawtool.PencilTool
|
||||
u.PaletteTab.Show()
|
||||
u.DoodadTab.Hide()
|
||||
} else {
|
||||
u.Canvas.Tool = uix.ActorTool
|
||||
u.Canvas.Tool = drawtool.ActorTool
|
||||
u.PaletteTab.Hide()
|
||||
u.DoodadTab.Show()
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ type Canvas struct {
|
|||
Scrollable bool // Cursor keys will scroll the viewport of this canvas.
|
||||
|
||||
// Selected draw tool/mode, default Pencil, for editable canvases.
|
||||
Tool Tool
|
||||
Tool drawtool.Tool
|
||||
|
||||
// MaskColor will force every pixel to render as this color regardless of
|
||||
// the palette index of that pixel. Otherwise pixels behave the same and
|
||||
|
|
|
@ -21,7 +21,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
)
|
||||
|
||||
switch w.Tool {
|
||||
case PencilTool:
|
||||
case drawtool.PencilTool:
|
||||
// If no swatch is active, do nothing with mouse clicks.
|
||||
if w.Palette.ActiveSwatch == nil {
|
||||
return nil
|
||||
|
@ -90,7 +90,73 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
|
||||
w.lastPixel = nil
|
||||
}
|
||||
case ActorTool:
|
||||
case drawtool.LineTool:
|
||||
// If no swatch is active, do nothing with mouse clicks.
|
||||
if w.Palette.ActiveSwatch == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clicking? Log all the pixels while doing so.
|
||||
if ev.Button1.Now {
|
||||
// Initialize a new Stroke for this atomic drawing operation?
|
||||
if w.currentStroke == nil {
|
||||
w.currentStroke = drawtool.NewStroke(drawtool.Line, w.Palette.ActiveSwatch.Color)
|
||||
w.currentStroke.ExtraData = w.Palette.ActiveSwatch
|
||||
w.currentStroke.PointA = render.NewPoint(cursor.X, cursor.Y)
|
||||
w.AddStroke(w.currentStroke)
|
||||
}
|
||||
|
||||
w.currentStroke.PointB = render.NewPoint(cursor.X, cursor.Y)
|
||||
} else {
|
||||
// Mouse released, commit the points to the drawing.
|
||||
if w.currentStroke != nil {
|
||||
for pt := range render.IterLine2(w.currentStroke.PointA, w.currentStroke.PointB) {
|
||||
w.chunks.Set(pt, w.Palette.ActiveSwatch)
|
||||
}
|
||||
|
||||
// Add the stroke to level history.
|
||||
if w.level != nil {
|
||||
w.level.UndoHistory.AddStroke(w.currentStroke)
|
||||
}
|
||||
|
||||
w.RemoveStroke(w.currentStroke)
|
||||
w.currentStroke = nil
|
||||
}
|
||||
}
|
||||
case drawtool.RectTool:
|
||||
// If no swatch is active, do nothing with mouse clicks.
|
||||
if w.Palette.ActiveSwatch == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Clicking? Log all the pixels while doing so.
|
||||
if ev.Button1.Now {
|
||||
// Initialize a new Stroke for this atomic drawing operation?
|
||||
if w.currentStroke == nil {
|
||||
w.currentStroke = drawtool.NewStroke(drawtool.Rectangle, w.Palette.ActiveSwatch.Color)
|
||||
w.currentStroke.ExtraData = w.Palette.ActiveSwatch
|
||||
w.currentStroke.PointA = render.NewPoint(cursor.X, cursor.Y)
|
||||
w.AddStroke(w.currentStroke)
|
||||
}
|
||||
|
||||
w.currentStroke.PointB = render.NewPoint(cursor.X, cursor.Y)
|
||||
} else {
|
||||
// Mouse released, commit the points to the drawing.
|
||||
if w.currentStroke != nil {
|
||||
for pt := range render.IterRect(w.currentStroke.PointA, w.currentStroke.PointB) {
|
||||
w.chunks.Set(pt, w.Palette.ActiveSwatch)
|
||||
}
|
||||
|
||||
// Add the stroke to level history.
|
||||
if w.level != nil {
|
||||
w.level.UndoHistory.AddStroke(w.currentStroke)
|
||||
}
|
||||
|
||||
w.RemoveStroke(w.currentStroke)
|
||||
w.currentStroke = nil
|
||||
}
|
||||
}
|
||||
case drawtool.ActorTool:
|
||||
// See if any of the actors are below the mouse cursor.
|
||||
var WP = w.WorldIndexAt(cursor)
|
||||
|
||||
|
@ -134,7 +200,7 @@ func (w *Canvas) loopEditable(ev *events.State) error {
|
|||
if len(deleteActors) > 0 && w.OnDeleteActors != nil {
|
||||
w.OnDeleteActors(deleteActors)
|
||||
}
|
||||
case LinkTool:
|
||||
case drawtool.LinkTool:
|
||||
// See if any of the actors are below the mouse cursor.
|
||||
var WP = w.WorldIndexAt(cursor)
|
||||
|
||||
|
|
|
@ -3,12 +3,13 @@ package uix
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"git.kirsle.net/apps/doodle/pkg/drawtool"
|
||||
"git.kirsle.net/apps/doodle/pkg/shmem"
|
||||
)
|
||||
|
||||
// LinkStart initializes the Link tool.
|
||||
func (w *Canvas) LinkStart() {
|
||||
w.Tool = LinkTool
|
||||
w.Tool = drawtool.LinkTool
|
||||
w.linkFirst = nil
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ func (w *Canvas) presentStrokes(e render.Engine) {
|
|||
w.drawStrokes(e, strokes)
|
||||
|
||||
// Dynamic actor links visible in the ActorTool and LinkTool.
|
||||
if w.Tool == ActorTool || w.Tool == LinkTool {
|
||||
if w.Tool == drawtool.ActorTool || w.Tool == drawtool.LinkTool {
|
||||
w.presentActorLinks(e)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user