diff --git a/camera.go b/camera.go index a3ea7b6..b9227ba 100644 --- a/camera.go +++ b/camera.go @@ -27,7 +27,7 @@ type Camera struct { on_ interface{} } -func (c *Camera) init(g *Game, winW, winH float64, worldW, worldH float64) { +func (c *Camera) init(g *Game) { c.g = g } diff --git a/game.go b/game.go index 5a436af..b7ad893 100644 --- a/game.go +++ b/game.go @@ -443,7 +443,7 @@ func (p *Game) loadIndex(g reflect.Value, proj *projConfig) (err error) { } engine.SyncPlatformSetWindowSize(int64(p.windowWidth_), int64(p.windowHeight_)) - p.Camera.init(p, float64(p.windowWidth_), float64(p.windowHeight_), float64(p.worldWidth_), float64(p.worldHeight_)) + p.Camera.init(p) // setup proxy's property p.proxy = engine.SyncNewBackdropProxy(p, p.getCostumePath(), p.getCostumeRenderScale()) diff --git a/go.mod b/go.mod index e5910a2..fe1f45f 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,12 @@ go 1.21.3 require ( github.com/pkg/errors v0.9.1 github.com/realdream-ai/gdspx v0.0.0-20241204130734-35c372f84f57 - github.com/realdream-ai/mathf v0.0.0-20241204125103-284ee6a3722d - golang.org/x/image v0.18.0 + github.com/realdream-ai/mathf v0.0.0-20241205091834-a85cb2402a16 golang.org/x/mobile v0.0.0-20220518205345-8578da9835fd ) +require golang.org/x/image v0.23.0 // indirect + replace ( golang.org/x/image => golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d golang.org/x/mobile => golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5 diff --git a/go.sum b/go.sum index 3ebb0db..1cc4cf3 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/realdream-ai/gdspx v0.0.0-20241204130734-35c372f84f57 h1:iF9BObP4FNyjdyxJD8ng0mCf+dJTaVExco+QWChoukc= github.com/realdream-ai/gdspx v0.0.0-20241204130734-35c372f84f57/go.mod h1:UCzetvoQdU+yfesI6xAL33acsuEbYICGQUcYpGiAW00= -github.com/realdream-ai/mathf v0.0.0-20241204125103-284ee6a3722d h1:hEIUl272UkUUd2F77nONdEDR1tHLpe1MAgaYAGoVnEk= -github.com/realdream-ai/mathf v0.0.0-20241204125103-284ee6a3722d/go.mod h1:oAFczOO99bG05kC9tKp5deLqrvZSjtBDIpNH36ZWwnY= +github.com/realdream-ai/mathf v0.0.0-20241205091834-a85cb2402a16 h1:V/zAuyQF0v6ng+UVwJi+qF0s+P/nEHb/lha3Uf86TQM= +github.com/realdream-ai/mathf v0.0.0-20241205091834-a85cb2402a16/go.mod h1:zCbLmeT7a+pH1sknxgdFLiha6xA3gezTtwbTuuNRJWE= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= diff --git a/internal/gdi/color_utils.go b/internal/gdi/color_utils.go deleted file mode 100644 index 0ce8634..0000000 --- a/internal/gdi/color_utils.go +++ /dev/null @@ -1,105 +0,0 @@ -package gdi - -import ( - "math" - "math/rand" -) - -// HSV2RGB converts hue (0-360), saturation (0-1), and brightness (0-1) to RGB. -func HSV2RGB(h, s, v float64) (uint8, uint8, uint8) { - var r, g, b float64 - h = math.Mod(h, 360) - if h < 0 { - h += 360 - } - s = math.Max(0, math.Min(s, 1)) - v = math.Max(0, math.Min(v, 1)) - - i := math.Floor(h / 60) - f := (h / 60) - i - p := v * (1 - s) - q := v * (1 - (s * f)) - t := v * (1 - (s * (1 - f))) - switch int(i) { - case 0: - r = v - g = t - b = p - case 1: - r = q - g = v - b = p - case 2: - r = p - g = v - b = t - case 3: - r = p - g = q - b = v - case 4: - r = t - g = p - b = v - case 5: - r = v - g = p - b = q - } - return uint8(math.Floor(r * 255)), uint8(math.Floor(g * 255)), uint8(math.Floor(b * 255)) -} - -// RGB2HSV converts RGB to an array containing the hue, saturation, and brightness. -func RGB2HSV(R, G, B uint8) (h, s, v float64) { - var f, i float64 - r := float64(R) / 255 - g := float64(G) / 255 - b := float64(B) / 255 - x := math.Min(math.Min(r, g), b) - v = math.Max(math.Max(r, g), b) - if x == v { - return // gray; hue arbitrarily reported as zero - } - if r == x { - f = g - b - i = 3 - } else if g == x { - f = b - r - i = 5 - } else { - f = r - g - i = 1 - } - h = math.Mod((i-(f/(v-x)))*60, 360) - s = (v - x) / v - return -} - -// ScaleBrightness changes color brightness. -func ScaleBrightness(r, g, b uint8, scale float64) (uint8, uint8, uint8) { - h, s, v := RGB2HSV(r, g, b) - val := math.Max(0, math.Min(scale*v, 1)) - return HSV2RGB(h, s, val) -} - -// MixRGB mixs rgb1 with rgb2. 0 gives all rgb1, 1 gives rbg2, .5 mixes them 50/50. -func MixRGB(r1, g1, b1 uint8, r2, g2, b2 uint8, fraction float64) (r, g, b uint8) { - if fraction <= 0 { - return r1, g1, b1 - } - if fraction >= 1 { - return r2, g2, b2 - } - r = uint8(fraction*float64(r2) + (1.0-fraction)*float64(r1)) - g = uint8(fraction*float64(g2) + (1.0-fraction)*float64(g1)) - b = uint8(fraction*float64(b2) + (1.0-fraction)*float64(b1)) - return -} - -// Random returns a random color. -func Random() (uint8, uint8, uint8) { - h := 360 * rand.Float64() - s := 0.7 + (0.3 * rand.Float64()) - v := 0.6 + (0.4 * rand.Float64()) - return HSV2RGB(h, s, v) -} diff --git a/internal/gdi/text.go b/internal/text/text.go similarity index 96% rename from internal/gdi/text.go rename to internal/text/text.go index b489fd2..e5e3b7f 100644 --- a/internal/gdi/text.go +++ b/internal/text/text.go @@ -1,4 +1,4 @@ -package gdi +package text import ( "strings" @@ -29,7 +29,7 @@ func calculateWordLength(word string) int { } // splitString splits the input string into lines with a maximum placeholder width n -func SplitString(input string, n int) string { +func SplitLines(input string, n int) string { words := strings.Fields(input) var result strings.Builder lineLength := 0 diff --git a/internal/ui/ui_say.go b/internal/ui/ui_say.go index 38ae19c..231d30e 100644 --- a/internal/ui/ui_say.go +++ b/internal/ui/ui_say.go @@ -7,13 +7,13 @@ import ( . "github.com/realdream-ai/gdspx/pkg/engine" "github.com/goplus/spx/internal/engine" - "github.com/goplus/spx/internal/gdi" + "github.com/goplus/spx/internal/text" ) const ( - SayMsgSpliteWidth = 25 - SayMsgLineHeight = 26 - SayMsgDefaultHeight = 77 + sayMsgSpliteWidth = 25 + sayMsgLineHeight = 26 + sayMsgDefaultHeight = 77 ) type UiSay struct { @@ -50,10 +50,10 @@ func (pself *UiSay) SetText(winX, winY float64, x, y float64, w, h float64, msg hasNextLine := strings.ContainsRune(msg, '\n') finalMsg := msg if !hasNextLine { - finalMsg = gdi.SplitString(msg, SayMsgSpliteWidth) + finalMsg = text.SplitLines(msg, sayMsgSpliteWidth) } lineCount := strings.Count(finalMsg, "\n") - uiHeight := SayMsgDefaultHeight + float64(lineCount)*SayMsgLineHeight + uiHeight := sayMsgDefaultHeight + float64(lineCount)*sayMsgLineHeight maxYPos := winY/2 - uiHeight yPos = math.Max(-winY/2, math.Min(yPos, maxYPos)) xPos = math.Max(-winX/2, math.Min(x, winX/2)) diff --git a/measure.go b/measure.go index 44c79f7..02243bc 100644 --- a/measure.go +++ b/measure.go @@ -22,6 +22,7 @@ import ( "strings" "github.com/goplus/spx/internal/ui" + "github.com/realdream-ai/mathf" ) const ( @@ -38,7 +39,7 @@ type measure struct { // computed properties text string - color Color + color mathf.Color svgLineStyle string svgRotate string svgSize int // size*scale + 0.5 + measureLineWidth @@ -52,7 +53,7 @@ func newMeasure(v specsp) *measure { text = strings.TrimSuffix(text, ".0") heading := getSpcspVal(v, "heading", 0.0).(float64) svgSize := int(size*scale + 0.5 + measureLineWidth) - c, err := parseColor(getSpcspVal(v, "color", 0.0)) + c, err := mathf.NewColorAny(getSpcspVal(v, "color", 0.0)) if err != nil { panic(err) } @@ -69,7 +70,7 @@ func newMeasure(v specsp) *measure { svgSize: svgSize, panel: panel, } - panel.UpdateInfo(meansureObj.x, meansureObj.y, size*scale, heading, text, toEngineColor(c)) + panel.UpdateInfo(meansureObj.x, meansureObj.y, size*scale, heading, text, c) return meansureObj } diff --git a/monitor.go b/monitor.go index af1412b..1fd90f0 100644 --- a/monitor.go +++ b/monitor.go @@ -25,6 +25,7 @@ import ( "github.com/goplus/spx/internal/tools" "github.com/goplus/spx/internal/ui" + "github.com/realdream-ai/mathf" ) // ------------------------------------------------------------------------------------- @@ -38,7 +39,7 @@ type Monitor struct { val string eval func() string mode int - color Color + color mathf.Color x, y float64 label string visible bool @@ -72,9 +73,9 @@ func newMonitor(g reflect.Value, v specsp) (*Monitor, error) { return nil, syscall.ENOENT } mode := int(v["mode"].(float64)) - color, err := parseColor(getSpcspVal(v, "color")) + color, err := mathf.NewColorAny(getSpcspVal(v, "color")) if err != nil { - color = Color{R: 0x28, G: 0x9c, B: 0xfc, A: 0xff} + color = RGBA(0x28, 0x9c, 0xfc, 0xff) } label := v["label"].(string) x := v["x"].(float64) @@ -100,7 +101,7 @@ func (pself *Monitor) onUpdate(delta float64) { pself.panel.UpdateScale(pself.size) pself.panel.UpdatePos(pself.x, pself.y) pself.panel.UpdateText(pself.label, val) - pself.panel.UpdateColor(toEngineColor(pself.color)) + pself.panel.UpdateColor(pself.color) } func getTarget(g reflect.Value, target string) (reflect.Value, int) { @@ -151,26 +152,6 @@ func (p *Monitor) setVisible(visible bool) { p.visible = visible } -const ( - stmDefaultW = 47 - stmDefaultSmW = 41 - stmCornerSize = 2 - stmVertGapSm = 4 - stmHoriGapSm = 5 -) - -var ( - stmBackground = Color{R: 0xf6, G: 0xf8, B: 0xfa, A: 0xff} - stmBackgroundPen = Color{R: 0xf6, G: 0xf8, B: 0xfa, A: 0xff} - stmValueground = Color{R: 0x21, G: 0x9f, B: 0xfc, A: 0xff} - stmValueRectPen = Color{R: 0xf6, G: 0xf8, B: 0xfa, A: 0xff} -) - -type rectKey struct { - x, y, w, h float64 - clr, clrPen Color -} - // ------------------------------------------------------------------------------------- // IWidget func (pself *Monitor) GetName() WidgetName { diff --git a/pen.go b/pen.go index 3c4c815..14f1ecb 100644 --- a/pen.go +++ b/pen.go @@ -16,16 +16,14 @@ package spx -import ( - "image/color" -) +import "github.com/realdream-ai/mathf" // ------------------------------------------------------------------------------------- type penLine struct { x1, y1 int x2, y2 int - clr color.RGBA + clr mathf.Color width int } diff --git a/sprite.go b/sprite.go index 9a573de..b9e790a 100644 --- a/sprite.go +++ b/sprite.go @@ -17,13 +17,11 @@ package spx import ( - "image/color" "log" "math" "reflect" "github.com/goplus/spx/internal/engine" - "github.com/goplus/spx/internal/gdi" "github.com/goplus/spx/internal/time" "github.com/goplus/spx/internal/tools" "github.com/realdream-ai/mathf" @@ -199,7 +197,7 @@ type SpriteImpl struct { animBindings map[string]string defaultAnimation SpriteAnimationName - penColor color.RGBA + penColor mathf.Color penShade float64 penHue float64 penWidth float64 @@ -1394,8 +1392,6 @@ func (p *SpriteImpl) ClearGraphEffects() { // ----------------------------------------------------------------------------- -type Color = color.RGBA - func (p *SpriteImpl) TouchingColor(color Color) bool { panic("todo gdspx") } @@ -1544,7 +1540,7 @@ func (p *SpriteImpl) PenDown() { } func (p *SpriteImpl) SetPenColor(color Color) { - h, _, v := gdi.RGB2HSV(color.R, color.G, color.B) + h, _, v := color.ToHSV() p.penHue = (200 * h) / 360 p.penShade = 50 * v p.penColor = color @@ -1595,17 +1591,18 @@ func (p *SpriteImpl) setPenShade(v float64, change bool) { } func (p *SpriteImpl) doUpdatePenColor() { - r, g, b := gdi.HSV2RGB((p.penHue*180)/100, 1, 1) + color := mathf.NewColorHSV((p.penHue*180)/100, 1, 1) shade := p.penShade if shade > 100 { // range 0..100 shade = 200 - shade } + a := p.penColor.A if shade < 50 { - r, g, b = gdi.MixRGB(0, 0, 0, r, g, b, (10+shade)/60) + p.penColor = mathf.LerpColor(mathf.ColorBlack(), color, (10+shade)/60) } else { - r, g, b = gdi.MixRGB(r, g, b, 255, 255, 255, (shade-50)/60) + p.penColor = mathf.LerpColor(color, mathf.ColorWhite(), (shade-50)/60) } - p.penColor = color.RGBA{R: r, G: g, B: b, A: p.penColor.A} + p.penColor.A = a } func (p *SpriteImpl) SetPenSize(size float64) { diff --git a/uinode.go b/uinode.go deleted file mode 100644 index 453513e..0000000 --- a/uinode.go +++ /dev/null @@ -1,19 +0,0 @@ -package spx - -import ( - gdspx "github.com/realdream-ai/gdspx/pkg/engine" - - "github.com/goplus/spx/internal/engine" -) - -type ProxyUi struct { - gdspx.UiNode -} - -func NewUiNode(path string) *ProxyUi { - node := engine.SyncCreateUiNode[ProxyUi](path) - return node -} -func (pthis *ProxyUi) SetText(text string) { - engine.SyncUiSetText(pthis.UiNode.Id, text) -} diff --git a/utils.go b/utils.go index d8fd31b..a6825b2 100644 --- a/utils.go +++ b/utils.go @@ -17,22 +17,15 @@ package spx import ( - "errors" "math/rand" "os" "time" "github.com/realdream-ai/mathf" - "golang.org/x/image/colornames" ) // ----------------------------------------------------------------------------- -var ( - errInvalidColorFormat = errors.New("invalid color format") - errUnsupportedColorFormat = errors.New("unsupported color format") -) - func init() { rand.Seed(time.Now().UnixNano()) } @@ -59,74 +52,23 @@ func Iround(v float64) int { return int(v - 0.5) } +type Color = mathf.Color + // ----------------------------------------------------------------------------- func RGB(r, g, b uint8) Color { - return Color{R: r, G: g, B: b, A: 0xff} + return mathf.NewColorRGBi(r, g, b) } func RGBA(r, g, b, a uint8) Color { - return Color{R: r, G: g, B: b, A: a} + return mathf.NewColorRGBAi(r, g, b, a) } -func toEngineColor(c Color) mathf.Color { - return mathf.NewColor(float64(c.R)/255, float64(c.G)/255, float64(c.B)/255, float64(c.A)/255) +func RGBf(r, g, b float64) Color { + return mathf.NewColorRGB(r, g, b) } -// parseColor, s can be int, float64 or string -func parseColor(s interface{}) (Color, error) { - if s == nil { - return Color{}, errors.New("color is nil") - } - if c, ok := s.(int); ok { - return Color{uint8(c >> 16), uint8((c >> 8) & 0xff), uint8(c & 0xff), 0xff}, nil - } - if f, ok := s.(float64); ok { - c := int(f) - return Color{uint8(c >> 16), uint8((c >> 8) & 0xff), uint8(c & 0xff), 0xff}, nil - } - ss, ok := s.(string) - if !ok { - return Color{}, errUnsupportedColorFormat - } - c, ok := colornames.Map[ss] - if ok { - return c, nil - } - return parseHexColor(ss) -} - -func parseHexColor(s string) (Color, error) { - if s == "" || s[0] != '#' { - return Color{}, errInvalidColorFormat - } - var err error - hexToByte := func(b byte) byte { - switch { - case b >= '0' && b <= '9': - return b - '0' - case b >= 'a' && b <= 'f': - return b - 'a' + 10 - case b >= 'A' && b <= 'F': - return b - 'A' + 10 - default: - err = errInvalidColorFormat - return 0 - } - } - c := Color{A: 0xff} - switch len(s) { - case 7: - c.R = hexToByte(s[1])<<4 + hexToByte(s[2]) - c.G = hexToByte(s[3])<<4 + hexToByte(s[4]) - c.B = hexToByte(s[5])<<4 + hexToByte(s[6]) - case 4: - c.R = hexToByte(s[1]) * 17 - c.G = hexToByte(s[2]) * 17 - c.B = hexToByte(s[3]) * 17 - default: - err = errInvalidColorFormat - } - return c, err +func RGBAf(r, g, b, a float64) Color { + return mathf.NewColorRGBA(r, g, b, a) } // -----------------------------------------------------------------------------