Skip to content

Commit

Permalink
Added new features, fixed resolution related issues
Browse files Browse the repository at this point in the history
  • Loading branch information
esimov committed Nov 9, 2023
1 parent 969ae3e commit 3d201d5
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 68 deletions.
8 changes: 4 additions & 4 deletions cloth.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"gioui.org/op/paint"
)

const lineWidth = 0.8

type Cloth struct {
constraints []*Constraint
particles []*Particle
Expand Down Expand Up @@ -65,7 +67,7 @@ func (c *Cloth) Init(posX, posY int, hud *Hud) {
c.constraints = append(c.constraints, constraint)
}

pinX := x % (clothX / 7)
pinX := x % (clothX / 9)
if y == 0 && pinX == 0 {
particle.pinX = true
}
Expand All @@ -79,7 +81,7 @@ func (c *Cloth) Init(posX, posY int, hud *Hud) {
// Update updates the cloth particles invoked on each frame event of the Gio internal window calls.
// The cloth contraints are solved by using the Verlet integration formulas.
func (cloth *Cloth) Update(gtx layout.Context, mouse *Mouse, hud *Hud, dt float64) {
dragForce := float32(mouse.getForce() * 0.75)
dragForce := float32(mouse.getForce() * 0.25)
clothColor := color.NRGBA{R: 0x55, A: 0xff}
// Convert the RGB color to HSL based on the applied force over the mouse focus area.
col := LinearFromSRGB(clothColor).HSLA().Lighten(dragForce).RGBA().SRGB()
Expand All @@ -94,8 +96,6 @@ func (cloth *Cloth) Update(gtx layout.Context, mouse *Mouse, hud *Hud, dt float6
}
}

const lineWidth = 0.8

var path clip.Path
path.Begin(gtx.Ops)

Expand Down
14 changes: 10 additions & 4 deletions hud.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ type Hud struct {
type slider struct {
widget *widget.Float
title string
index int
min float32
value float32
max float32
Expand All @@ -74,9 +73,10 @@ func NewHud() *Hud {
}

sliders := []slider{
{title: "Drag force", min: 2, value: 4, max: 25},
{title: "Drag force", min: 1.1, value: 2, max: 15},
{title: "Gravity force", min: 100, value: 250, max: 500},
{title: "Elasticity", min: 10, value: 30, max: 50},
{title: "Stiffness", min: 0.95, value: 0.98, max: 0.99},
{title: "Tear distance", min: 5, value: 20, max: 80},
}
for idx, s := range sliders {
Expand Down Expand Up @@ -151,7 +151,7 @@ func (h *Hud) ShowControlPanel(gtx layout.Context, th *material.Theme, isActive
)

{ // Draw close button
offset := float32(gtx.Dp(unit.Dp(16)))
offset := float32(gtx.Dp(unit.Dp(8)))

var path clip.Path
path.Begin(gtx.Ops)
Expand Down Expand Up @@ -216,8 +216,14 @@ func (h *Hud) ShowControlPanel(gtx layout.Context, th *material.Theme, isActive
return h.list.Layout(gtx, len(h.sliders),
func(gtx C, index int) D {
if slider, ok := h.sliders[index]; ok {
var precisionFmt string
if slider.widget.Value > 1 {
precisionFmt = "%s: %.0f"
} else {
precisionFmt = "%s: %.2f"
}
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(material.Body1(th, fmt.Sprintf("%s: %.0f", slider.title, slider.widget.Value)).Layout),
layout.Rigid(material.Body1(th, fmt.Sprintf(precisionFmt, slider.title, slider.widget.Value)).Layout),
layout.Flexed(1, material.Slider(th, slider.widget, slider.min, slider.max).Layout),
)
}
Expand Down
57 changes: 29 additions & 28 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,19 @@ var (
windowWidth = defaultWindowWidth
windowHeight = defaultWindowHeigth

// App related variables
hud *Hud
cloth *Cloth
mouse *Mouse
clothW int
clothH int

// Gio Ops related variables
ops op.Ops
initTime time.Time
deltaTime time.Duration
mouseScrollY unit.Dp
mouseDrag bool

// pprof related variables
profile string
Expand All @@ -64,6 +72,9 @@ func main() {
log.Fatal(err)
}
}
hud = NewHud()
mouse = &Mouse{maxScrollY: unit.Dp(maxFocusArea)}
mouse.setScrollY(defFocusArea)

go func() {
w := app.NewWindow(
Expand All @@ -79,6 +90,8 @@ func main() {
}

func loop(w *app.Window) error {
var keyTag struct{}

if profile != "" {
defer pprof.StopCPUProfile()
}
Expand All @@ -91,19 +104,6 @@ func loop(w *app.Window) error {
th.Palette.ContrastBg = defaultColor
th.FingerSize = 15

mouse := &Mouse{maxScrollY: unit.Dp(maxFocusArea)}
mouse.setScrollY(defFocusArea)

isDragging := false

var clothW int = int(unit.Dp(windowWidth) * 1.2)
var clothH int = int(unit.Dp(windowHeight) * 0.4)

cloth := NewCloth(clothW, clothH, 8, 0.99, defaultColor)
hud := NewHud()

var keyTag struct{}

for {
select {
case e := <-w.Events():
Expand All @@ -115,7 +115,7 @@ func loop(w *app.Window) error {
gtx := layout.NewContext(&ops, e)
hud.panelWidth = gtx.Dp(unit.Dp(windowSizeX))
hud.btnSize = gtx.Dp(unit.Dp(40))
hud.closeBtn = gtx.Dp(unit.Dp(25))
hud.closeBtn = gtx.Dp(unit.Dp(30))

if hud.isActive {
if !hud.panelInit.IsZero() {
Expand All @@ -132,11 +132,16 @@ func loop(w *app.Window) error {
pprof.StartCPUProfile(file)
}

if !cloth.isInitialized {
// Cloth is not initialized yet. Initialize it.
if cloth == nil {
clothW = gtx.Dp(unit.Dp(windowWidth))
clothH = gtx.Dp(unit.Dp(windowHeight) * 0.33)
cloth = NewCloth(clothW, clothH, 12, 0.98, defaultColor)

width := gtx.Constraints.Max.X
height := gtx.Constraints.Max.Y

startX := (width - clothW) / 2
startX := int(unit.Dp(width-clothW) / 2)
startY := int(unit.Dp(height) * 0.2)

cloth.Init(startX, startY, hud)
Expand All @@ -149,7 +154,7 @@ func loop(w *app.Window) error {

if mouse.getLeftButton() {
deltaTime = time.Since(initTime)
mouse.increaseForce(deltaTime.Seconds())
mouse.setForce(deltaTime.Seconds() * 5)
}

for _, ev := range gtx.Queue.Events(&keyTag) {
Expand Down Expand Up @@ -205,8 +210,9 @@ func loop(w *app.Window) error {
hud.showHelpPanel = false
}
}

fillBackground(gtx, color.NRGBA{R: 0xf2, G: 0xf2, B: 0xf2, A: 0xff})
// Fill background
paint.ColorOp{Color: color.NRGBA{R: 0xf2, G: 0xf2, B: 0xf2, A: 0xff}}.Add(gtx.Ops)
paint.PaintOp{}.Add(gtx.Ops)

layout.Stack{}.Layout(gtx,
layout.Stacked(func(gtx layout.Context) layout.Dimensions {
Expand Down Expand Up @@ -259,22 +265,22 @@ func loop(w *app.Window) error {
initTime = time.Now()
hud.showHelpPanel = false
case pointer.Release:
isDragging = false
mouseDrag = false

mouse.resetForce()
mouse.releaseLeftButton()
mouse.releaseRightButton()
mouse.setDragging(isDragging)
mouse.setDragging(mouseDrag)
mouse.setCtrlDown(false)
case pointer.Drag:
isDragging = true
mouseDrag = true
}
switch ev.Buttons {
case pointer.ButtonPrimary:
mouse.setLeftButton()
pos := mouse.getCurrentPosition(ev)
mouse.updatePosition(float64(pos.X), float64(pos.Y))
mouse.setDragging(isDragging)
mouse.setDragging(mouseDrag)
case pointer.ButtonSecondary:
mouse.setRightButton()
pos := mouse.getCurrentPosition(ev)
Expand Down Expand Up @@ -330,8 +336,3 @@ func loop(w *app.Window) error {
}
}
}

func fillBackground(gtx layout.Context, col color.NRGBA) {
paint.ColorOp{Color: col}.Add(gtx.Ops)
paint.PaintOp{}.Add(gtx.Ops)
}
2 changes: 1 addition & 1 deletion mouse.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (m *Mouse) getCtrlDown() bool {
return m.ctrlDown
}

func (m *Mouse) increaseForce(force float64) {
func (m *Mouse) setForce(force float64) {
m.force = force
}

Expand Down
59 changes: 28 additions & 31 deletions particle.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ const (
defFocusArea = 50
minFocusArea = 30
maxFocusArea = 120
maxDragForce = 20
)

// Particle holds the basic components of the particle system.
Expand All @@ -24,7 +23,7 @@ type Particle struct {
px, py float64
vx, vy float64
friction float64
elasticity float64
stiffness float64
dragForce float64
pinX bool
isActive bool
Expand All @@ -37,13 +36,13 @@ func NewParticle(x, y float64, hud *Hud, col color.NRGBA) *Particle {
p := &Particle{
x: x, y: y, px: x, py: y, color: col,
}
dragForce := float64(hud.sliders[0].widget.Value)
elasticity := float64(hud.sliders[2].widget.Value)
hudDragForce := float64(hud.sliders[0].widget.Value)
hudStiffness := float64(hud.sliders[2].widget.Value)

p.isActive = true
p.highlighted = false
p.dragForce = dragForce
p.elasticity = elasticity
p.dragForce = hudDragForce
p.stiffness = hudStiffness

return p
}
Expand All @@ -53,7 +52,7 @@ func (p *Particle) Update(gtx layout.Context, mouse *Mouse, hud *Hud, delta floa
p.update(gtx, mouse, hud, delta)
}

// draw draws the particle at the {x, y} position with the radius `r`.
// Deprecated: draw draws the particle at the {x, y} position with the radius `r`.
func (p *Particle) draw(gtx layout.Context, x, y, r float32) {
var (
sq float64
Expand Down Expand Up @@ -81,8 +80,12 @@ func (p *Particle) draw(gtx layout.Context, x, y, r float32) {
func (p *Particle) update(gtx layout.Context, mouse *Mouse, hud *Hud, dt float64) {
p.highlighted = false

p.friction = float64(hud.sliders[3].widget.Value)
p.dragForce = float64(hud.sliders[0].widget.Value)
p.stiffness = float64(hud.sliders[2].widget.Value)

gravityForce := float64(hud.sliders[1].widget.Value)
tearDistance := float64(hud.sliders[3].widget.Value)
tearDistance := float64(hud.sliders[4].widget.Value)

if p.pinX {
// Recalculate the pinned particles position when the window is resized.
Expand All @@ -93,6 +96,13 @@ func (p *Particle) update(gtx layout.Context, mouse *Mouse, hud *Hud, dt float64
return
}

// Holding the left mouse button will increase the dragging force
// resulting in a much advanced cloth destruction.
if mouse.getLeftButton() {
maxDragForce := float64(hud.sliders[0].max)
p.increaseForce(mouse, maxDragForce)
}

// Window width and height.
width, height := gtx.Constraints.Max.X, gtx.Constraints.Max.Y

Expand All @@ -103,17 +113,17 @@ func (p *Particle) update(gtx layout.Context, mouse *Mouse, hud *Hud, dt float64
if mouse.getDragging() && dist < float64(tearDistance) {
dx := mouse.x - mouse.px
dy := mouse.y - mouse.py
if dx > p.elasticity {
dx = p.elasticity
if dx > p.stiffness {
dx = p.stiffness
}
if dy > p.elasticity {
dy = p.elasticity
if dy > p.stiffness {
dy = p.stiffness
}
if dx < -p.elasticity {
dx = -p.elasticity
if dx < -p.stiffness {
dx = -p.stiffness
}
if dy < -p.elasticity {
dy = -p.elasticity
if dy < -p.stiffness {
dy = -p.stiffness
}
p.px = p.x - dx*p.dragForce
p.py = p.y - dy*p.dragForce
Expand Down Expand Up @@ -143,14 +153,6 @@ func (p *Particle) update(gtx layout.Context, mouse *Mouse, hud *Hud, dt float64
}
}

// Holding the left mouse button will increase the dragging force
// resulting in a much advanced cloth destruction.
if mouse.getLeftButton() {
p.increaseForce(mouse)
} else {
p.resetForce(hud)
}

px, py := p.x, p.y
p.vy += gravityForce

Expand Down Expand Up @@ -184,14 +186,9 @@ func (p *Particle) update(gtx layout.Context, mouse *Mouse, hud *Hud, dt float64
}

// increaseForce increases the dragging force.
func (p *Particle) increaseForce(m *Mouse) {
p.dragForce += m.force
func (p *Particle) increaseForce(m *Mouse, maxDragForce float64) {
p.dragForce += m.getForce()
if p.dragForce > maxDragForce {
p.dragForce = maxDragForce
}
}

// resetForce resets the dragging force to the default value.
func (p *Particle) resetForce(hud *Hud) {
p.dragForce = float64(hud.sliders[0].value)
}

0 comments on commit 3d201d5

Please sign in to comment.