131 lines
3.7 KiB
Go
131 lines
3.7 KiB
Go
package editor
|
|
|
|
import (
|
|
"aego/core/ids"
|
|
"aego/core/mathx"
|
|
"aego/editor/core/context"
|
|
"aego/editor/core/document"
|
|
"aego/editor/core/shape"
|
|
"aego/modules/physics/components"
|
|
"aego/schema"
|
|
"aego/ui/core"
|
|
"aego/ui/widgets"
|
|
)
|
|
|
|
func (p *plugin) edit(ctx *context.Editor, d *document.SceneDocument, nodes []ids.NodeID, fd *schema.FieldDescriptor, e widgets.Edit, v schema.Value) {
|
|
if e.Begin && p.tx == nil {
|
|
p.tx = d.History.Begin("Set Mass")
|
|
}
|
|
if e.Changed {
|
|
if err := d.Props.Set(p.tx, nodes, p.body.ID, fd.ID, v); err != nil {
|
|
ctx.Notify(context.LevelError, err.Error())
|
|
}
|
|
}
|
|
if e.End && p.tx != nil {
|
|
p.tx.Commit()
|
|
p.tx = nil
|
|
}
|
|
}
|
|
|
|
func (p *plugin) bodyInspector(ctx *context.Editor, nodes []ids.NodeID, def func()) {
|
|
d := ctx.Doc()
|
|
massFD, ok1 := p.body.Field("mass")
|
|
modeFD, ok2 := p.body.Field("massMode")
|
|
if d == nil || !ok1 || !ok2 {
|
|
def()
|
|
return
|
|
}
|
|
ui := ctx.UI
|
|
mode, modeMixed, _ := d.Props.Common(nodes, p.body.ID, modeFD.ID)
|
|
switch {
|
|
case !modeMixed && components.MassMode(mode.I) == components.MassOverride:
|
|
v, mixed, _ := d.Props.Common(nodes, p.body.ID, massFD.ID)
|
|
f := v.AsFloat()
|
|
e := widgets.DragNumber(ui, ui.ID("mass"), widgets.Field(ui, "Mass"), &f, widgets.NumberOpts{Speed: 0.05, Min: 0, HasMin: true, Mixed: mixed})
|
|
p.edit(ctx, d, nodes, massFD, e, schema.Float32(float32(f)))
|
|
case len(nodes) == 1:
|
|
text := "from colliders"
|
|
if sim := p.sim(); sim != nil {
|
|
if bh, ok := sim.BodyOf(d.Scene().Handle(nodes[0])); ok {
|
|
m, _, _, _ := sim.World().BodyMass(bh)
|
|
text = widgets.FormatNumber(float64(m), widgets.NumberOpts{}) + " (from colliders)"
|
|
}
|
|
}
|
|
ui.TextIn(widgets.Field(ui, "Mass"), text, ui.Theme.TextDim, core.AlignLeft)
|
|
}
|
|
def()
|
|
}
|
|
|
|
func (p *plugin) colliderInspector(k components.Kind) func(*context.Editor, []ids.NodeID, func()) {
|
|
return func(ctx *context.Editor, nodes []ids.NodeID, def func()) {
|
|
d := ctx.Doc()
|
|
ui := ctx.UI
|
|
th := &ui.Theme
|
|
if d != nil && len(nodes) == 1 {
|
|
if msg, bad := p.issue(nodes[0], components.Names[k]); bad {
|
|
for _, line := range widgets.WrapLines(ui, msg, ui.Cursor().W-8) {
|
|
r := ui.Cursor().Next(0)
|
|
bg := th.Error
|
|
bg.A = 0.18
|
|
ui.Rect(r, bg)
|
|
ui.Text(line, mathx.Vec2{X: r.X + 4, Y: ui.TextY(r)}, th.Error)
|
|
}
|
|
}
|
|
}
|
|
def()
|
|
if d == nil || k == components.KindPolygon || k == components.KindEdge {
|
|
return
|
|
}
|
|
if widgets.Button(ui, "Snap to Sprite") {
|
|
p.snapToSprite(ctx, d, nodes, k)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (p *plugin) snapToSprite(ctx *context.Editor, d *document.SceneDocument, nodes []ids.NodeID, k components.Kind) {
|
|
s := d.Scene()
|
|
set := shape.Set{Reg: ctx.Shapes}
|
|
if ctx.Loader != nil {
|
|
set.Res = ctx.Loader
|
|
}
|
|
td := p.types[k]
|
|
type value struct {
|
|
name string
|
|
v schema.Value
|
|
}
|
|
tx := d.History.Begin("Snap to Sprite")
|
|
done := 0
|
|
for _, n := range nodes {
|
|
sh, ok := set.Of(s, s.Handle(n))
|
|
if !ok || sh.Kind != shape.Rect || sh.Order < 0 {
|
|
continue
|
|
}
|
|
r := sh.Local
|
|
vals := []value{{"offset", schema.Vec2(mathx.Vec2{X: r.X + r.W/2, Y: r.Y + r.H/2})}}
|
|
switch k {
|
|
case components.KindBox:
|
|
vals = append(vals, value{"size", schema.Vec2(mathx.Vec2{X: r.W, Y: r.H})})
|
|
case components.KindCircle:
|
|
vals = append(vals, value{"radius", schema.Float32(max(r.W, r.H) / 2)})
|
|
case components.KindCapsule:
|
|
vals = append(vals, value{"length", schema.Float32(r.W)}, value{"radius", schema.Float32(r.H / 2)})
|
|
}
|
|
for _, x := range vals {
|
|
fd, ok := td.Field(x.name)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if err := d.Props.Set(tx, []ids.NodeID{n}, td.ID, fd.ID, x.v); err != nil {
|
|
tx.Abort()
|
|
ctx.Notify(context.LevelError, err.Error())
|
|
return
|
|
}
|
|
}
|
|
done++
|
|
}
|
|
tx.Commit()
|
|
if done == 0 {
|
|
ctx.Notify(context.LevelInfo, "No sprite on the selected nodes")
|
|
}
|
|
}
|