Skip to content

Develop#2

Open
phantomlight wants to merge 8544 commits intocrnjan:developfrom
MonoGame:develop
Open

Develop#2
phantomlight wants to merge 8544 commits intocrnjan:developfrom
MonoGame:develop

Conversation

@phantomlight
Copy link

No description provided.

richlander and others added 30 commits December 27, 2024 14:46
MonoGame.Packaging.Flatpak is a package I wrote a while ago to quickly
package up a MonoGame game into a flatpak package for Linux during
`dotnet pack` process.

However its long since been broken and I don't see any benefit in
keeping it around in its current state.
…8636)

Changed the name of the **save** option from 'Save...' to 'Save' and
changed 'Save As' to 'Save As...' under the **file** menu of the menu
strip of the MGCB Editor for convention. As **save as** opens a dialog
while **save** does not.

---------

Co-authored-by: Simon (Darkside) Jackson <darkside@zenithmoon.com>
Fixes a documentation typo.

### Description of Change

This is a very simple change that fixes a single typo in the
`MonoGame.Framework.Content.Pipeline/Processors/ModelProcessor.cs` file.

Before: `MipMpas`
After: `MipMaps`

Co-authored-by: Simon (Darkside) Jackson <darkside@zenithmoon.com>
Reference specific commit for the Vulkan setup, so things build. We'll
need to update this once the setup-vulkan-sdk 1.2.1 release it official.

As per temporary suggested fix there -
humbletim/setup-vulkan-sdk#28 (comment)
Wine 10.0 removed the wine64 executable and now only has wine. This
change detects which one is available and uses it.

It also fixes an issue where the working directory could not be set.

```
An error occurred trying to start process 'wine64' with working directory '/Users/runner/work/MonoGame/MonoGame/Artifacts/Tests/Tools/Release'.
```

We do this by providing an actual working directory which we know
exists. This is the location of the WineHelper executable.
I started addressing #8104 and those changes should make MonoGame mostly
safe in AOT contexts (it fixes all the errors of loading assets and
removes the need to force MonoGame to not be trimmed).

Working on this actually made visible more AOT issues. I fixed the most
trivial IL warnings but some of them persists.
Also, since BRUTE hasn't fully retired yet, I'm trying to write this in
a ```net452``` backward compatible way (some of the newer and better
reflection stuff isn't available on older .NET Frameworks).

Any help is welcome!

Here are my notes on the remaining issues (none really are blockers,
just enhancing the AOT experience and avoid misleading warnings for
users):

- [x] ```ReflectiveReader```, ```DictionaryReader```, ```ArrayReader```,
and ```MultiArrayReader``` need to be flagged as not compatible with AOT
with the ```RequiresDynamicCode``` attribute. Those types are generic
and can't be made safe for AOT. The warning inside the attribute must
encourage users to rewrite their content serialization in a way that
doesn't rely on reflection is they wish to use AOT.

- [ ] WindowsDX will [fail loading an embedded
icon](https://github.com/MonoGame/MonoGame/blob/develop/MonoGame.Framework/Platform/Windows/WinFormsGameWindow.cs#L261)
because ```assembly.Location``` is always null in AOT contexts.

Those ones aren't really issues and will likely not trigger runtime
errors. We could just disable warnings on those, but it would be nice to
try to fix them in a clean way to avoid unforeseen consequences:

- [ ]
[VectorConversion](https://github.com/MonoGame/MonoGame/blob/develop/MonoGame.Framework/Design/VectorConversion.cs)
uses reflection to convert to/from ```IPackedVector```. This needs to be
rewritten reflection-free. We can also assume that ```IPackedVector```
is never trimmed and just disable the warnings, but that's an easy fix
and likely less error-prone to not rely on disabling warnings.

- [ ] There are a couple of instances of type instance creation that we
should try to get rid of if possible:

https://github.com/MonoGame/MonoGame/blob/2e72fcfa4144ea5bc413963af8f97a2d5e902338/MonoGame.Framework/Content/ContentReaders/MultiArrayReader.cs#L36

https://github.com/MonoGame/MonoGame/blob/2e72fcfa4144ea5bc413963af8f97a2d5e902338/MonoGame.Framework/Graphics/Vertices/VertexDeclaration.cs#L214

- [ ] ```ContentTypeReaderManager``` has a warning here (might be
fixable):

https://github.com/MonoGame/MonoGame/blob/2e72fcfa4144ea5bc413963af8f97a2d5e902338/MonoGame.Framework/Content/ContentTypeReaderManager.cs#L154

- [ ] ```ContentManager``` has 2 warnings here (can be disabled, this
will likely never fail, and this is only useful for Android):

https://github.com/MonoGame/MonoGame/blob/2e72fcfa4144ea5bc413963af8f97a2d5e902338/MonoGame.Framework/Content/ContentManager.cs#L592

- [ ] DesktopGL has ```VertexBuffer.GetBufferData()``` which might fail
in AOT depending on the vertex declaration (we can't fix this, but it
would be best to flag this method as incompatible, but like other
warnings, this should actually be fine):

https://github.com/MonoGame/MonoGame/blob/2e72fcfa4144ea5bc413963af8f97a2d5e902338/MonoGame.Framework/Platform/Graphics/Vertices/VertexBuffer.OpenGL.cs#L92
Partially addresses #8165

### XML Documentation 

This PR aims to add new and update existing XML documentation to various
public members with the intent to reduce build warnings
Fixes #8408

We'll need to update SDL to latest 2.x release after that for maximum
profit.
…atform (#8660)

Fixes #8657 

FileDrop in a WindowsDX project cuts off the last character in the path

### Description of Change

Adding a byte to the final call of DragQueryFile as it expects the final
byte to be the destination of the null string terminator. Ie, '.png' is
4 chars, with buffSize = 4, result would be '.pn`null`'

> [out] lpszFile
> 
> Type: LPTSTR
> 
> The address of a buffer that receives the file name of a dropped file
when the function returns. This file name is a null-terminated string.
If this parameter is NULL, DragQueryFile returns the required size, in
characters, of this buffer.

Co-authored-by: Simon (Darkside) Jackson <darkside@zenithmoon.com>
…trix (#8671)

Fixes #8661

### Description of Change

Fixes `OpenAssetImporter.GetRelativeTransform` to now correctly return a
row-major matrix. Appears to have been broken when #8607 removed the
`ToXna(Matrix4x4 matrix)` method, resulting in the return of an
incorrect column-major matrix.

While this fixes the rendering of ShipGame models, I just realised other
changes from that PR might have broken other things. I'll try some other
3d models and import options next I guess.

---------

Co-authored-by: Simon (Darkside) Jackson <darkside@zenithmoon.com>
…8676)

This commit removes an early return in the WineHelper.cs file to allow the process to retry with "wine" as the fallback executable instead of "wine64".

Removed the return statement in the catch block so that after changing the executable to "wine", the program will continue to start the process.

This change enables the intended retry logic for process execution.
### Description of Change
This PR:
a) fixes the typo docline in `ContentManager.cs` introduced in
7b84682#diff-37705868f9e9f6e1ee0f3b9f8d532d01f861d3e26a3050b30435ac545abb81ceR301

b) adds **empty** doclines for readers that were made public in
a23eccd
(this fixes all
[CS1591](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs1591)
warnings in DesktopGL and partly in WindowsDX):
`Content/ContentReaders/ArrayReader.cs`
`Content/ContentReaders/DictionaryReader.cs`
`Content/ContentReaders/EnumReader.cs`
`Content/ContentReaders/ListReader.cs`
`Content/ContentReaders/MultiArrayReader.cs`
`Content/ContentReaders/NullableReader.cs`
`Content/ContentReaders/ReflectiveReader.cs`
Feel free to revert this change, if actual documentation is to be added
to these files.
…itives() (#8580)

Fixes #3125

## Description of Change

Added vertex size check to GraphicsDevice.DrawUserPrimitives()
Now method throws an exception when the size of a vertexDeclaration.VertexStride is less than ReflectionHelpers.FastSizeOf<T>() as suggested here:
#3125 (comment)
<!--
Are you targeting develop? All PRs should target the develop branch
unless otherwise noted.
-->

Fixes #6298

<!--
Please try to make sure that there is a bug logged for the issue being
fixed if one is not present.
Especially for issues which are complex. 
The bug should describe the problem and how to reproduce it.
-->

### Description of Change

Implemented the ContainsPrecise method for BoundingBox, as suggested by
Member (#8564)
- ContainsPrecise performs an exact containment check between a
BoundingBox and
BoundingFrustum, avoiding false positives
- Implemented 6 unit tests covering various scenarios for the
ContainsPrecise method
- Tests include cases for full containment (1), intersection (3), and
disjoint (2) relationships

<!-- 
Enter description of the fix in this section.
Please be as descriptive as possible, future contributors will need to
know *why* these changes are being made.
For inspiration review the commit/PR history in the MonoGame repository.
-->
Comit 5595e50 added changes to the working directory that caused a
problem when compiling effects.
So lets back out that change.

```
The input file '/Users/xxx/.nuget/packages/dotnet-mgcb/3.8.2.1922-develop/tools/net8.0/any/shaders/NormalMapping.fx' was not found!
```
For some reason, ```ConsoleCheck``` has been unplugged from the CI and
as a result some PRs introduced incompatibilities with .NET 4.5 / C# 5.

This PR fixes the incompatibilities and restores ```ConsoleCheck```.

For now, the ```ConsoleCheck``` only tests against the current code
architecture. It doesn't test the newer ```Native``` structure but some
consoles have already been ported to that structure, so we need
something like ```ConsoleCheck.Native```.

Additionnaly, it would be necessary to have the ```DesktopGL``` tests to
run using ```PublishAot``` to make sure that no PR uses runtime
reflection (which we can't test with building ```ConsoleCheck```) to
avoid regressions on the ```PublishAot``` compatibility.

-----

If anyone wonders "why is this limitation still in place? didn't you
change the console runtime?", the answer is: yes and no.

Yes, the consoles have been moved toward using ```PublishAot``` instead
of BRUTE. All but one, because ```PublishAot``` can't be used there.
Which means that there is one single platform currently limiting the
entirety of MonoGame. We're trying to figuring it out, but it's a
process we don't have a power over and involves bureaucracy (or possibly
to rewrite entirely BRUTE). So no ETA on fixing this, but it's expected
to take a very long time.
This PR updates DesktopGL to SDL 2.32.2
…-platform apps. (#8663)

Fixes #8664 


### Description of Change

Moved the SensorData classes up to the top level (still don't like that
the namespaces are `Microsoft.Devices.*`), then refactored the Platform
classes to remove the iOS IFDEF, following more consistent patterns in
the codebase.
Then added the classes to the non supported classes (the throw
`PlatformNotSupported` exceptions if called), but this now allows game
devs to use Accelerometer and Compass classes in a more cross-platform
way.

Since Microsoft has pulled the WinPhone, in MG 4, we should consider
renaming the namespace to `MonoGame.Devices.*`, IMHO.
Fixes #8683

### Description of Change

Fixes importing contentproj files that reference files outside the
project directory. Visual Studio puts a `<Link>` in a `<Content>`,
`<Compile>` or `<None>` element to show the desired position in the
structure, which MGCB was not respecting.
As Per subject line. Something I missed with the previous PR 🤦‍♂️ .
Hi! First time contributing, please be gentle!

I ran into a problem where I couldn't set the Pitch of a sound effect
instance below `-1.0f` or above `1.0f` without throwing an exception.
This is on purpose, according to the docs, but 1 octave up/down is
really limiting!

I saw discussion of it in [this ancient
PR](#4852) and it seems there's
no technical reason for this limitation. The best justification I can
imagine is "That's how XNA did it." (I have no evidence of this, total
guess).

My proposal is pretty straightforward: we just get rid of the range
check and let AL handle it. I'm not changing any of the math for
backwards compatibility, plus 1.0 == 1 octave is actually pretty
elegant, I just wish I could have 2.0, or 10.0!

I'd be happy to add/modify a test for this, but I wasn't able to run the
unit tests because I can't get Monogame to build on my machine
(attempting to build via Visual Studio 2019 using
`MonoGame.Framework.DesktopGL.sln` and/or `MonoGame.Tools.Windows.sln`).
This pull request is to fix DynamicSoundEffectInstance requesting
buffers too late. More details on the issue can be found here: #7565

For demonstration purposes please see the OpenALPendingBufferCount
project within here:

[https://github.com/squarebananas/MonoGameSamplesForIssues](https://github.com/squarebananas/MonoGameSamplesForIssues)

---------

Co-authored-by: Simon (Darkside) Jackson <darkside@zenithmoon.com>
Prevents a "Skipping XYZ..." message for each asset which is _not_
converted during the content build process.

On projects with a lot of content, this creates a lot of noise. I left
the normal output message enabled since the conversion can be slow, and
it gives the user indication of what is happening. The "Skipping XYZ..."
messages just tend to drown out everything else.
…8690)

Just a quick one - saw a few trivial warnings when building in debug
that were due to invalid XMLDOC comments. Thought I'd fix them up.
Updating the csproj files for the solution with README references fo r
the NuGet packages to make them clearer, including links to required
destinations such as issue fixing

- resolves: #8691
harry-cpp and others added 30 commits December 29, 2025 11:44
Stuff done:
- Split out the base class logger from the new content builder logger
- Hooked up the `LogLevel` parameter to the content logger
- Hooked up the `LoggerRootDirectory` so we got some proper pathing
showing up
- Reworked the default appearance of the log thats:
  - Friendly for msbuild to parse the warnings / errors from
  - Friendly appearance for threaded logging if we ever get to that
- Honestly even better for looking at for me :D, technically if anyone
liked the previous one they can just assign the `ContentBuilder.Logger`
property to a custom made logger

Bellow are some examples on appearance based on log level.

Debug:
<img width="648" height="398" alt="debug"
src="https://github.com/user-attachments/assets/534cb671-5616-438b-b005-4db79b2bce52"
/>

Info:
<img width="532" height="187" alt="info"
src="https://github.com/user-attachments/assets/0cd5da1d-7fb9-47ae-92f0-2c38b00c874d"
/>

Warning:
<img width="397" height="101" alt="warning"
src="https://github.com/user-attachments/assets/3393db82-0186-44d7-ab22-bc6250b27d43"
/>
We renamed `WindowsGDK` `TargetPlatform` and `MonoGamePlatform` to
`WindowsDX12`.

Also fixed shader, texture, and audio profiles for `WindowsDX12`.
# Summary

Updating license year for 2026 and a revision of published docs in the
repository
# Summary

Update templates to use the 3.8.5-preview releases for CB templates
More Fixes going all the way back to
#[8101](#8101)

### Description of Change

Updates remaining Headers with the previous **The MonoGame Team**
copyright to match the new Foundation Copyright standard. I happened to
be playing around with the newer native implementations and noticed the
CType generators had the older copyright text and then I went down this
rabbit hole of finding more and more.

I apologize for the big PR! It really is just comment updates with the
exception of these files that have impactful changes to the comments
created on newly generated CTypes files:

Tools/MonoGame.Generator.CTypes/EnumWritter.cs
Tools/MonoGame.Generator.CTypes/PInvokeWritter.cs
Tools/MonoGame.Generator.CTypes/StructWritter.cs
I **suspect** this is supposed to fix the following issues (the
circumstances when this reproduces are a bit different for me, but the
stack is similar to what #9164 has reported; I suspect they all are
relatively about the same, and it would make sense to at least ask the
folks to re-check their issues after merging this fix):
- fix #9164
- fix #9161
- fix #9156

### Description of Change
Previously, the pointers `lastFeature` and `deviceFeatures2` could
outlive the variables they are pointing to. These pointers are then
exposed as part of the `deviceCreateInfo` — which could cause crash if
the stack memory is reused for any purpose.

The problem was reproduced for me when debugging a MonoGame program by
Rider on Windows, but not under any other circumstances (e.g. debugging
via VS or just running the program — no luck, doesn't reproduce).

Also note that it was only reproducing if using the **Release** build of
`mgruntime.dll` — not the **Debug** one.

Rebuilt MonoGame locally, can confirm I have stable repro before the fix
(on the official binaries and on the ones I build myself), and after the
fix the issue no longer reproduces.

---------

Co-authored-by: Simon (Darkside) Jackson <darkside@zenithmoon.com>
This is the initial implementation of Song for the native backend including a unit test as well.
Added a contributor declaration to certify no LLMs were used for the
contributed code.
## Description

Fixes two bugs in `Color.FromHSV()`

1. Fixes fractional hue calculation within color wheel segments. The
fractional position `f` within each 60deg segment was calcualted as `int
f = (int)(h / 60.0f) - i`, which always resulted in a `0` due to integer
arithmetic. Changed to `float f = (h % 60.0f) / 60.0f` to correctly
calcualte fractional position within [0,1] range.
2. Removed incorrect normalization of saturation and value parameters.
The documentation for the method states that these values should be in
the [0,1] range. By normalizing them by dividing by 100, this causes
colors to be nearly black in all cases (e.g. passing `s=1.0, v=1.0`
would result in RGB values of `2` instead of `255`)

Additionally, `Color.FromHSV()`, `Color.FromHSL()` were changed to
`static` methods. These are factory methods for creating a `Color` value
from a different structure, it doesn't make sense to have them as
instance members that require an instance before using.

## Breaking Changes

Since `Color.FromHSV()` and `Color.FromHSL()` are changed to static
factory methods, this would be considered a breaking change as it
changes the public API that already existed. Not sure if you want to
keep this change since it's technically a breaking change or we can
obsolete the existing ones with a warning and forward them to the new
static ones, then remove the instance methods in a future release where
breaking changes are good.

## Related Issues
- Closes #9131
# Summary

Cleanup for the builder `.targets`, does not need exception for windows
for launching the builder project.
Cleaned up
Disable VSCode based CoPilot features so that contributors who need to
use CoPilot for work or other projects do not need to disable it
manually.

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.
Add a new `FontImporter` in which you can directly specify the
properties that would otherwise go into a .spritefont file.

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.
Fixes #9011 

### Description of Change

The `StringBuilder` in `HandleDropMessage` was allocated with a buffer
size of `buffSize`, but the `cch` parameter passed to `DragQueryFile` is
`buffSize + 1` (to account for the null terminator).

This mismatch could cause the last character of file paths to be
truncated on some configurations, as reported in the issue.

The fix ensures the `StringBuilder` capacity matches the expected buffer
size passed to the Win32 API.

**Before:**
```csharp
StringBuilder builder = new StringBuilder((int)buffSize);
DragQueryFile(hdrop, i, builder, buffSize + 1);
```
**After:**
```csharp
StringBuilder builder = new StringBuilder((int)buffSize + 1);
DragQueryFile(hdrop, i, builder, buffSize + 1);
```

Co-authored-by: Tom Spilman <tom@sickheadgames.com>
Fixes #9189 

### Description of Change

Takes the same logic used in Load and handles converting \\\ to the /
format when trying to UnloadAssets.
Verified that it works using a simple Repro project based on the
provided code in the issue.

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.

Co-authored-by: Jake Kirkbride <jakelegendxiii@rjtechnologies.com>
- Fix `TokenType` to be internal to pipeline.
- Updated CppNet submodule for doc fixes.

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.
Also added some improved docs for FrameworkDispatcher.

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.
- Validate controllers have valid gamepad profiles before reporting as
connected
- Fix GetCapabilities() to set IsConnected = true when profiles exist
- Applies to both iOS and tvOS implementations

Addresses #9099

### Description of Change

Adds defensive validation to iOS/tvOS gamepad detection in response to
reports of phantom controllers appearing in iOS 18.

## Changes Made

1. **Profile validation in `PlatformGetState()`**: Before reporting a
controller as connected, verify it has a valid gamepad profile
(ExtendedGamepad, Gamepad, or MicroGamepad for tvOS).

2. **`GetCapabilities()`**: Now sets `IsConnected = true` when a
controller has a valid profile.

## Rationale

Users report phantom gamepads appearing on iOS 18, even when no gamepad
is connected. Disabling Bluetooth or unpairing devices resolves it,
suggesting Apple's `GCController.Controllers` array may include
paired-but-disconnected controllers or misclassified Bluetooth devices.

This validation ensures only controllers with actual gamepad input
profiles are reported as connected by adding a defensive layer without
breaking legitimate controller support.

## Testing Notes

- Non-breaking change—legitimate controllers with valid profiles
continue to work
- Filters devices without gamepad profiles (keyboards, mice,
disconnected controllers)
### Description of Change
Refactored Matrix.CreateBillboard for better readability.
Renamed local variables:
vector -> cameraDir
vector2 -> up
vector3 -> right
…ementations to avoid confusion. (#9203)

# Summary

It was repoted there was confusion regardind the description of
`Keys.None` as it was different to other implementations.

On review, this has now been updated to "No Key Set" which aligns with
all other "None" enum definitions, including `Buttons.None`

Resolves - #7826
Fixes #9213 

Lets pin xcode for 26.0.1 to fix this error

```
error : This version of .NET for iOS (26.0.9783) requires Xcode 26.0. The current version of Xcode is 26.2. Either install Xcode 26.0, or use a different version of .NET for iOS. See https://aka.ms/xcode-requirement for more information. 
```

26.0.1 is already installed on the macos images, we just need to select
it until its no longer available.


### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.
<!--
Are you targeting develop? All PRs should target the develop branch
unless otherwise noted.
-->

Fixes #9205 

<!--
Please try to make sure that there is a bug logged for the issue being
fixed if one is not present.
Especially for issues which are complex. 
The bug should describe the problem and how to reproduce it.
-->

### Description of Change

This adds `SaveAsPngShouldWork` and `SaveAsJpegShouldWork` to
Texture2DTests.cs, plus some static helpers for building test textures.

Both tests rely on `Texture2D.FromStream`. They make a sample texture,
save to a `MemoryStream` with the method being tested, and then compare
the sample against the result of `Texture2D.FromStream` on the same
memory stream.

The PNG tests require all pixels to be identical between the two images,
and the JPEG tests require that all result pixels be within 35 of the
source on R, G, and B channels. Alpha is not tested for JPEG. 35 was
arbitrary to get my test cases to pass so I won't lose any sleep over it
if someone who understands JPEG better than me wants to improve the
result comparison.
 
<!-- 
Enter description of the fix in this section.
Please be as descriptive as possible, future contributors will need to
know *why* these changes are being made.
For inspiration review the commit/PR history in the MonoGame repository.
-->


### Contributor Declaration

- [X] I certify that no LLM's were used to generate any code or
documentation in this contribution.

Co-authored-by: Tom Spilman <tom@sickheadgames.com>
#9220)

Fixes #9212 


### Description of Change
This PR addresses an issue on the Vulkan where textures that were 2D
arrays were getting mapped to `VK_IMAGE_VIEW_TYPE_2D` instead of
`VK_IMAGE_VIEW_TYPE_2D_ARRAY`. On MacOS, this mismatch causes an
application crash.

The approach chosen was to add an additional optional `layerCount`
parameter to `ToVkImageViewType` that can be used to distinguish between
2D and 2D Array types.

Note that there is a similarly named `ToVkImageType` that performs a
conversion between `MGTextureType` and Vulkan constants. It does not
include this new switching logic because it doesn't seem to affect the
MacOS runtime problem which is what motivated the creation of #9212.

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.

Co-authored-by: Adam Carter <adamcarter@umpquabank.com>
Fixes #9206.

### Description of Change

This changes [
RenderTarget3D.cs](https://github.com/MonoGame/MonoGame/blob/6058c786ee5b30d9ab91135edd4df29acaefc52c/MonoGame.Framework/Graphics/RenderTarget3D.cs)
to add XML comments for the class.

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.
…ng units from KHz to Hz where appropriate. (#9238)

### Description of Change

This pull request changes the error string for `WavImporter`'s
`InvalidContentException` when a `.wav` file outside of the supported
sample rate range is supplied. Previously, this error string incorrectly
displayed the offending file's sample rate in `Hz` yet labeled it as
`KHz`. This pull request changes the unit label to `Hz` and, for the
sake of consistency, further changes the part of the error string that
informs the user of the 8KHz-48KHz bounds to be displayed in `Hz`.

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.
Pin Xcode to use 26.2 to fix the CI builds

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.
Turns out we were missing the float * Matrix operator on the Matrix
class all these years. We have Matrix * float, but not the other. This
adds it.


https://learn.microsoft.com/en-us/previous-versions/windows/xna/bb198123(v=xnagamestudio.40)

### Contributor Declaration

- [x] I certify that no LLM's were used to generate any code or
documentation in this contribution.
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.