Gisle Aune
2 years ago
13 changed files with 247 additions and 50 deletions
-
31cmd/bustest/main.go
-
60device/state.go
-
60effects/gradient.go
-
4effects/manual.go
-
18effects/pattern.go
-
54effects/random.go
-
23effects/utils.go
-
3interface.go
-
10internal/color/color.go
-
7internal/color/hs.go
-
8internal/color/rgb.go
-
5internal/gentools/ptr.go
-
2services/effectenforcer.go
@ -0,0 +1,60 @@ |
|||
package effects |
|||
|
|||
import ( |
|||
"fmt" |
|||
"git.aiterp.net/lucifer3/server/device" |
|||
"math" |
|||
"time" |
|||
) |
|||
|
|||
type Gradient struct { |
|||
States []device.State `json:"states,omitempty"` |
|||
AnimationMS int64 `json:"AnimationMs,omitempty"` |
|||
Reverse bool `json:"backward,omitempty"` |
|||
Interpolate bool `json:"interpolate,omitempty"` |
|||
} |
|||
|
|||
func (e Gradient) State(index, length, round, _ int) device.State { |
|||
if len(e.States) == 0 { |
|||
return device.State{} |
|||
} |
|||
|
|||
if e.Reverse { |
|||
index = length - (index + 1) |
|||
} |
|||
|
|||
walkedIndex := (index + round) % length |
|||
indexFactor := math.Min(float64(walkedIndex)/float64(length-1), 1) |
|||
stateIncrement := 1.0 / float64(len(e.States)-1) |
|||
|
|||
for i := range e.States { |
|||
a := float64(i) * stateIncrement |
|||
if indexFactor >= a { |
|||
si := e.States[i] |
|||
sj := e.States[(i+1)%len(e.States)] |
|||
f := (indexFactor - a) / stateIncrement |
|||
|
|||
if f < 0 || f > 1 { |
|||
panic(f) |
|||
} |
|||
|
|||
if e.Interpolate { |
|||
return si.Interpolate(sj, f) |
|||
} else if f < 0.5 { |
|||
return si |
|||
} else { |
|||
return sj |
|||
} |
|||
} |
|||
} |
|||
|
|||
return e.States[len(e.States)-1] |
|||
} |
|||
|
|||
func (e Gradient) Frequency() time.Duration { |
|||
return time.Duration(e.AnimationMS) * time.Millisecond |
|||
} |
|||
|
|||
func (e Gradient) EffectDescription() string { |
|||
return fmt.Sprintf("Gradient(states:%s, anim:%dms, int:%t)", statesDescription(e.States), e.AnimationMS, e.Interpolate) |
|||
} |
@ -0,0 +1,54 @@ |
|||
package effects |
|||
|
|||
import ( |
|||
"fmt" |
|||
"git.aiterp.net/lucifer3/server/device" |
|||
"math/rand" |
|||
"time" |
|||
) |
|||
|
|||
type Random struct { |
|||
States []device.State `json:"states,omitempty"` |
|||
Interpolate bool `json:"interpolate,omitempty"` |
|||
AnimationMS int64 `json:"animationMs,omitempty"` |
|||
} |
|||
|
|||
func (e Random) State(_, _, _, _ int) device.State { |
|||
if len(e.States) == 0 { |
|||
return device.State{} |
|||
} |
|||
|
|||
indexFactor := rand.Float64() |
|||
stateIncrement := 1.0 / float64(len(e.States)-1) |
|||
|
|||
for i := range e.States { |
|||
a := float64(i) * stateIncrement |
|||
if indexFactor >= a { |
|||
si := e.States[i] |
|||
sj := e.States[(i+1)%len(e.States)] |
|||
f := (indexFactor - a) / stateIncrement |
|||
|
|||
if f < 0 || f > 1 { |
|||
panic(f) |
|||
} |
|||
|
|||
if e.Interpolate { |
|||
return si.Interpolate(sj, f) |
|||
} else if f < 0.5 { |
|||
return si |
|||
} else { |
|||
return sj |
|||
} |
|||
} |
|||
} |
|||
|
|||
return e.States[len(e.States)-1] |
|||
} |
|||
|
|||
func (e Random) Frequency() time.Duration { |
|||
return time.Duration(e.AnimationMS) * time.Millisecond |
|||
} |
|||
|
|||
func (e Random) EffectDescription() string { |
|||
return fmt.Sprintf("Random(states:%s, anim:%dms, int:%t)", statesDescription(e.States), e.AnimationMS, e.Interpolate) |
|||
} |
@ -0,0 +1,23 @@ |
|||
package effects |
|||
|
|||
import ( |
|||
"git.aiterp.net/lucifer3/server/device" |
|||
"strings" |
|||
) |
|||
|
|||
func statesDescription(states []device.State) string { |
|||
sb := strings.Builder{} |
|||
sb.Grow(128) |
|||
|
|||
sb.WriteRune('[') |
|||
for i, state := range states { |
|||
if i > 0 { |
|||
sb.WriteString(", ") |
|||
} |
|||
|
|||
sb.WriteString(state.String()) |
|||
} |
|||
sb.WriteRune(']') |
|||
|
|||
return sb.String() |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue