Skip to content

Conversation

@Kite2810
Copy link
Contributor

@Kite2810 Kite2810 commented Dec 26, 2025

Fixes Texture count bug.
adds optional skeleton replace option.
Adds replace Texture option.
If Skeleton is imported, reset Bones to 0, otherwise crash if trying to display collisions on invalid bone indicates.

Summary by CodeRabbit

Release Notes

  • New Features
    • Added "Keep skeleton" checkbox option in the model importer dialog to control whether the original skeleton is retained during import.
    • Added "Replace Texture" context menu option to replace individual textures within model files with new PNG images.
    • Texture replacement automatically rebuilds and normalizes texture data to ensure compatibility.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 26, 2025

📝 Walkthrough

Walkthrough

This pull request extends the KH2 MDLX Editor with three main features: optional collision bone resetting during model import, user control over skeleton retention via UI checkbox, and individual texture replacement capability. Changes span import logic, view models, UI bindings, and stream handling during MDLX file building.

Changes

Cohort / File(s) Summary
Model Import & Collision Handling
OpenKh.Tools.Kh2MdlxEditor/Utils/MdlxEditorImporter.cs
Added System.Linq import. Enhanced replaceMeshModelSkeletal with optional collisionFile parameter to update TextureCount from distinct textures and reset collision bones when provided. Introduced new ResetCollisionBones(ModelCollision) helper method to zero collision bone indices.
Import UI & ViewModel
OpenKh.Tools.Kh2MdlxEditor/ViewModels/Importer_VM.cs, OpenKh.Tools.Kh2MdlxEditor/Views/Importer_Window.xaml, OpenKh.Tools.Kh2MdlxEditor/Views/Importer_Window.xaml.cs
Added public KeepSkeleton boolean property to Importer_VM (default true). Updated UI to include two-checkbox panel for "Keep shadow" and "Keep skeleton" with TwoWay bindings. Button_Import now sets both KEEP_ORIGINAL_SHADOW and KEEP_ORIGINAL_SKELETON static flags before import.
Texture Replacement Feature
OpenKh.Tools.Kh2MdlxEditor/ViewModels/TextureFile_VM.cs, OpenKh.Tools.Kh2MdlxEditor/Views/TextureFile_Control.xaml, OpenKh.Tools.Kh2MdlxEditor/Views/TextureFile_Control.xaml.cs
Added replaceTextureAt(int, string) method in TextureFile_VM to validate index, convert PNG to Imgd, rebuild texture list, and update model. Extended TextureFile_Control constructor to accept optional onTextureReplaced callback. Added "Replace Texture" context menu item and public Texture_Replace handler for PNG file dialog and UI refresh.
Model Building & Integration
OpenKh.Tools.Kh2MdlxEditor/ViewModels/Main2_VM.cs, OpenKh.Tools.Kh2MdlxEditor/Views/Main2_Window.xaml.cs
In buildBarFile, reset stream position to 0 after writing model, texture, and collision data. In replaceModel, pass CollisionFile parameter to replaceMeshModelSkeletal. Added LoadTextureControl helper in Main2_Window.xaml.cs to guard TextureFile_Control instantiation and wire refresh callback.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • shananas
  • kenjiuno
  • Delta-473

Poem

🐰 A skeleton's kept, a texture's swapped clean,
Collision bones reset—the finest I've seen!
With checkboxes dancing and streams flowing right,
The MDLX editor reaches new height! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is partially related to the changeset. It mentions fixing a texture count bug and adding skeleton/texture options, which are confirmed in the changes, but the title is cut off (ends with 'and re…') making it incomplete and vague about the third feature. Complete the title to fully describe all main changes (e.g., 'Fixes texture count bug, adds optional skeleton replace option, and adds replace texture feature') or use a more concise version that covers the primary intent.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 765df71 and dfe2d1b.

📒 Files selected for processing (9)
  • OpenKh.Tools.Kh2MdlxEditor/Utils/MdlxEditorImporter.cs
  • OpenKh.Tools.Kh2MdlxEditor/ViewModels/Importer_VM.cs
  • OpenKh.Tools.Kh2MdlxEditor/ViewModels/Main2_VM.cs
  • OpenKh.Tools.Kh2MdlxEditor/ViewModels/TextureFile_VM.cs
  • OpenKh.Tools.Kh2MdlxEditor/Views/Importer_Window.xaml
  • OpenKh.Tools.Kh2MdlxEditor/Views/Importer_Window.xaml.cs
  • OpenKh.Tools.Kh2MdlxEditor/Views/Main2_Window.xaml.cs
  • OpenKh.Tools.Kh2MdlxEditor/Views/TextureFile_Control.xaml
  • OpenKh.Tools.Kh2MdlxEditor/Views/TextureFile_Control.xaml.cs
🧰 Additional context used
🧬 Code graph analysis (7)
OpenKh.Tools.Kh2MdlxEditor/ViewModels/Importer_VM.cs (1)
OpenKh.Tools.Kh2MdlxEditor/Utils/MdlxEditorImporter.cs (1)
  • MdlxEditorImporter (13-307)
OpenKh.Tools.Kh2MdlxEditor/Utils/MdlxEditorImporter.cs (4)
OpenKh.AssimpUtils/Kh2MdlxAssimp.cs (7)
  • Dictionary (137-149)
  • Dictionary (514-534)
  • Assimp (16-135)
  • Assimp (151-272)
  • Assimp (496-510)
  • VifMesh (274-368)
  • Kh2MdlxAssimp (11-535)
OpenKh.Kh2/Models/ModelCommon.cs (4)
  • List (237-251)
  • Matrix4x4 (253-274)
  • ModelCommon (10-332)
  • Bone (125-169)
OpenKh.Kh2/Models/VIF/VifUtils.cs (2)
  • VifUtils (5-120)
  • calcBaseAddress (102-119)
OpenKh.Kh2/Models/VIF/VifMesh.cs (2)
  • VifMesh (11-20)
  • VifMesh (16-19)
OpenKh.Tools.Kh2MdlxEditor/ViewModels/Main2_VM.cs (1)
OpenKh.Tools.Kh2MdlxEditor/Utils/MdlxEditorImporter.cs (1)
  • MdlxEditorImporter (13-307)
OpenKh.Tools.Kh2MdlxEditor/ViewModels/TextureFile_VM.cs (2)
OpenKh.Kh2/ModelTexture.cs (13)
  • ModelTexture (14-977)
  • ModelTexture (416-479)
  • ModelTexture (557-561)
  • ModelTexture (563-694)
  • ModelTexture (932-933)
  • Texture (29-90)
  • Texture (37-50)
  • PixelFormat (873-884)
  • GetData (71-89)
  • GetClut (58-69)
  • Write (320-334)
  • Write (710-823)
  • Build (481-488)
OpenKh.Tools.Kh2MdlxEditor/Utils/ImageUtils.cs (5)
  • ModelTexture (41-52)
  • ModelTexture (54-57)
  • ImageUtils (15-137)
  • Imgd (17-39)
  • Imgd (65-108)
OpenKh.Tools.Kh2MdlxEditor/Views/Main2_Window.xaml.cs (1)
OpenKh.Tools.Kh2MdlxEditor/Views/TextureFile_Control.xaml.cs (4)
  • TextureFile_Control (19-190)
  • TextureFile_Control (25-28)
  • TextureFile_Control (30-35)
  • TextureFile_Control (38-51)
OpenKh.Tools.Kh2MdlxEditor/Views/Importer_Window.xaml.cs (1)
OpenKh.Tools.Kh2MdlxEditor/Utils/MdlxEditorImporter.cs (1)
  • MdlxEditorImporter (13-307)
OpenKh.Tools.Kh2MdlxEditor/Views/TextureFile_Control.xaml.cs (3)
OpenKh.Tools.Kh2MdlxEditor/ViewModels/Main2_VM.cs (3)
  • Main2_VM (10-120)
  • Main2_VM (25-25)
  • Main2_VM (26-29)
OpenKh.Kh2/ModelTexture.cs (5)
  • ModelTexture (14-977)
  • ModelTexture (416-479)
  • ModelTexture (557-561)
  • ModelTexture (563-694)
  • ModelTexture (932-933)
OpenKh.Tools.Kh2MdlxEditor/ViewModels/TextureFile_VM.cs (4)
  • TextureFile_VM (11-109)
  • TextureFile_VM (18-18)
  • TextureFile_VM (19-24)
  • replaceTextureAt (39-108)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Analyze (csharp)
  • GitHub Check: build
🔇 Additional comments (22)
OpenKh.Tools.Kh2MdlxEditor/Views/TextureFile_Control.xaml (1)

43-43: LGTM! Context menu item properly wired.

The new "Replace Texture" menu item follows the established pattern and correctly binds to the Texture_Replace handler implemented in the code-behind.

OpenKh.Tools.Kh2MdlxEditor/Views/Importer_Window.xaml.cs (2)

1-1: LGTM! Required namespace import.

The OpenKh.Tools.Kh2MdlxEditor.Utils namespace is needed to access MdlxEditorImporter static flags.


76-78: LGTM! Follows established pattern for import configuration.

The static flag pattern is consistent with the existing TRIANGLE_INVERSE flag in MdlxEditorImporter. The flags are set immediately before use, minimizing risk.

OpenKh.Tools.Kh2MdlxEditor/Views/Importer_Window.xaml (1)

20-23: LGTM! UI correctly exposes both import options.

The horizontal StackPanel layout with proper spacing and TwoWay binding aligns with the new KeepSkeleton feature. Both options are now accessible to users.

OpenKh.Tools.Kh2MdlxEditor/ViewModels/Importer_VM.cs (3)

31-31: LGTM! New property follows established pattern.

The KeepSkeleton property mirrors the existing KeepShadow property structure and provides user control over skeleton retention during import.


42-42: LGTM! Safe default value.

Defaulting to true preserves the original skeleton by default, which is the safer option and prevents unexpected behavior changes for existing workflows.


120-120: LGTM! Properly propagates flag to importer.

The KeepSkeleton value is correctly assigned to the static KEEP_ORIGINAL_SKELETON flag before model import, ensuring the user's choice is respected.

OpenKh.Tools.Kh2MdlxEditor/Views/Main2_Window.xaml.cs (1)

111-121: LGTM! Clean refactoring with proper null guards.

The extracted LoadTextureControl helper method:

  • Adds appropriate null checks before creating the control
  • Passes mainVM to enable texture replacement integration
  • Uses a self-referential callback pattern to enable UI refresh after texture replacement

This design cleanly supports the new texture replacement feature while maintaining good separation of concerns.

OpenKh.Tools.Kh2MdlxEditor/ViewModels/Main2_VM.cs (2)

90-90: LGTM! Critical fix for stream positioning.

Resetting the stream position to 0 after writing is essential to ensure subsequent reads (e.g., by Bar.Write in line 170 of Main2_Window.xaml.cs) can successfully read the data from the beginning of the stream. Without these resets, the streams would be positioned at EOF, causing empty or corrupted data to be written to the output file.

Also applies to: 95-95, 99-99


117-118: LGTM! Enables collision bone reset during skeleton import.

Passing CollisionFile to replaceMeshModelSkeletal allows the importer to reset collision bone references when a new skeleton is imported, preventing crashes from invalid bone indices as described in the PR objectives.

OpenKh.Tools.Kh2MdlxEditor/ViewModels/TextureFile_VM.cs (3)

3-7: LGTM! Required using directives.

The additional using directives support the new texture replacement functionality.


13-13: LGTM! Callback pattern enables external notification.

The callback mechanism allows the parent Main2_VM to be notified when a texture is replaced, ensuring the view model state stays synchronized.

Also applies to: 19-19, 23-23


38-108: LGTM! Comprehensive texture replacement implementation.

The replaceTextureAt method:

  • Validates the index range (lines 41-44)
  • Rebuilds the entire texture list to ensure consistency (lines 50-71)
  • Correctly preserves footer data (lines 74-82)
  • Uses a write/read cycle to normalize the ModelTexture format (lines 94-97)
  • Notifies the parent via callback (line 100)
  • Updates the observable collection for UI refresh (lines 103-107)

The full rebuild approach, while not minimal, ensures proper formatting and consistency across all textures. The swizzled: false parameter on line 67 is correct since textures from ModelTexture.Images are already in unswizzled format.

OpenKh.Tools.Kh2MdlxEditor/Views/TextureFile_Control.xaml.cs (4)

22-23: LGTM! Fields support the new texture replacement feature.

The private fields enable integration with Main2_VM and support external refresh callbacks after texture replacement.


37-51: LGTM! Constructor cleanly integrates with parent VM.

The new constructor:

  • Accepts Main2_VM and an optional refresh callback
  • Wires a callback to update Main2_VM.TextureFile when a texture is replaced (lines 43-48)
  • Enables bidirectional synchronization between the control and the parent view model

55-55: LGTM! Forces WPF data binding refresh.

Setting DataContext = null before reassigning forces WPF to recognize the change and refresh all bindings, ensuring the UI reflects the updated texture data.


109-141: LGTM! Well-structured texture replacement handler.

The Texture_Replace method:

  • Guards against no selection (line 112)
  • Filters to PNG files only (line 119)
  • Properly handles exceptions with detailed error messages (lines 134-138)
  • Invokes the refresh callback to update the UI (line 129)
  • Provides user feedback with success/error MessageBox dialogs

The implementation is robust and user-friendly.

OpenKh.Tools.Kh2MdlxEditor/Utils/MdlxEditorImporter.cs (5)

1-9: LGTM! Necessary import for LINQ functionality.

The addition of System.Linq is required for the .Distinct() method used on line 79 to fix the texture count bug.


69-69: LGTM! Backward-compatible signature change.

The optional collisionFile parameter enables the collision bone reset feature when importing a new skeleton, while maintaining backward compatibility for existing callers.


79-79: LGTM! Correct fix for the texture count bug.

The calculation properly counts distinct texture indices from the materialToTexture dictionary, which correctly handles cases where multiple materials share the same texture. The null-coalescing operator provides a safe fallback.


89-99: LGTM! Proper collision bone reset logic.

The logic correctly resets collision bones when importing a new skeleton, preventing crashes from invalid bone index references. The conditional ensures this only executes when a new skeleton is imported and collision data is present.


139-149: LGTM! Well-implemented helper method.

The method properly handles null checks and clearly implements the collision bone reset functionality. The comment accurately describes its purpose of preventing crashes from invalid bone indices.

List<DmaVifPacket> dmaVifPackets = VifProcessor.vifMeshToDmaVifPackets(vifMesh);

ModelSkeletal.SkeletalGroup group = VifProcessor.getSkeletalGroup(dmaVifPackets, (uint)mesh.MaterialIndex, baseAddress);
group.Header.TextureIndex = (uint)materialToTexture[mesh.MaterialIndex];
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider adding null check for consistency.

Line 79 uses a null-conditional operator for materialToTexture, but this line directly accesses the dictionary without null checking. If materialToTexture is null (e.g., if createModelTexture wasn't called first), this will throw a NullReferenceException.

🔎 Suggested fix for consistency
-                group.Header.TextureIndex = (uint)materialToTexture[mesh.MaterialIndex];
+                group.Header.TextureIndex = (uint)(materialToTexture?[mesh.MaterialIndex] ?? mesh.MaterialIndex);

Or add an explicit null check at the start of the method if materialToTexture being populated is a precondition.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In OpenKh.Tools.Kh2MdlxEditor/Utils/MdlxEditorImporter.cs around line 115, the
code accesses materialToTexture directly which can be null (causing
NullReferenceException); either add an explicit null check at the start of the
method and throw a clear ArgumentNullException if materialToTexture is required,
or guard this access by using the null-conditional operator and a safe fallback
(e.g., set TextureIndex to a default value) so the code does not dereference a
null dictionary.

Copy link
Collaborator

@Delta-473 Delta-473 left a comment

Choose a reason for hiding this comment

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

LGTM

@Delta-473 Delta-473 merged commit 3fc837c into OpenKH:master Dec 31, 2025
4 checks passed
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.

2 participants