Skip to content

Comments

Update sprite's scale(render & collision) implement #979

Draft
JiepengTan wants to merge 1 commit intogoplus:devfrom
JiepengTan:pr_update_sprite_scale_impl
Draft

Update sprite's scale(render & collision) implement #979
JiepengTan wants to merge 1 commit intogoplus:devfrom
JiepengTan:pr_update_sprite_scale_impl

Conversation

@JiepengTan
Copy link
Contributor

@JiepengTan JiepengTan commented Oct 27, 2025

related pr: goplus/godot#186

@JiepengTan JiepengTan marked this pull request as draft October 27, 2025 15:42
@gemini-code-assist
Copy link

Summary of Changes

Hello @JiepengTan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request refactors the sprite transformation system to provide more explicit control over scaling and horizontal flipping. It introduces a dedicated boolean flag for horizontal flipping, separating it from the general scale factor, and updates the underlying engine and FFI layers to support this new approach. The changes aim to improve clarity and control over how sprites are rendered and manipulated.

Highlights

  • Sprite Transformation Logic Refinement: The calcRenderRotation function now explicitly returns a boolean flipH for horizontal flipping instead of incorporating it into a hScale float. This separates flipping from general scaling.
  • Unified Scaling Implementation: The UpdateTransform method in internal/engine/sprite.go now consistently uses sprite.scale for scaling and ensures the scale value is always positive. It also applies uniform scaling using NewVec2(scale, scale).
  • Dedicated Horizontal Flip Control: A new flipH boolean parameter has been introduced in UpdateTransform and propagated through the engine, allowing for explicit horizontal flipping of sprites.
  • FFI and Engine Interface Updates: New SetFlipH, IsFlipH, and UpdateAllSvgSpritesScale methods have been added to the engine's sprite manager interface and their corresponding FFI bindings, enabling external control over sprite flipping and SVG scale updates.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@JiepengTan JiepengTan changed the title Update sprite scale impl Update sprite's scale(render & collision) implement Oct 27, 2025
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the sprite scale implementation by introducing a flipH parameter to handle horizontal flipping, and adjusts the scale calculation to ensure correct scaling behavior. The changes involve modifications across several files to accommodate the new parameter and logic.

gdspx.go Outdated
Comment on lines 165 to 167
rot, flipH := calcRenderRotation(sprite)
scale := sprite.scale
sprite.syncSprite.UpdateTransform(x, y, rot, scale, flipH, offsetX, offsetY, isSync)

Choose a reason for hiding this comment

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

medium

The scale variable is being assigned the value of sprite.scale on line 166, but it's not clear if this is the correct scale to be used in all cases. It might be more appropriate to calculate the scale based on the costume's bitmap resolution, similar to how it's done in getCostumeBoundByAlpha. This ensures consistency in scaling across different parts of the code.

Consider calculating the scale based on costume properties to ensure consistency.

Comment on lines 47 to 52

// scale 现在是正数,表示实际缩放大小
scale := float64(scale64)
if scale < 0 {
scale = -scale
}

Choose a reason for hiding this comment

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

medium

The code adjusts the scale to be positive if it's negative. It would be helpful to add a comment explaining why the scale can be negative in the first place and why it needs to be adjusted here. This will help future developers understand the purpose of this adjustment.

Suggested change
// scale 现在是正数,表示实际缩放大小
scale := float64(scale64)
if scale < 0 {
scale = -scale
}
posOffset := Vec2{X: float64(offsetX), Y: float64(offsetY)}
// scale can be negative, indicating a flip. We want the absolute value for scaling.
scale := float64(scale64)
if scale < 0 {
scale = -scale
}

Comment on lines 48 to 52
// scale 现在是正数,表示实际缩放大小
scale := float64(scale64)
if scale < 0 {
scale = -scale
}
Copy link
Contributor

Choose a reason for hiding this comment

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

CRITICAL: Missing Input Validation

The scale parameter should be validated to prevent division-by-zero and special float values:

Suggested change
// scale 现在是正数,表示实际缩放大小
scale := float64(scale64)
if scale < 0 {
scale = -scale
}
// Scale should always be positive and valid
scale := float64(scale64)
if scale < 0 {
scale = -scale
}
if scale == 0 || math.IsNaN(scale) || math.IsInf(scale, 0) {
scale = 1.0 // Default to safe value
}

This prevents rendering crashes and physics engine instability when scale = 0, NaN, or Infinity.

}

func (pself *Sprite) UpdateTransform(x, y float64, rot float64, scale64 float64, offsetX, offsetY float64, isSync bool) {
func (pself *Sprite) UpdateTransform(x, y float64, rot float64, scale64 float64, flipH bool, offsetX, offsetY float64, isSync bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing Function Documentation

This function needs comprehensive documentation explaining the new behavior:

Suggested change
func (pself *Sprite) UpdateTransform(x, y float64, rot float64, scale64 float64, flipH bool, offsetX, offsetY float64, isSync bool) {
// UpdateTransform updates the sprite's position, rotation, scale, and flip state.
// Parameters:
// - x, y: Position coordinates
// - rot: Rotation in degrees
// - scale64: Scale factor (always positive; horizontal flipping is controlled separately via flipH)
// - flipH: Whether to flip the sprite horizontally
// - offsetX, offsetY: Pivot offset coordinates
// - isSync: Whether to apply changes synchronously
//
// Note: Scale is now always positive; horizontal flipping is controlled via flipH.
func (pself *Sprite) UpdateTransform(x, y float64, rot float64, scale64 float64, flipH bool, offsetX, offsetY float64, isSync bool) {

The signature change is breaking and requires clear documentation.

}

func calcRenderRotation(p *SpriteImpl) (float64, float64) {
func calcRenderRotation(p *SpriteImpl) (float64, bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing Function Documentation

Add documentation explaining return values and behavior:

Suggested change
func calcRenderRotation(p *SpriteImpl) (float64, bool) {
// calcRenderRotation calculates the rotation angle and horizontal flip state for rendering a sprite.
// Returns:
// - float64: The rotation angle in degrees
// - bool: Whether the sprite should be horizontally flipped
//
// Behavior by rotation style:
// - None: Returns 0 degrees with no flipping
// - LeftRight: Returns 0 degrees with flipH set based on direction
func calcRenderRotation(p *SpriteImpl) (float64, bool) {

@xgopilot
Copy link
Contributor

xgopilot bot commented Oct 27, 2025

Excellent refactoring! The separation of scale and flip is a significant improvement in code clarity. Key strengths:

✅ Better semantic clarity - explicit flipH vs implicit negative scale
✅ Improved maintainability and type safety
✅ Clean separation of concerns

Critical issue: Missing input validation for zero/NaN/Infinity scale values could cause rendering crashes. Please address inline comments.

@JiepengTan JiepengTan force-pushed the pr_update_sprite_scale_impl branch 3 times, most recently from 997d4d6 to b86c495 Compare October 30, 2025 09:31
@JiepengTan JiepengTan marked this pull request as ready for review October 31, 2025 00:55
@JiepengTan JiepengTan requested a review from joeykchen October 31, 2025 00:55
@xgopilot
Copy link
Contributor

xgopilot bot commented Oct 31, 2025

Code Review Summary

Overall, this PR successfully refactors sprite scale/flip handling with cleaner separation of concerns. The new approach (separate flipH boolean vs. negative scale encoding) improves code clarity and enables uniform scaling optimizations.

Critical Issue: Missing API methods in pure engine wrapper will cause compilation failures.

Performance: No significant concerns. The additional FFI call overhead is negligible given low call frequency.

Security: No vulnerabilities identified. Consider adding validation to prevent zero scale values (quality issue, not security).

See inline comments for specific issues.

scale := float64(scale64)
if scale < 0 {
scale = -scale
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Defensive abs() check - Consider adding validation at source

This defensive check ensures scale is positive, but suggests incomplete migration or potential bugs upstream. If getCostumeRenderScale() always returns positive values, this check is unnecessary. If negative scale can occur via ChangeSize(-value), consider validating at the source instead:

func (p *SpriteImpl) SetSize(size float64) {
    if size <= 0 {
        size = 0.01 // or log warning
    }
    // ... rest
}

Additionally, zero scale could cause division-by-zero issues in pivot calculations. Consider adding a minimum threshold.

}

func calcRenderRotation(p *SpriteImpl) (float64, float64) {
func calcRenderRotation(p *SpriteImpl) (float64, bool) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Good improvement: Clear separation of rotation and flip state. The new signature (rotation float64, flipH bool) is more explicit and type-safe than the previous (rotation, hScale float64) approach.

func (pself *spriteMgrImpl) SetRenderScale(obj gdx.Object, scale Vec2) {}
func (pself *spriteMgrImpl) GetRenderScale(obj gdx.Object) Vec2 {
var _ret1 Vec2
func (pself *spriteMgrImpl) SetFlipH(obj gdx.Object, flip bool) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

CRITICAL: Missing SetFlipH/IsFlipH methods in pure wrapper

The ISpriteMgr interface (pkg/gdspx/pkg/engine/interface.gen.go:206-207) requires SetFlipH and IsFlipH methods, but this pure wrapper implementation is missing them. This will cause compilation failures when building with -tags pure_engine.

Additionally, the old SetRenderScale/GetRenderScale methods still exist in this file and should be removed.

Action required: Regenerate this file or manually add:

func (pself *spriteMgrImpl) SetFlipH(obj gdx.Object, flip bool) {}
func (pself *spriteMgrImpl) IsFlipH(obj gdx.Object) bool {
    var _ret1 bool
    return _ret1
}

And remove the SetRenderScale/GetRenderScale methods.

pself.SetPosition(pos)
pself.SetRotation(rad)
pself.SetScale(NewVec2(scale, 1))
pself.SetScale(NewVec2(scale, scale))
Copy link
Contributor

Choose a reason for hiding this comment

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

Performance note: Uniform scaling (scale, scale) is better than the previous non-uniform approach. GPU rasterizers and physics engines can optimize uniform scaling more effectively.

@JiepengTan JiepengTan force-pushed the pr_update_sprite_scale_impl branch from b86c495 to 3ec2f74 Compare November 2, 2025 13:46
@JiepengTan JiepengTan marked this pull request as draft November 2, 2025 14:10
@JiepengTan JiepengTan marked this pull request as ready for review January 15, 2026 15:50
@JiepengTan JiepengTan marked this pull request as draft January 15, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant