Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Alchemy.SourceGenerator.Tests/GeneratorUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ static ImmutableArray<MetadataReference> LoadFrameworkReferences()
namespace UnityEngine
{
public class Object { }
public class GameObject : Object { }
public class MonoBehaviour : Object { }
public interface ISerializationCallbackReceiver
{
void OnBeforeSerialize();
Expand Down
55 changes: 55 additions & 0 deletions Alchemy.SourceGenerator.Tests/NamespaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,59 @@ public partial class Player

await Assert.That(result.AllGeneratedText).Contains("__alchemySerializationData_My_Game_Player");
}

[Test]
public async Task Dictionary_types_are_globally_qualified_when_root_namespace_is_shadowed()
{
var result = GeneratorUtils.Run("""
using System;
using System.Collections.Generic;
using Alchemy.Serialization;
using Artillery.Entities;
using Artillery.Entities.Units;

namespace Artillery.Artillery
{
public sealed class NamespaceCollision { }
}

namespace Artillery.Entities
{
public enum UnitTeam
{
Ally,
Enemy
}
}

namespace Artillery.Entities.Units
{
public class BasicUnit : UnityEngine.MonoBehaviour { }
}

namespace Artillery.Entities.Units.Configuration
{
[AlchemySerialize]
public partial class UnitConfiguration
{
[AlchemySerializeField, NonSerialized]
public Dictionary<UnitTeam, UnityEngine.GameObject> teamObjects = new();

[AlchemySerializeField, NonSerialized]
public Dictionary<int, BasicUnit> units = new();

[AlchemySerializeField, NonSerialized]
public Dictionary<UnitTeam, BasicUnit> teamUnits = new();
}
}
""");

await Assert.That(result.AllGeneratedText).Contains(
"FromJson<global::System.Collections.Generic.Dictionary<global::Artillery.Entities.UnitTeam, global::UnityEngine.GameObject>>");
await Assert.That(result.AllGeneratedText).Contains(
"FromJson<global::System.Collections.Generic.Dictionary<int, global::Artillery.Entities.Units.BasicUnit>>");
await Assert.That(result.AllGeneratedText).Contains(
"FromJson<global::System.Collections.Generic.Dictionary<global::Artillery.Entities.UnitTeam, global::Artillery.Entities.Units.BasicUnit>>");
await Assert.That(result.DescribeCompilationErrors()).IsEqualTo("<none>");
}
}
2 changes: 1 addition & 1 deletion Alchemy.SourceGenerator/AlchemySerializeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ static string ProcessClass(INamedTypeSymbol typeSymbol, List<IFieldSymbol> field
{{
if ({alchemySerializationDataName}.{field.Name}.isCreated)
{{
this.{field.Name} = global::Alchemy.Serialization.Internal.SerializationHelper.FromJson<{field.Type.ToDisplayString()}>({alchemySerializationDataName}.{field.Name}.data, {alchemySerializationDataName}.UnityObjectReferences);
this.{field.Name} = global::Alchemy.Serialization.Internal.SerializationHelper.FromJson<{field.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>({alchemySerializationDataName}.{field.Name}.data, {alchemySerializationDataName}.UnityObjectReferences);
}}
}}
catch (global::System.Exception ex)
Expand Down
5 changes: 4 additions & 1 deletion Alchemy/Assets/Alchemy/Editor/Elements/DictionaryField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,10 @@ public override void Lock()
valueField.OnValueChanged -= SetValue;
valueField.OnValueChanged += x =>
{
ReflectionHelper.GetProperty(collection.GetType(), "Item").SetValue(collection, x, new object[] { key });
value = x;
keyValuePair = Activator.CreateInstance(kvType, key, value);
ReflectionHelper.GetProperty(collection.GetType(), "Item").SetValue(collection, value, new object[] { key });
OnValueChanged?.Invoke(keyValuePair);
};
}

Expand Down
44 changes: 44 additions & 0 deletions Alchemy/Assets/Alchemy/Editor/Elements/GenericField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,22 @@ void Build(object obj, Type type, string label, bool isDelayed)
{
AddField(new IntegerField(label), (int)obj);
}
else if (type == typeof(sbyte))
{
AddSmallIntegerField(label, (sbyte)obj, sbyte.MinValue, sbyte.MaxValue, x => (sbyte)x);
}
else if (type == typeof(byte))
{
AddSmallIntegerField(label, (byte)obj, byte.MinValue, byte.MaxValue, x => (byte)x);
}
else if (type == typeof(short))
{
AddSmallIntegerField(label, (short)obj, short.MinValue, short.MaxValue, x => (short)x);
}
else if (type == typeof(ushort))
{
AddSmallIntegerField(label, (ushort)obj, ushort.MinValue, ushort.MaxValue, x => (ushort)x);
}

else if (type == typeof(uint))
{
Expand Down Expand Up @@ -256,6 +272,34 @@ void Build(object obj, Type type, string label, bool isDelayed)
bool isDelayed;
bool changed;

void AddSmallIntegerField<T>(string label, int value, int minValue, int maxValue, Func<int, T> convert)
{
var control = new IntegerField(label) { value = value };
control.RegisterValueChangedCallback(x =>
{
var newValue = Math.Clamp(x.newValue, minValue, maxValue);
control.SetValueWithoutNotify(newValue);
if (isDelayed)
{
changed = true;
}
else
{
OnValueChanged?.Invoke(convert(newValue));
}
});
if (isDelayed)
{
control.RegisterCallback<FocusOutEvent>(_ =>
{
if (!changed) return;
OnValueChanged?.Invoke(convert(control.value));
changed = false;
});
}
Add(control);
}

void AddField<T>(BaseField<T> control, T value)
{
control.value = value;
Expand Down
1 change: 1 addition & 0 deletions Alchemy/Assets/Alchemy/Editor/Elements/HashMapFieldBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ public void Rebuild()
foreach (var item in (IEnumerable)collection)
{
var element = CreateItem(collection, item, "Element " + i);
element.OnValueChanged += _ => OnValueChanged?.Invoke(collection);
element.OnClose += () =>
{
if (isInputting) return;
Expand Down
Binary file modified Alchemy/Assets/Alchemy/Generator/Alchemy.SourceGenerator.dll
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1515897830369383587
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8483165521676513262}
- component: {fileID: 8927840334069668456}
m_Layer: 0
m_Name: DictionarySerializationTest
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &8483165521676513262
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1515897830369383587}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &8927840334069668456
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1515897830369383587}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 49945db4d049472db986e6e1eddce306, type: 3}
m_Name:
m_EditorClassIdentifier: Alchemy.Tests.EditorUI::Alchemy.Tests.EditorUI.DictionarySerializationTest
__alchemySerializationData_Alchemy_Tests_EditorUI_DictionarySerializationTest:
sbyteKeys:
isCreated: 1
data: "[\n {\n \"Key\": -101,\n \"Value\": 1\n }\n]"
byteKeys:
isCreated: 1
data: "[\n {\n \"Key\": 251,\n \"Value\": 2\n }\n]"
shortKeys:
isCreated: 1
data: "[\n {\n \"Key\": -30001,\n \"Value\": 3\n }\n]"
ushortKeys:
isCreated: 1
data: "[\n {\n \"Key\": 60001,\n \"Value\": 4\n }\n]"
intKeys:
isCreated: 1
data: "[\n {\n \"Key\": -2000000001,\n \"Value\": 5\n }\n]"
uintKeys:
isCreated: 1
data: "[\n {\n \"Key\": 4000000001,\n \"Value\": 6\n }\n]"
longKeys:
isCreated: 1
data: "[\n {\n \"Key\": -900000000000000001,\n \"Value\":
7\n }\n]"
ulongKeys:
isCreated: 1
data: "[\n {\n \"Key\": 18000000000000000001,\n \"Value\":
8\n }\n]"
floatKeys:
isCreated: 1
data: "[\n {\n \"Key\": 123.625,\n \"Value\": 9\n }\n]"
doubleKeys:
isCreated: 1
data: "[\n {\n \"Key\": -98765.5,\n \"Value\": 10\n }\n]"
boolKeys:
isCreated: 1
data: "[\n {\n \"Key\": true,\n \"Value\": 11\n }\n]"
stringKeys:
isCreated: 1
data: "{\n \"Alchemy\": 12\n}"
unityObjectReferences: []

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using Alchemy.Inspector;
using UnityEngine;
#if ALCHEMY_SUPPORT_SERIALIZATION
using Alchemy.Serialization;
#endif

namespace Alchemy.Tests.EditorUI
{
#if ALCHEMY_SUPPORT_SERIALIZATION
[AlchemySerialize]
#endif
[DocumentationSample]
public partial class DictionarySerializationTest : MonoBehaviour
{
#if ALCHEMY_SUPPORT_SERIALIZATION
[HorizontalGroup("8-bit")]
[AlchemySerializeField, NonSerialized]
public Dictionary<sbyte, int> sbyteKeys = new() { [(sbyte)-101] = 1 };

[HorizontalGroup("8-bit")]
[AlchemySerializeField, NonSerialized]
public Dictionary<byte, int> byteKeys = new() { [(byte)251] = 2 };

[HorizontalGroup("16-bit")]
[AlchemySerializeField, NonSerialized]
public Dictionary<short, int> shortKeys = new() { [(short)-30001] = 3 };

[HorizontalGroup("16-bit")]
[AlchemySerializeField, NonSerialized]
public Dictionary<ushort, int> ushortKeys = new() { [(ushort)60001] = 4 };

[HorizontalGroup("32-bit")]
[AlchemySerializeField, NonSerialized]
public Dictionary<int, int> intKeys = new() { [-2000000001] = 5 };

[HorizontalGroup("32-bit")]
[AlchemySerializeField, NonSerialized]
public Dictionary<uint, int> uintKeys = new() { [4000000001u] = 6 };

[HorizontalGroup("64-bit")]
[AlchemySerializeField, NonSerialized]
public Dictionary<long, int> longKeys = new() { [-900000000000000001L] = 7 };

[HorizontalGroup("64-bit")]
[AlchemySerializeField, NonSerialized]
public Dictionary<ulong, int> ulongKeys = new() { [18000000000000000001UL] = 8 };

[HorizontalGroup("Floating Point")]
[AlchemySerializeField, NonSerialized]
public Dictionary<float, int> floatKeys = new() { [123.625f] = 9 };

[HorizontalGroup("Floating Point")]
[AlchemySerializeField, NonSerialized]
public Dictionary<double, int> doubleKeys = new() { [-98765.5d] = 10 };

[HorizontalGroup("Other")]
[AlchemySerializeField, NonSerialized]
public Dictionary<bool, int> boolKeys = new() { [true] = 11 };

[HorizontalGroup("Other")]
[AlchemySerializeField, NonSerialized]
public Dictionary<string, int> stringKeys = new() { ["Alchemy"] = 12 };
#endif
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Alchemy.Tests.EditorUI.Editor",
"rootNamespace": "Alchemy.Tests.EditorUI.Editor",
"name": "Alchemy.Tests.EditorUI.EditMode",
"rootNamespace": "Alchemy.Tests.EditorUI.EditMode",
"references": [
"GUID:27619889b8ba8c24980f49ee34dbb44a",
"GUID:0acc523941302664db1f4e527237feb3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using UnityEngine;
using UnityEngine.UIElements;

namespace Alchemy.Tests.EditorUI.Editor
namespace Alchemy.Tests.EditorUI.EditMode
{
public sealed class DocumentationEditorWindow : AlchemyEditorWindow
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using UnityEngine;
using UnityEngine.UIElements;

namespace Alchemy.Tests.EditorUI.Editor
namespace Alchemy.Tests.EditorUI.EditMode
{
public class DocumentationEditorSamplesTest
{
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "Alchemy.Tests.EditorUI.PlayModeInEditor",
"rootNamespace": "Alchemy.Tests.EditorUI.PlayModeInEditor",
"references": [
"GUID:27619889b8ba8c24980f49ee34dbb44a",
"GUID:0acc523941302664db1f4e527237feb3",
"GUID:88be65f96b86746888c927a5c8ff3534",
"GUID:9b64a2fc1d4b46d2bb1c83d6bc7287ff",
"GUID:5fd453cd0d182422093c4a764fd5eadb"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [
{
"name": "com.unity.serialization",
"expression": "",
"define": "ALCHEMY_SUPPORT_SERIALIZATION"
}
],
"noEngineReferences": false
}
Loading