Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func init() {
"IPlatformMgr": reflect.TypeOf((*q.IPlatformMgr)(nil)).Elem(),
"IResMgr": reflect.TypeOf((*q.IResMgr)(nil)).Elem(),
"ISceneMgr": reflect.TypeOf((*q.ISceneMgr)(nil)).Elem(),
"ISpineMgr": reflect.TypeOf((*q.ISpineMgr)(nil)).Elem(),
"ISpriteMgr": reflect.TypeOf((*q.ISpriteMgr)(nil)).Elem(),
"ISpriter": reflect.TypeOf((*q.ISpriter)(nil)).Elem(),
"ITilemapMgr": reflect.TypeOf((*q.ITilemapMgr)(nil)).Elem(),
Expand Down Expand Up @@ -74,6 +75,7 @@ func init() {
"PlatformMgr": reflect.ValueOf(&q.PlatformMgr),
"ResMgr": reflect.ValueOf(&q.ResMgr),
"SceneMgr": reflect.ValueOf(&q.SceneMgr),
"SpineMgr": reflect.ValueOf(&q.SpineMgr),
"SpriteMgr": reflect.ValueOf(&q.SpriteMgr),
"TilemapMgr": reflect.ValueOf(&q.TilemapMgr),
"TilemapparserMgr": reflect.ValueOf(&q.TilemapparserMgr),
Expand Down
106 changes: 53 additions & 53 deletions cmd/gox/template/platform/webworker/worker.wrap.gen.js
Original file line number Diff line number Diff line change
@@ -1,54 +1,54 @@
/*------------------------------------------------------------------------------
// This code was generated by template worker.wrap.gen.js.tmpl.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. Any updates should be done in
// "worker.wrap.gen.js.tmpl" so they can be included in the generated
// code.
//----------------------------------------------------------------------------*/
function BindFFI(goBridge) {
var ffi = {}
ffi.gdspx_on_engine_start = goBridge.getGoFunction("gdspx_on_engine_start")
ffi.gdspx_on_engine_update = goBridge.getGoFunction("gdspx_on_engine_update")
ffi.gdspx_on_engine_fixed_update = goBridge.getGoFunction("gdspx_on_engine_fixed_update")
ffi.gdspx_on_engine_destroy = goBridge.getGoFunction("gdspx_on_engine_destroy")
ffi.gdspx_on_engine_reset = goBridge.getGoFunction("gdspx_on_engine_reset")
ffi.gdspx_on_engine_pause = goBridge.getGoFunction("gdspx_on_engine_pause")
ffi.gdspx_on_scene_sprite_instantiated = goBridge.getGoFunction("gdspx_on_scene_sprite_instantiated")
ffi.gdspx_on_sprite_ready = goBridge.getGoFunction("gdspx_on_sprite_ready")
ffi.gdspx_on_sprite_updated = goBridge.getGoFunction("gdspx_on_sprite_updated")
ffi.gdspx_on_sprite_fixed_updated = goBridge.getGoFunction("gdspx_on_sprite_fixed_updated")
ffi.gdspx_on_sprite_destroyed = goBridge.getGoFunction("gdspx_on_sprite_destroyed")
ffi.gdspx_on_sprite_frames_set_changed = goBridge.getGoFunction("gdspx_on_sprite_frames_set_changed")
ffi.gdspx_on_sprite_animation_changed = goBridge.getGoFunction("gdspx_on_sprite_animation_changed")
ffi.gdspx_on_sprite_frame_changed = goBridge.getGoFunction("gdspx_on_sprite_frame_changed")
ffi.gdspx_on_sprite_animation_looped = goBridge.getGoFunction("gdspx_on_sprite_animation_looped")
ffi.gdspx_on_sprite_animation_finished = goBridge.getGoFunction("gdspx_on_sprite_animation_finished")
ffi.gdspx_on_sprite_vfx_finished = goBridge.getGoFunction("gdspx_on_sprite_vfx_finished")
ffi.gdspx_on_sprite_screen_exited = goBridge.getGoFunction("gdspx_on_sprite_screen_exited")
ffi.gdspx_on_sprite_screen_entered = goBridge.getGoFunction("gdspx_on_sprite_screen_entered")
ffi.gdspx_on_mouse_pressed = goBridge.getGoFunction("gdspx_on_mouse_pressed")
ffi.gdspx_on_mouse_released = goBridge.getGoFunction("gdspx_on_mouse_released")
ffi.gdspx_on_key_pressed = goBridge.getGoFunction("gdspx_on_key_pressed")
ffi.gdspx_on_key_released = goBridge.getGoFunction("gdspx_on_key_released")
ffi.gdspx_on_action_pressed = goBridge.getGoFunction("gdspx_on_action_pressed")
ffi.gdspx_on_action_just_pressed = goBridge.getGoFunction("gdspx_on_action_just_pressed")
ffi.gdspx_on_action_just_released = goBridge.getGoFunction("gdspx_on_action_just_released")
ffi.gdspx_on_axis_changed = goBridge.getGoFunction("gdspx_on_axis_changed")
ffi.gdspx_on_collision_enter = goBridge.getGoFunction("gdspx_on_collision_enter")
ffi.gdspx_on_collision_stay = goBridge.getGoFunction("gdspx_on_collision_stay")
ffi.gdspx_on_collision_exit = goBridge.getGoFunction("gdspx_on_collision_exit")
ffi.gdspx_on_trigger_enter = goBridge.getGoFunction("gdspx_on_trigger_enter")
ffi.gdspx_on_trigger_stay = goBridge.getGoFunction("gdspx_on_trigger_stay")
ffi.gdspx_on_trigger_exit = goBridge.getGoFunction("gdspx_on_trigger_exit")
ffi.gdspx_on_ui_ready = goBridge.getGoFunction("gdspx_on_ui_ready")
ffi.gdspx_on_ui_updated = goBridge.getGoFunction("gdspx_on_ui_updated")
ffi.gdspx_on_ui_destroyed = goBridge.getGoFunction("gdspx_on_ui_destroyed")
ffi.gdspx_on_ui_pressed = goBridge.getGoFunction("gdspx_on_ui_pressed")
ffi.gdspx_on_ui_released = goBridge.getGoFunction("gdspx_on_ui_released")
ffi.gdspx_on_ui_hovered = goBridge.getGoFunction("gdspx_on_ui_hovered")
ffi.gdspx_on_ui_clicked = goBridge.getGoFunction("gdspx_on_ui_clicked")
ffi.gdspx_on_ui_toggle = goBridge.getGoFunction("gdspx_on_ui_toggle")
ffi.gdspx_on_ui_text_changed = goBridge.getGoFunction("gdspx_on_ui_text_changed")
return ffi
/*------------------------------------------------------------------------------
// This code was generated by template worker.wrap.gen.js.tmpl.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. Any updates should be done in
// "worker.wrap.gen.js.tmpl" so they can be included in the generated
// code.
//----------------------------------------------------------------------------*/
function BindFFI(goBridge) {
var ffi = {}
ffi.gdspx_on_engine_start = goBridge.getGoFunction("gdspx_on_engine_start")
ffi.gdspx_on_engine_update = goBridge.getGoFunction("gdspx_on_engine_update")
ffi.gdspx_on_engine_fixed_update = goBridge.getGoFunction("gdspx_on_engine_fixed_update")
ffi.gdspx_on_engine_destroy = goBridge.getGoFunction("gdspx_on_engine_destroy")
ffi.gdspx_on_engine_reset = goBridge.getGoFunction("gdspx_on_engine_reset")
ffi.gdspx_on_engine_pause = goBridge.getGoFunction("gdspx_on_engine_pause")
ffi.gdspx_on_scene_sprite_instantiated = goBridge.getGoFunction("gdspx_on_scene_sprite_instantiated")
ffi.gdspx_on_sprite_ready = goBridge.getGoFunction("gdspx_on_sprite_ready")
ffi.gdspx_on_sprite_updated = goBridge.getGoFunction("gdspx_on_sprite_updated")
ffi.gdspx_on_sprite_fixed_updated = goBridge.getGoFunction("gdspx_on_sprite_fixed_updated")
ffi.gdspx_on_sprite_destroyed = goBridge.getGoFunction("gdspx_on_sprite_destroyed")
ffi.gdspx_on_sprite_frames_set_changed = goBridge.getGoFunction("gdspx_on_sprite_frames_set_changed")
ffi.gdspx_on_sprite_animation_changed = goBridge.getGoFunction("gdspx_on_sprite_animation_changed")
ffi.gdspx_on_sprite_frame_changed = goBridge.getGoFunction("gdspx_on_sprite_frame_changed")
ffi.gdspx_on_sprite_animation_looped = goBridge.getGoFunction("gdspx_on_sprite_animation_looped")
ffi.gdspx_on_sprite_animation_finished = goBridge.getGoFunction("gdspx_on_sprite_animation_finished")
ffi.gdspx_on_sprite_vfx_finished = goBridge.getGoFunction("gdspx_on_sprite_vfx_finished")
ffi.gdspx_on_sprite_screen_exited = goBridge.getGoFunction("gdspx_on_sprite_screen_exited")
ffi.gdspx_on_sprite_screen_entered = goBridge.getGoFunction("gdspx_on_sprite_screen_entered")
ffi.gdspx_on_mouse_pressed = goBridge.getGoFunction("gdspx_on_mouse_pressed")
ffi.gdspx_on_mouse_released = goBridge.getGoFunction("gdspx_on_mouse_released")
ffi.gdspx_on_key_pressed = goBridge.getGoFunction("gdspx_on_key_pressed")
ffi.gdspx_on_key_released = goBridge.getGoFunction("gdspx_on_key_released")
ffi.gdspx_on_action_pressed = goBridge.getGoFunction("gdspx_on_action_pressed")
ffi.gdspx_on_action_just_pressed = goBridge.getGoFunction("gdspx_on_action_just_pressed")
ffi.gdspx_on_action_just_released = goBridge.getGoFunction("gdspx_on_action_just_released")
ffi.gdspx_on_axis_changed = goBridge.getGoFunction("gdspx_on_axis_changed")
ffi.gdspx_on_collision_enter = goBridge.getGoFunction("gdspx_on_collision_enter")
ffi.gdspx_on_collision_stay = goBridge.getGoFunction("gdspx_on_collision_stay")
ffi.gdspx_on_collision_exit = goBridge.getGoFunction("gdspx_on_collision_exit")
ffi.gdspx_on_trigger_enter = goBridge.getGoFunction("gdspx_on_trigger_enter")
ffi.gdspx_on_trigger_stay = goBridge.getGoFunction("gdspx_on_trigger_stay")
ffi.gdspx_on_trigger_exit = goBridge.getGoFunction("gdspx_on_trigger_exit")
ffi.gdspx_on_ui_ready = goBridge.getGoFunction("gdspx_on_ui_ready")
ffi.gdspx_on_ui_updated = goBridge.getGoFunction("gdspx_on_ui_updated")
ffi.gdspx_on_ui_destroyed = goBridge.getGoFunction("gdspx_on_ui_destroyed")
ffi.gdspx_on_ui_pressed = goBridge.getGoFunction("gdspx_on_ui_pressed")
ffi.gdspx_on_ui_released = goBridge.getGoFunction("gdspx_on_ui_released")
ffi.gdspx_on_ui_hovered = goBridge.getGoFunction("gdspx_on_ui_hovered")
ffi.gdspx_on_ui_clicked = goBridge.getGoFunction("gdspx_on_ui_clicked")
ffi.gdspx_on_ui_toggle = goBridge.getGoFunction("gdspx_on_ui_toggle")
ffi.gdspx_on_ui_text_changed = goBridge.getGoFunction("gdspx_on_ui_text_changed")
return ffi
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func init() {
"IPlatformMgr": reflect.TypeOf((*q.IPlatformMgr)(nil)).Elem(),
"IResMgr": reflect.TypeOf((*q.IResMgr)(nil)).Elem(),
"ISceneMgr": reflect.TypeOf((*q.ISceneMgr)(nil)).Elem(),
"ISpineMgr": reflect.TypeOf((*q.ISpineMgr)(nil)).Elem(),
"ISpriteMgr": reflect.TypeOf((*q.ISpriteMgr)(nil)).Elem(),
"ISpriter": reflect.TypeOf((*q.ISpriter)(nil)).Elem(),
"ITilemapMgr": reflect.TypeOf((*q.ITilemapMgr)(nil)).Elem(),
Expand Down Expand Up @@ -74,6 +75,7 @@ func init() {
"PlatformMgr": reflect.ValueOf(&q.PlatformMgr),
"ResMgr": reflect.ValueOf(&q.ResMgr),
"SceneMgr": reflect.ValueOf(&q.SceneMgr),
"SpineMgr": reflect.ValueOf(&q.SpineMgr),
"SpriteMgr": reflect.ValueOf(&q.SpriteMgr),
"TilemapMgr": reflect.ValueOf(&q.TilemapMgr),
"TilemapparserMgr": reflect.ValueOf(&q.TilemapparserMgr),
Expand Down
11 changes: 11 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,16 @@ type animPayload struct {
MaxBitmap int64 `json:"max_bitmap"`
}

// Spine animation configuration
type spineAnimConfig struct {
Atlas string `json:"atlas"` // atlas file path, e.g. "spine/spineboy.atlas"
Skeleton string `json:"skeleton"` // skeleton file path, e.g. "spine/spineboy-pro.skel"
DefaultMix float64 `json:"defaultMix"` // animation mix time, default 0.1
AnimMap map[string]string `json:"animMap"` // SPX animation name -> Spine animation name mapping
StepDuration float64 `json:"stepDuration"` // step animation duration factor, default 0.01
TurnToDuration float64 `json:"turnToDuration"` // turn animation duration for 360 degrees, default 1.0
}
Comment on lines +276 to +284

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security: Missing Input Validation

Numeric parameters (DefaultMix, StepDuration, TurnToDuration) loaded from JSON lack validation. Users could provide extreme values (NaN, Infinity, negative numbers, very large values) that could cause:

  • Division by zero in animation calculations
  • Resource exhaustion through extremely long durations
  • Unexpected behavior with NaN propagation

Recommendation: Add validation in initSpineConfig():

if cfg.DefaultMix < 0 || math.IsNaN(cfg.DefaultMix) || math.IsInf(cfg.DefaultMix, 0) {
    log.Printf("Warning: Invalid DefaultMix value, using default")
    cfg.DefaultMix = 0.1
}
// Similar checks for StepDuration and TurnToDuration


// -------------------------------------------------------------------------------------

type spriteConfig struct {
Expand All @@ -288,6 +298,7 @@ type spriteConfig struct {
FAnimations map[string]*aniConfig `json:"fAnimations"`
MAnimations map[string]*aniConfig `json:"mAnimations"`
TAnimations map[string]*aniConfig `json:"tAnimations"`
SpineAnim *spineAnimConfig `json:"spineAnim"` // Spine animation configuration (optional)
Visible bool `json:"visible"`
IsDraggable bool `json:"isDraggable"`
Pivot mathf.Vec2 `json:"pivot"`
Expand Down
14 changes: 13 additions & 1 deletion gdspx.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,25 @@ func (sprite *SpriteImpl) syncCheckInitProxy() {
// bind syncSprite
if sprite.syncSprite == nil && !sprite.HasDestroyed {
sprite.syncSprite = engine.SyncNewSprite(sprite, mathf.NewVec2(sprite.x, sprite.y))
syncInitSpritePhysicInfo(sprite, sprite.syncSprite)
sprite.syncSprite.Name = sprite.name
sprite.syncSprite.SetTypeName(sprite.name)
sprite.syncSprite.SetVisible(sprite.isVisible)
sprite.applyGraphicEffects(true)
sprite.syncSprite.RegisterOnAnimationLooped(sprite.syncOnAnimationLooped)
sprite.syncSprite.RegisterOnAnimationFinished(sprite.syncOnAnimationFinished)

// Spine mode: set skeleton first, then set renderScale (C++ will calculate correct collision box)
if sprite.isSpineMode() {
atlasPath := engine.ToAssetPath(sprite.spineConfig.Atlas)
skeletonPath := engine.ToAssetPath(sprite.spineConfig.Skeleton)
sprite.syncSprite.SetSpineSkeleton(atlasPath, skeletonPath, sprite.spineConfig.DefaultMix)
// In Spine mode, need to set renderScale, which triggers C++ side to update collision box
renderScale := sprite.getCostumeRenderScale()
sprite.syncSprite.SetRenderScale(mathf.NewVec2(renderScale, renderScale))
}

// Initialize physics config (C++ has already set collision box in Spine mode)
syncInitSpritePhysicInfo(sprite, sprite.syncSprite)
// Mark as dirty to ensure initial sync
sprite.isDirty = true
}
Expand Down
Loading