BUTR/Bannerlord.UIExtenderEx

View on GitHub
docs/articles/runtime/ViewModelPatching.svg

Summary

Maintainability
Test Coverage
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1138" height="1004" contentStyleType="text/css" preserveAspectRatio="none" style="width:1138px;height:1004px;background:#fff" version="1.1" viewBox="0 0 1138 1004" zoomAndPan="magnify"><g><rect width="650.5" height="109.873" x="481.5" fill="none" style="stroke:#000;stroke-width:1.5" y="358.367"/><rect width="318" height="64.582" x="814" fill="none" style="stroke:#000;stroke-width:1.5" y="614.822"/><rect width="318" height="64.582" x="814" fill="none" style="stroke:#000;stroke-width:1.5" y="811.986"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="27" x2="27" y1="83.621" y2="229.494"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="27" x2="27" y1="229.494" y2="257.494"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="27" x2="27" y1="257.494" y2="517.24"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="27" x2="27" y1="517.24" y2="545.24"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="27" x2="27" y1="545.24" y2="714.404"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="27" x2="27" y1="714.404" y2="742.404"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="27" x2="27" y1="742.404" y2="921.568"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="288.5" x2="288.5" y1="83.621" y2="229.494"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="288.5" x2="288.5" y1="229.494" y2="257.494"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="288.5" x2="288.5" y1="257.494" y2="517.24"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="288.5" x2="288.5" y1="517.24" y2="545.24"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="288.5" x2="288.5" y1="545.24" y2="714.404"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="288.5" x2="288.5" y1="714.404" y2="742.404"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="288.5" x2="288.5" y1="742.404" y2="921.568"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="382.5" x2="382.5" y1="83.621" y2="229.494"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="382.5" x2="382.5" y1="229.494" y2="257.494"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="382.5" x2="382.5" y1="257.494" y2="517.24"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="382.5" x2="382.5" y1="517.24" y2="545.24"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="382.5" x2="382.5" y1="545.24" y2="714.404"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="382.5" x2="382.5" y1="714.404" y2="742.404"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="382.5" x2="382.5" y1="742.404" y2="921.568"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="568.5" x2="568.5" y1="83.621" y2="229.494"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="568.5" x2="568.5" y1="229.494" y2="257.494"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="568.5" x2="568.5" y1="257.494" y2="517.24"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="568.5" x2="568.5" y1="517.24" y2="545.24"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="568.5" x2="568.5" y1="545.24" y2="714.404"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="568.5" x2="568.5" y1="714.404" y2="742.404"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="568.5" x2="568.5" y1="742.404" y2="921.568"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="695.5" x2="695.5" y1="83.621" y2="229.494"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="695.5" x2="695.5" y1="229.494" y2="257.494"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="695.5" x2="695.5" y1="257.494" y2="517.24"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="695.5" x2="695.5" y1="517.24" y2="545.24"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="695.5" x2="695.5" y1="545.24" y2="714.404"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="695.5" x2="695.5" y1="714.404" y2="742.404"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="695.5" x2="695.5" y1="742.404" y2="921.568"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="912" x2="912" y1="83.621" y2="229.494"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="912" x2="912" y1="229.494" y2="257.494"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="912" x2="912" y1="257.494" y2="517.24"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="912" x2="912" y1="517.24" y2="545.24"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="912" x2="912" y1="545.24" y2="714.404"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="912" x2="912" y1="714.404" y2="742.404"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="912" x2="912" y1="742.404" y2="921.568"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="1066" x2="1066" y1="83.621" y2="229.494"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="1066" x2="1066" y1="229.494" y2="257.494"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="1066" x2="1066" y1="257.494" y2="517.24"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="1066" x2="1066" y1="517.24" y2="545.24"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="1066" x2="1066" y1="545.24" y2="714.404"/><line style="stroke:#a80036;stroke-width:1;stroke-dasharray:1,4" x1="1066" x2="1066" y1="714.404" y2="742.404"/><line style="stroke:#181818;stroke-width:.5;stroke-dasharray:5,5" x1="1066" x2="1066" y1="742.404" y2="921.568"/><text x="5" y="80.107" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="38">Game</text><ellipse cx="27" cy="13.5" fill="#E2E2F0" rx="8" ry="8" style="stroke:#181818;stroke-width:.5"/><path fill="none" d="M27,21.5 L27,48.5 M14,29.5 L40,29.5 M27,48.5 L14,63.5 M27,48.5 L40,63.5" style="stroke:#181818;stroke-width:.5"/><text x="5" y="935.676" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="38">Game</text><ellipse cx="27" cy="947.689" fill="#E2E2F0" rx="8" ry="8" style="stroke:#181818;stroke-width:.5"/><path fill="none" d="M27,955.6895 L27,982.6895 M14,963.6895 L40,963.6895 M27,982.6895 L14,997.6895 M27,982.6895 L40,997.6895" style="stroke:#181818;stroke-width:.5"/><rect width="85" height="32.621" x="246.5" y="50" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="253.5" y="72.107" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="71">SubModule</text><rect width="85" height="32.621" x="246.5" y="920.568" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="253.5" y="942.676" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="71">SubModule</text><rect width="82" height="32.621" x="341.5" y="50" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="348.5" y="72.107" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="68">UIExtender</text><rect width="82" height="32.621" x="341.5" y="920.568" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="348.5" y="942.676" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="68">UIExtender</text><rect width="154" height="32.621" x="491.5" y="50" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="498.5" y="72.107" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="140">ViewModelComponent</text><rect width="154" height="32.621" x="491.5" y="920.568" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="498.5" y="942.676" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="140">ViewModelComponent</text><rect width="81" height="32.621" x="655.5" y="50" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="662.5" y="72.107" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67">ViewModel</text><rect width="81" height="32.621" x="655.5" y="920.568" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="662.5" y="942.676" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="67">ViewModel</text><rect width="176" height="32.621" x="824" y="50" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="831" y="72.107" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="162">ViewModelWithMixinPatch</text><rect width="176" height="32.621" x="824" y="920.568" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="831" y="942.676" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="162">ViewModelWithMixinPatch</text><rect width="112" height="32.621" x="1010" y="50" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="1017" y="72.107" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="98">ViewModelMixin</text><rect width="112" height="32.621" x="1010" y="920.568" fill="#E2E2F0" rx="2.5" ry="2.5" style="stroke:#181818;stroke-width:.5"/><text x="1017" y="942.676" fill="#000" font-family="sans-serif" font-size="14" lengthAdjust="spacing" textLength="98">ViewModelMixin</text><polygon fill="#181818" points="277 112.912 287 116.912 277 120.912 281 116.912" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="27" x2="283" y1="116.912" y2="116.912"/><text x="34" y="111.649" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="238">OnBeforeInitialModuleScreenSetAsRoot()</text><polygon fill="#181818" points="370.5 144.203 380.5 148.203 370.5 152.203 374.5 148.203" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="289" x2="376.5" y1="148.203" y2="148.203"/><text x="296" y="142.94" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="56">Register()</text><polygon fill="#181818" points="556.5 175.494 566.5 179.494 556.5 183.494 560.5 179.494" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="382.5" x2="562.5" y1="179.494" y2="179.494"/><text x="389.5" y="174.231" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="162">Register(Type[] mixinTypes)</text><polygon fill="#181818" points="393.5 189.494 383.5 193.494 393.5 197.494 389.5 193.494" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="387.5" x2="567.5" y1="193.494" y2="193.494"/><polygon fill="#181818" points="300 203.494 290 207.494 300 211.494 296 207.494" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="294" x2="381.5" y1="207.494" y2="207.494"/><polygon fill="#181818" points="38 217.494 28 221.494 38 225.494 34 221.494" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="32" x2="288" y1="221.494" y2="221.494"/><polygon fill="#181818" points="684 276.785 694 280.785 684 284.785 688 280.785" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="27" x2="690" y1="280.785" y2="280.785"/><text x="34" y="275.522" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="75">Constructor()</text><polygon fill="#181818" points="900 308.076 910 312.076 900 316.076 904 312.076" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="696" x2="906" y1="312.076" y2="312.076"/><text x="703" y="306.813" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="192">Harmony intercepts Constructor()</text><polygon fill="#181818" points="579.5 339.367 569.5 343.367 579.5 347.367 575.5 343.367" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="573.5" x2="911" y1="343.367" y2="343.367"/><text x="585.5" y="338.104" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="181">InitializeMixinsForVMInstance()</text><path fill="#EEE" d="M481.5,358.3672 L554.5,358.3672 L554.5,367.6582 L544.5,377.6582 L481.5,377.6582 L481.5,358.3672" style="stroke:#000;stroke-width:1.5"/><rect width="650.5" height="109.873" x="481.5" fill="none" style="stroke:#000;stroke-width:1.5" y="358.367"/><text x="496.5" y="373.396" fill="#000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="28">loop</text><text x="569.5" y="372.237" fill="#000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="178">[All registered ViewModelMixin]</text><polygon fill="#181818" points="1054 396.949 1064 400.949 1054 404.949 1058 400.949" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="568.5" x2="1060" y1="400.949" y2="400.949"/><text x="575.5" y="395.687" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="75">Constructor()</text><polygon fill="#181818" points="707 428.24 697 432.24 707 436.24 703 432.24" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="701" x2="1065" y1="432.24" y2="432.24"/><text x="713" y="426.978" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="258">Refresh() (if the original Constructor() calls it)</text><polygon fill="#181818" points="1054 442.24 1064 446.24 1054 450.24 1058 446.24" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="696" x2="1060" y1="446.24" y2="446.24"/><polygon fill="#181818" points="579.5 456.24 569.5 460.24 579.5 464.24 575.5 460.24" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="573.5" x2="1065" y1="460.24" y2="460.24"/><polygon fill="#181818" points="900 477.24 910 481.24 900 485.24 904 481.24" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="568.5" x2="906" y1="481.24" y2="481.24"/><polygon fill="#181818" points="707 491.24 697 495.24 707 499.24 703 495.24" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="701" x2="911" y1="495.24" y2="495.24"/><polygon fill="#181818" points="38 505.24 28 509.24 38 513.24 34 509.24" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="32" x2="695" y1="509.24" y2="509.24"/><polygon fill="#181818" points="684 564.531 694 568.531 684 572.531 688 568.531" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="27" x2="690" y1="568.531" y2="568.531"/><text x="34" y="563.269" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="52">Refresh()</text><polygon fill="#181818" points="900 595.822 910 599.822 900 603.822 904 599.822" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="696" x2="906" y1="599.822" y2="599.822"/><text x="703" y="594.56" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="169">Harmony intercepts Refresh()</text><path fill="#EEE" d="M814,614.8223 L887,614.8223 L887,624.1133 L877,634.1133 L814,634.1133 L814,614.8223" style="stroke:#000;stroke-width:1.5"/><rect width="318" height="64.582" x="814" fill="none" style="stroke:#000;stroke-width:1.5" y="614.822"/><text x="829" y="629.851" fill="#000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="28">loop</text><text x="902" y="628.692" fill="#000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="178">[All registered ViewModelMixin]</text><polygon fill="#181818" points="1054 653.404 1064 657.404 1054 661.404 1058 657.404" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="912" x2="1060" y1="657.404" y2="657.404"/><text x="919" y="652.142" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="52">Refresh()</text><polygon fill="#181818" points="923 667.404 913 671.404 923 675.404 919 671.404" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="917" x2="1065" y1="671.404" y2="671.404"/><polygon fill="#181818" points="707 688.404 697 692.404 707 696.404 703 692.404" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="701" x2="911" y1="692.404" y2="692.404"/><polygon fill="#181818" points="38 702.404 28 706.404 38 710.404 34 706.404" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="32" x2="695" y1="706.404" y2="706.404"/><polygon fill="#181818" points="684 761.695 694 765.695 684 769.695 688 765.695" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="27" x2="690" y1="765.695" y2="765.695"/><text x="34" y="760.433" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="70">OnFinalize()</text><polygon fill="#181818" points="900 792.986 910 796.986 900 800.986 904 796.986" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="696" x2="906" y1="796.986" y2="796.986"/><text x="703" y="791.724" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="187">Harmony intercepts OnFinalize()</text><path fill="#EEE" d="M814,811.9863 L887,811.9863 L887,821.2773 L877,831.2773 L814,831.2773 L814,811.9863" style="stroke:#000;stroke-width:1.5"/><rect width="318" height="64.582" x="814" fill="none" style="stroke:#000;stroke-width:1.5" y="811.986"/><text x="829" y="827.015" fill="#000" font-family="sans-serif" font-size="13" font-weight="bold" lengthAdjust="spacing" textLength="28">loop</text><text x="902" y="825.856" fill="#000" font-family="sans-serif" font-size="11" font-weight="bold" lengthAdjust="spacing" textLength="178">[All registered ViewModelMixin]</text><polygon fill="#181818" points="1054 850.568 1064 854.568 1054 858.568 1058 854.568" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1" x1="912" x2="1060" y1="854.568" y2="854.568"/><text x="919" y="849.306" fill="#000" font-family="sans-serif" font-size="13" lengthAdjust="spacing" textLength="70">OnFinalize()</text><polygon fill="#181818" points="923 864.568 913 868.568 923 872.568 919 868.568" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="917" x2="1065" y1="868.568" y2="868.568"/><polygon fill="#181818" points="707 885.568 697 889.568 707 893.568 703 889.568" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="701" x2="911" y1="889.568" y2="889.568"/><polygon fill="#181818" points="38 899.568 28 903.568 38 907.568 34 903.568" style="stroke:#181818;stroke-width:1"/><line style="stroke:#181818;stroke-width:1;stroke-dasharray:2,2" x1="32" x2="695" y1="903.568" y2="903.568"/></g></svg>