/* ┌──────────────────────────────────────────────────────────────────┐ │ Author: Ivan Murzak (https://github.com/IvanMurzak) │ │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │ │ Copyright (c) 2025 Ivan Murzak │ │ Licensed under the Apache License, Version 2.0. │ │ See the LICENSE file in the project root for more information. │ └──────────────────────────────────────────────────────────────────┘ */ #nullable enable using System; using System.Text.Json; using System.Text.Json.Nodes; using com.IvanMurzak.ReflectorNet.Json; using com.IvanMurzak.ReflectorNet.Utils; using UnityEngine; namespace com.IvanMurzak.Unity.MCP.JsonConverters { public class Matrix4x4Converter : JsonSchemaConverter, IJsonSchemaConverter { // Pre-computed property names to avoid string allocations in the Write loop private static readonly string[] MatrixPropertyNames = { "m00", "m01", "m02", "m03", "m10", "m11", "m12", "m13", "m20", "m21", "m22", "m23", "m30", "m31", "m32", "m33" }; public override JsonNode GetSchema() => new JsonObject { [JsonSchema.Type] = JsonSchema.Object, [JsonSchema.Properties] = new JsonObject { ["m00"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m01"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m02"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m03"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m10"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m11"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m12"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m13"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m20"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m21"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m22"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m23"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m30"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m31"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m32"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number }, ["m33"] = new JsonObject { [JsonSchema.Type] = JsonSchema.Number } }, [JsonSchema.Required] = new JsonArray { "m00", "m01", "m02", "m03", "m10", "m11", "m12", "m13", "m20", "m21", "m22", "m23", "m30", "m31", "m32", "m33" }, [JsonSchema.AdditionalProperties] = false }; public override JsonNode GetSchemaRef() => new JsonObject { [JsonSchema.Ref] = JsonSchema.RefValue + Id }; public override Matrix4x4 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) throw new JsonException("Expected start of object token."); float m00 = 0, m01 = 0, m02 = 0, m03 = 0; float m10 = 0, m11 = 0, m12 = 0, m13 = 0; float m20 = 0, m21 = 0, m22 = 0, m23 = 0; float m30 = 0, m31 = 0, m32 = 0, m33 = 0; while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) { var m = new Matrix4x4(); m.m00 = m00; m.m01 = m01; m.m02 = m02; m.m03 = m03; m.m10 = m10; m.m11 = m11; m.m12 = m12; m.m13 = m13; m.m20 = m20; m.m21 = m21; m.m22 = m22; m.m23 = m23; m.m30 = m30; m.m31 = m31; m.m32 = m32; m.m33 = m33; return m; } if (reader.TokenType == JsonTokenType.PropertyName) { var propertyName = reader.GetString(); reader.Read(); switch (propertyName) { case "m00": m00 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m01": m01 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m02": m02 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m03": m03 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m10": m10 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m11": m11 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m12": m12 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m13": m13 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m20": m20 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m21": m21 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m22": m22 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m23": m23 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m30": m30 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m31": m31 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m32": m32 = JsonFloatHelper.ReadFloat(ref reader, options); break; case "m33": m33 = JsonFloatHelper.ReadFloat(ref reader, options); break; default: throw new JsonException($"Unexpected property name: {propertyName}."); } } } throw new JsonException("Expected end of object token."); } public override void Write(Utf8JsonWriter writer, Matrix4x4 value, JsonSerializerOptions options) { writer.WriteStartObject(); for (int i = 0; i < 16; i++) { int row = i / 4; int col = i % 4; JsonFloatHelper.WriteFloat(writer, MatrixPropertyNames[i], value[row, col], options); } writer.WriteEndObject(); } } }