Skip to content

Commit

Permalink
Support ispx with generics (#312)
Browse files Browse the repository at this point in the history
* simplify `Gopt_Game_Gopx_GetWidget`

* split getWidget

* make `getAllShapes` private
  • Loading branch information
nighca committed Aug 28, 2024
1 parent 3df776b commit d1b083e
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 20 deletions.
45 changes: 25 additions & 20 deletions game.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ type Spriter interface {
}
type Gamer interface {
initGame(sprites []Spriter) *Game
getGame() *Game
}

func (p *Game) IsRunned() bool {
Expand Down Expand Up @@ -1351,32 +1350,38 @@ func (p *Game) ShowVar(name string) {
p.setStageMonitor("", getVarPrefix+name, true)
}

func (p *Game) getAllShapes() []Shape {
return p.items
}

// -----------------------------------------------------------------------------
// Widget

// GetWidget returns the widget instance with given name. It panics if not found.
func Gopt_Game_Gopx_GetWidget[T any](game interface{}, name string) *T {
var gamePtr *Game
switch ptr := game.(type) {
case *Game:
gamePtr = ptr
case interface{ Parent() *Game }:
gamePtr = ptr.Parent()
case Gamer:
gamePtr = ptr.getGame()
default:
panic("GetWidget: unexpected game type" + reflect.TypeOf(game).String())
}
items := gamePtr.items
type ShapeGetter interface {
getAllShapes() []Shape
}

// GetWidget_ returns the widget instance with given name. It panics if not found.
// Instead of being used directly, it is meant to be called by `Gopt_Game_Gopx_GetWidget` only.
// We extract `GetWidget_` to keep `Gopt_Game_Gopx_GetWidget` simple, which simplifies work in ispx,
// see details in https://github.com/goplus/builder/issues/765#issuecomment-2313915805.
func GetWidget_(sg ShapeGetter, name string) Widget {
items := sg.getAllShapes()
for _, item := range items {
widget, ok := item.(Widget)
if ok && widget.GetName() == name {
if result, ok := widget.(interface{}).(*T); ok {
return result
} else {
panic("GetWidget: type mismatch - expected " + reflect.TypeOf((*T)(nil)).Elem().String() + ", got " + reflect.TypeOf(widget).String())
}
return widget
}
}
panic("GetWidget: widget not found - " + name)
}

// GetWidget returns the widget instance (in given type) with given name. It panics if not found.
func Gopt_Game_Gopx_GetWidget[T any](sg ShapeGetter, name string) *T {
widget := GetWidget_(sg, name)
if result, ok := widget.(interface{}).(*T); ok {
return result
} else {
panic("GetWidget: type mismatch")
}
}
4 changes: 4 additions & 0 deletions sprite.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ func (p *Sprite) Parent() *Game {
return p.g
}

func (p *Sprite) getAllShapes() []Shape {
return p.g.getAllShapes()
}

func (p *Sprite) init(
base string, g *Game, name string, sprite *spriteConfig, gamer reflect.Value, shared *sharedImages) {
if sprite.Costumes != nil {
Expand Down

0 comments on commit d1b083e

Please sign in to comment.