alchemyst/engine/types/appearance.go

197 lines
4.3 KiB
Go

package types
import (
"bytes"
"fmt"
"github.com/gammazero/deque"
"lab.zaar.be/thefish/alchemyst-go/engine/ecs"
"lab.zaar.be/thefish/alchemyst-go/util"
)
import blt "lab.zaar.be/thefish/bearlibterminal"
var crng = util.NewRNG()
type ColorHolder interface {
GetColor() uint32
}
type cdeque struct {
deque.Deque
}
func (c *cdeque) Next() uint8 {
c.Rotate(1)
return c.Front().(uint8)
}
type DanceColorHolder struct {
A uint8
R *cdeque
G *cdeque
B *cdeque
}
func (dch DanceColorHolder) GetColor() uint32 {
return blt.ColorFromARGB(
dch.A,
dch.R.Next(),
dch.G.Next(),
dch.B.Next(),
)
}
type PlainColorHolder struct {
A uint8
R uint8
G uint8
B uint8
}
func (chb PlainColorHolder) GetColor() uint32 {
return blt.ColorFromARGB(
chb.A,
chb.R,
chb.G,
chb.B,
)
}
type TileColorSet struct {
Fg ColorHolder `json:"fg"`
Bg ColorHolder `json:"bg"`
DarkFg ColorHolder `json:"darkfg"`
DarkBg ColorHolder `json:"darkbg"`
}
type GlyphHolder interface {
GetGlyph() string
}
type PlainGlyphHolder struct {
Glyph string
}
func (pgh PlainGlyphHolder) GetGlyph() string {
return pgh.Glyph
}
type Appearance struct {
Glyph GlyphHolder `json:"glyph"`
ColorSet TileColorSet `json:"colorSet"`
}
func SingleColorRing(colorValue uint8) *cdeque {
c := &cdeque{}
c.PushBack(colorValue)
return c
}
func FillColorRing(colorValue uint8, minGlow, maxGlow, step int) *cdeque {
q := make([]uint8, 0)
color := int(colorValue)
for color < maxGlow {
q = append(q, uint8(color))
color = crng.Range(1, step) + color
}
color = crng.Range(0, step+minGlow)
q = append(q, colorValue)
//for uint8(color) < uint8(colorValue) {
// q = append(q, uint8(color))
// color = crng.Range(1, step+minGlow)
//}
c := &cdeque{}
for _, v := range q {
c.PushBack(uint8(v))
}
return c
}
func DeviatedColorRing(colorValue uint8, minGlow, maxGlow int) *cdeque {
q := make([]uint8, 0)
color := int(colorValue)
color = crng.Range(minGlow, maxGlow) + color
q = append(q, colorValue)
c := &cdeque{}
c.PushBack(uint8(color))
return c
}
func (app Appearance) Type() string {
return ecs.AppearanceComponent
}
func (app *Appearance) MarshalJSON() ([]byte, error) {
buffer := bytes.NewBufferString("{")
//glyph
buffer.WriteString(`"glyph":{`)
if _, ok := app.Glyph.(*PlainGlyphHolder); ok {
buffer.WriteString(fmt.Sprintf(`"type":"plain", "chars":"%s"`, app.Glyph.GetGlyph()))
}
buffer.WriteString("},")
//color
buffer.WriteString(`"color":{`)
buffer.WriteString(getColorJson("fg", app.ColorSet.Fg) + ",")
buffer.WriteString(getColorJson("bg", app.ColorSet.Bg) + ",")
buffer.WriteString(getColorJson("darkfg", app.ColorSet.DarkFg) + ",")
buffer.WriteString(getColorJson("darkbg", app.ColorSet.DarkBg))
buffer.WriteString("}")
buffer.WriteString("}")
fmt.Printf("\n\nbuffer: %s\n\n", buffer.String())
return buffer.Bytes(), nil
}
func (app *Appearance) UnmarshalJSON(buffer []byte) error {
return nil
}
func getColorJson(field string, holder ColorHolder) string {
result := ""
if _, dch := holder.(*DanceColorHolder); dch {
result = fmt.Sprintf(`{"dance":{`)
result = result + detectRing("a", holder.(*DanceColorHolder).A) + ","
result = result + detectRing("r", holder.(*DanceColorHolder).R) + ","
result = result + detectRing("g", holder.(*DanceColorHolder).G) + ","
result = result + detectRing("b", holder.(*DanceColorHolder).B)
result = result + "}}"
}
if _, pch := holder.(*PlainColorHolder); pch {
result = fmt.Sprintf(`{"plain":[%d,%d,%d,%d]}`,
holder.(*PlainColorHolder).A,
holder.(*PlainColorHolder).R,
holder.(*PlainColorHolder).G,
holder.(*PlainColorHolder).B,
)
}
return fmt.Sprintf(`"%s":%s`, field, result)
}
func detectRing(channel string, something interface{}) string {
result := ""
switch something.(type) {
case (int),(uint8):
result += fmt.Sprintf(`"%s":{"plain":%d}`, channel, something)
case (*cdeque):
fmt.Printf("%v", something)
if something.(*cdeque).Len() == 1 {
//fixme right now we can not distinct plain and deviated
result += fmt.Sprintf(`"%s":{"single":[%v]}`, channel, something.(*cdeque).Front())
} else {
result += fmt.Sprintf(`"%s":{"fill":[%v, %v, %v, %v]}`,
channel,
something.(*cdeque).Front(),
something.(*cdeque).Next(),
something.(*cdeque).Next(),
something.(*cdeque).Next(),
)
}
}
return result
}