Fix instrument change clef not reacting to concert pitch toggle#32499
Fix instrument change clef not reacting to concert pitch toggle#32499CubikingChill wants to merge 1 commit intomusescore:masterfrom
Conversation
a3a6a58 to
fc16de4
Compare
|
Please do not merge at the moment. I am still working on the functionality of the code. |
dbac1f6 to
09ef22a
Compare
e2d3dcb to
5852a5f
Compare
6a58549 to
bcb2f3b
Compare
|
|
||
| for (size_t i = 0; i < part->nstaves(); i++) { | ||
| Staff* staff = part->staff(i); | ||
| // 直接獲取當前樂器定義的 ClefTypeList (包含 cp 和 tp) |
There was a problem hiding this comment.
Code comments in English please.
If these are just notes to help you understand things and remember what they do, that's fine. Just make sure you remove them all (or rewrite them in English) before you mark the PR as "ready for review".
But if you're using AI, we shouldn't be able to tell. The code should look how it would look if you had written it all yourself; the AI should just be used to arrive at the end result sooner.
There was a problem hiding this comment.
Your guess is correct. I am using some level of AI to skip reading all existing code. But I can assure you that once this PR goes out of draft. It will be clean.
📝 WalkthroughWalkthroughThis PR modifies instrument change clef handling to fix concert pitch synchronization issues. The changes introduce a parameter-multiplexing approach: Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/engraving/editing/edit.cpp (2)
6214-6253:⚠️ Potential issue | 🔴 CriticalFix the IC staff-group guard before it hits
ClefType::INVALID.Line 6251 still evaluates
ClefInfo::staffGroup(ct)before the!isICcheck. In the packed instrument-change path,ctis intentionallyClefType::INVALID, so this can trip invalid-enum lookup/asserts in the exact flow this PR adds. Also, once reordered, the IC path still needs a staff-group compatibility check based oncp/tprather than skipping it entirely.Suggested fix
- if (ClefInfo::staffGroup(ct) != staffGroup && !isIC) { - continue; - } + if (isIC) { + if (cp == ClefType::INVALID || tp == ClefType::INVALID + || ClefInfo::staffGroup(cp) != staffGroup + || ClefInfo::staffGroup(tp) != staffGroup) { + continue; + } + } else if (ClefInfo::staffGroup(ct) != staffGroup) { + continue; + }
6176-6326: 🧹 Nitpick | 🔵 TrivialPlease lock this packed IC path down with a regression.
This function now owns the special concert/transposing-clef initialization that fixes
#32614. A test that toggles Concert Pitch after multiple instrument changes, then deletes an earlier IC, would make future regressions here much easier to catch.If you want, I can draft the regression scenario for the existing engraving test framework.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: f24ce917-5a94-4e5f-aad2-22f844cfb0c9
📒 Files selected for processing (3)
src/engraving/dom/instrchange.cppsrc/engraving/dom/score.hsrc/engraving/editing/edit.cpp
| if (ClefInfo::symId(oldClefTypeList.concertClef) != ClefInfo::symId(newClefTypeList.concertClef) | ||
| || ClefInfo::symId(oldClefTypeList.transposingClef) != ClefInfo::symId(newClefTypeList.transposingClef)) { |
There was a problem hiding this comment.
Compare full clef types instead of glyph IDs.
Line 105 and Line 106 compare only ClefInfo::symId(...). Different clef types can share the same symbol, so required IC clef updates may be skipped.
Proposed fix
- if (ClefInfo::symId(oldClefTypeList.concertClef) != ClefInfo::symId(newClefTypeList.concertClef)
- || ClefInfo::symId(oldClefTypeList.transposingClef) != ClefInfo::symId(newClefTypeList.transposingClef)) {
+ if (oldClefTypeList.concertClef != newClefTypeList.concertClef
+ || oldClefTypeList.transposingClef != newClefTypeList.transposingClef) {📝 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.
| if (ClefInfo::symId(oldClefTypeList.concertClef) != ClefInfo::symId(newClefTypeList.concertClef) | |
| || ClefInfo::symId(oldClefTypeList.transposingClef) != ClefInfo::symId(newClefTypeList.transposingClef)) { | |
| if (oldClefTypeList.concertClef != newClefTypeList.concertClef | |
| || oldClefTypeList.transposingClef != newClefTypeList.transposingClef) { |
| int cp = static_cast<int>(newClefTypeList.concertClef); | ||
| int tp = static_cast<int>(newClefTypeList.transposingClef); | ||
| int packedData = 1000 + (cp & 0xFF) + ((tp & 0xFF) << 8); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Extract IC clef packing into shared constants/helper.
Line 109 uses inline 1000 and 0xFF. Please move this packing contract to a shared helper (or shared constants) used by both encode/decode sites to prevent divergence.
Refactor direction
- int cp = static_cast<int>(newClefTypeList.concertClef);
- int tp = static_cast<int>(newClefTypeList.transposingClef);
- int packedData = 1000 + (cp & 0xFF) + ((tp & 0xFF) << 8);
+ constexpr int kIcClefPackOffset = 1000;
+ constexpr int kIcClefMask = 0xFF;
+ const int cp = static_cast<int>(newClefTypeList.concertClef);
+ const int tp = static_cast<int>(newClefTypeList.transposingClef);
+ const int packedData = kIcClefPackOffset + (cp & kIcClefMask) + ((tp & kIcClefMask) << 8);📝 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.
| int cp = static_cast<int>(newClefTypeList.concertClef); | |
| int tp = static_cast<int>(newClefTypeList.transposingClef); | |
| int packedData = 1000 + (cp & 0xFF) + ((tp & 0xFF) << 8); | |
| constexpr int kIcClefPackOffset = 1000; | |
| constexpr int kIcClefMask = 0xFF; | |
| const int cp = static_cast<int>(newClefTypeList.concertClef); | |
| const int tp = static_cast<int>(newClefTypeList.transposingClef); | |
| const int packedData = kIcClefPackOffset + (cp & kIcClefMask) + ((tp & kIcClefMask) << 8); |
| void undoChangeUserMirror(Note*, DirectionH); | ||
| void undoChangeKeySig(Staff* ostaff, const Fraction& tick, KeySigEvent); | ||
| void undoChangeClef(Staff* ostaff, EngravingItem*, ClefType st, bool forInstrumentChange = false, Clef* clefToRelink = nullptr); | ||
| void undoChangeClef(Staff* ostaff, EngravingItem*, ClefType st, int forInstrumentChange = false, Clef* clefToRelink = nullptr); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Type change from bool to int with false default is semantically confusing.
While false implicitly converts to 0 in C++, using a boolean literal as the default for an int parameter obscures the intent. Additionally, the parameter name forInstrumentChange no longer accurately describes its content when it carries packed clef data.
Consider:
- Change the default to
0for clarity. - Rename the parameter (e.g.,
instrumentChangeDataorclefPackedData) to reflect its dual purpose. - Add a brief doc comment explaining the packing scheme (
1000 + concertClef + (transposingClef << 8)), or define named constants for the magic offset.
Proposed minimal fix for default value
- void undoChangeClef(Staff* ostaff, EngravingItem*, ClefType st, int forInstrumentChange = false, Clef* clefToRelink = nullptr);
+ void undoChangeClef(Staff* ostaff, EngravingItem*, ClefType st, int forInstrumentChange = 0, Clef* clefToRelink = nullptr);For a more robust API, consider introducing a small struct or enum to encapsulate the instrument-change clef data instead of relying on magic-number packing in a public interface.
📝 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.
| void undoChangeClef(Staff* ostaff, EngravingItem*, ClefType st, int forInstrumentChange = false, Clef* clefToRelink = nullptr); | |
| void undoChangeClef(Staff* ostaff, EngravingItem*, ClefType st, int forInstrumentChange = 0, Clef* clefToRelink = nullptr); |
|
Closing because the code was not compiled before contributing, and because clefs, key sigs and time sigs management are a very fragile part of our code base that has been in long need of a refactor and where it's not safe to accept contributions. See also #32755 (comment) |
Resolves: #32614
Summary by CodeRabbit