fix(camera): mark replacement shader fields as assignment clone#2988
fix(camera): mark replacement shader fields as assignment clone#2988cptbtptpbcptdtptp wants to merge 2 commits into
Conversation
Add @assignmentClone to _replacementShader and _replacementSubShaderTag so cloned cameras share the same shader/tag reference instead of deep cloning them (which would create unnecessary duplicates). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
WalkthroughCamera's internal replacement-shader state ( ChangesReplacement Shader Clone Preservation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/src/core/Camera.test.ts`:
- Around line 432-453: Replace the string assignment and string comparison with
a proper ShaderTagKey: create a ShaderTagKey via
ShaderTagKey.getByName("TestTag"), assign that to
camera._replacementSubShaderTag (instead of the raw string), and update the
assertion to compare the cloned camera's _replacementSubShaderTag to the same
ShaderTagKey (or compare their names via .getName()) so types and semantics
match; references: camera._replacementSubShaderTag, ShaderTagKey.getByName,
cloneCamera.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 1688ce5f-7744-4d70-9cf9-41db4bc2fbf8
📒 Files selected for processing (2)
packages/core/src/Camera.tstests/src/core/Camera.test.ts
| it("clone preserves replacement shader by reference (assignmentClone)", () => { | ||
| const shader = Shader.create("TestCloneReplaceShader", [ | ||
| new SubShader("Default", [new ShaderPass("Default", [], [], ShaderLanguage.GLSLES100)]) | ||
| ]); | ||
|
|
||
| // @ts-ignore | ||
| camera._replacementShader = shader; | ||
| // @ts-ignore | ||
| camera._replacementSubShaderTag = "TestTag"; | ||
|
|
||
| const cloneCamera = camera.entity.clone().getComponent(Camera); | ||
|
|
||
| // @ts-ignore - assignmentClone copies reference, not deep clone | ||
| expect(cloneCamera._replacementShader).to.eq(shader); | ||
| // @ts-ignore | ||
| expect(cloneCamera._replacementSubShaderTag).to.eq("TestTag"); | ||
|
|
||
| // @ts-ignore - cleanup | ||
| camera._replacementShader = null; | ||
| // @ts-ignore | ||
| camera._replacementSubShaderTag = null; | ||
| }); |
There was a problem hiding this comment.
Fix type violations in replacement shader tag assignment and assertion.
The test has two critical correctness issues:
-
Line 440: Assigns a string
"TestTag"directly to_replacementSubShaderTag, but this field is typed asShaderTagKey, notstring. While@ts-ignoresuppresses the type error, this violates the actual type contract. -
Line 447: Compares
_replacementSubShaderTagto the string"TestTag". If line 440 is corrected to use a properShaderTagKeyobject, this assertion will fail since you'd be comparing an object to a string.
The proper usage pattern is shown in Camera.ts line 719: ShaderTagKey.getByName(replacementTag).
🔧 Proposed fix using ShaderTagKey.getByName()
+ const testTag = ShaderTagKey.getByName("TestTag");
+
// `@ts-ignore`
camera._replacementShader = shader;
// `@ts-ignore`
- camera._replacementSubShaderTag = "TestTag";
+ camera._replacementSubShaderTag = testTag;
const cloneCamera = camera.entity.clone().getComponent(Camera);
// `@ts-ignore` - assignmentClone copies reference, not deep clone
expect(cloneCamera._replacementShader).to.eq(shader);
// `@ts-ignore`
- expect(cloneCamera._replacementSubShaderTag).to.eq("TestTag");
+ expect(cloneCamera._replacementSubShaderTag).to.eq(testTag);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| it("clone preserves replacement shader by reference (assignmentClone)", () => { | |
| const shader = Shader.create("TestCloneReplaceShader", [ | |
| new SubShader("Default", [new ShaderPass("Default", [], [], ShaderLanguage.GLSLES100)]) | |
| ]); | |
| // @ts-ignore | |
| camera._replacementShader = shader; | |
| // @ts-ignore | |
| camera._replacementSubShaderTag = "TestTag"; | |
| const cloneCamera = camera.entity.clone().getComponent(Camera); | |
| // @ts-ignore - assignmentClone copies reference, not deep clone | |
| expect(cloneCamera._replacementShader).to.eq(shader); | |
| // @ts-ignore | |
| expect(cloneCamera._replacementSubShaderTag).to.eq("TestTag"); | |
| // @ts-ignore - cleanup | |
| camera._replacementShader = null; | |
| // @ts-ignore | |
| camera._replacementSubShaderTag = null; | |
| }); | |
| it("clone preserves replacement shader by reference (assignmentClone)", () => { | |
| const shader = Shader.create("TestCloneReplaceShader", [ | |
| new SubShader("Default", [new ShaderPass("Default", [], [], ShaderLanguage.GLSLES100)]) | |
| ]); | |
| const testTag = ShaderTagKey.getByName("TestTag"); | |
| // `@ts-ignore` | |
| camera._replacementShader = shader; | |
| // `@ts-ignore` | |
| camera._replacementSubShaderTag = testTag; | |
| const cloneCamera = camera.entity.clone().getComponent(Camera); | |
| // `@ts-ignore` - assignmentClone copies reference, not deep clone | |
| expect(cloneCamera._replacementShader).to.eq(shader); | |
| // `@ts-ignore` | |
| expect(cloneCamera._replacementSubShaderTag).to.eq(testTag); | |
| // `@ts-ignore` - cleanup | |
| camera._replacementShader = null; | |
| // `@ts-ignore` | |
| camera._replacementSubShaderTag = null; | |
| }); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/src/core/Camera.test.ts` around lines 432 - 453, Replace the string
assignment and string comparison with a proper ShaderTagKey: create a
ShaderTagKey via ShaderTagKey.getByName("TestTag"), assign that to
camera._replacementSubShaderTag (instead of the raw string), and update the
assertion to compare the cloned camera's _replacementSubShaderTag to the same
ShaderTagKey (or compare their names via .getName()) so types and semantics
match; references: camera._replacementSubShaderTag, ShaderTagKey.getByName,
cloneCamera.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev/2.0 #2988 +/- ##
===========================================
+ Coverage 78.25% 78.30% +0.04%
===========================================
Files 900 900
Lines 99234 99236 +2
Branches 10172 10192 +20
===========================================
+ Hits 77657 77705 +48
+ Misses 21406 21360 -46
Partials 171 171
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
GuoLei1990
left a comment
There was a problem hiding this comment.
总结
_replacementShader(Shader 资源)和 _replacementSubShaderTag(ShaderTagKey 值)都是应按引用拷贝的共享对象,缺少装饰器时 CloneManager 会对其执行深克隆(错误)。补上 @assignmentClone 后行为正确。测试通过 eq() 断言引用相同,验证逻辑准确。
LGTM,可合入。
Summary
@assignmentCloneto_replacementShaderand_replacementSubShaderTagso cloned cameras share the same shader/tag reference instead of deep cloning them.Background
Extracted from
ca5252a9aon fix/shaderlab. Without this, cloning a camera that has a replacement shader set would deep-clone the Shader object, creating an unnecessary duplicate.Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit