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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All package updates & migration steps will be listed in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [4.4.0] - 2025-03-11
### Added
- Support for circular references of structs if using a `IReadOnlyList`
### Changed
- The "Regenerate Code" menu item opens the external code gen project if available to avoid confusion.

## [4.3.2] - 2025-01-24
- Disable the Unity LTS2020 property drawer recursive property crash workaround. It appears to work in LTS2022.

Expand Down
2 changes: 2 additions & 0 deletions Editor/Common/EditorParameterConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public static class CodeGeneration
// external codegen project
public static string ExternalProjectDir =>
Path.Combine(new[] { SanitizedDataPath(), "..", "ParametersCodeGen" });
public static string ExternalProjectSolutionPath =>
Path.Combine(new[] { ExternalProjectDir, "Solutions", "CodeGen.sln" });

// assembly infos
public static string AssemblyInfoPath => Path.Combine(new[] { RootDir, AssemblyInfo.FileName });
Expand Down
8 changes: 5 additions & 3 deletions Editor/Common/Models/ParameterStruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ void DFS(Type t)
{
var propertyInfo = propertyInfos[j];

var structType = AttemptToGetStructReference(propertyInfo);
// C# allows circular references in structs if a list is used (not direct field)
const bool includeLists = false;
var structType = AttemptToGetStructReference(propertyInfo, includeLists);
if (structType == null)
continue;
errorString = CheckStructCircularReferences(structType, path);
Expand All @@ -94,11 +96,11 @@ void DFS(Type t)
return errorString;
}

private Type AttemptToGetStructReference(PropertyInfo propertyInfo)
private Type AttemptToGetStructReference(PropertyInfo propertyInfo, bool includeLists)
{
if (ParameterStructReferencePropertyType.IsReferenceType(propertyInfo, out Type genericType))
return genericType;
if (ParameterStructReferenceListPropertyType.IsListReferenceType(propertyInfo, out genericType))
if (includeLists && ParameterStructReferenceListPropertyType.IsListReferenceType(propertyInfo, out genericType))
return genericType;
return null;
}
Expand Down
13 changes: 12 additions & 1 deletion Editor/Editor/ParametersWindow.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.IO;
using PocketGems.Parameters.CodeGeneration.Operation.Editor;
using PocketGems.Parameters.Common.Editor;
Expand All @@ -8,6 +9,7 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
using Object = UnityEngine.Object;

namespace PocketGems.Parameters.Editor.Editor
{
Expand All @@ -29,7 +31,16 @@ public static void GenerateData()
[MenuItem(MenuItemConstants.RegenerateCodePath, false, MenuItemConstants.RegenerateCodePriority)]
public static void GenerateCode()
{
EditorParameterDataManager.GenerateCodeFiles(GenerateCodeType.Generate, GenerateDataType.All);
bool isUsingExternalCodeGeneration = Directory.Exists(EditorParameterConstants.CodeGeneration.ExternalProjectDir);
if (isUsingExternalCodeGeneration)
{
EditorUtility.DisplayDialog("Code Generation", "Please use the external code generation project that will open in your IDE.", "Okay");
Application.OpenURL(new Uri(Path.GetFullPath(EditorParameterConstants.CodeGeneration.ExternalProjectSolutionPath)).AbsoluteUri);
}
else
{
EditorParameterDataManager.GenerateCodeFiles(GenerateCodeType.Generate, GenerateDataType.All);
}
}

[MenuItem(MenuItemConstants.ConfigPanelPath, false, MenuItemConstants.ConfigPanelPriority)]
Expand Down
36 changes: 18 additions & 18 deletions Tests/Editor/Common/Models/ParameterStructTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,29 @@ public void InvalidInterface(Type interfaceType)
}

[Test]
public void ValidWithNoCircularReferences()
[TestCase(typeof(ICircularAStruct))] // references B
[TestCase(typeof(ICircularBStruct))] // references A
[TestCase(typeof(ICircularCStruct))] // subclass of B
[TestCase(typeof(ICircularDStruct))] // references D (self)

[TestCase(typeof(ICircularEStruct))] // reference F
[TestCase(typeof(ICircularFStruct))] // reference G
[TestCase(typeof(ICircularGStruct))] // reference E
public void InvalidWithCircularReferences(Type interfaceType)
{
var parameterStruct = new ParameterStruct(typeof(IReferenceStructStruct));
Assert.IsTrue(parameterStruct.Validate(out IReadOnlyList<string> errors));
Assert.IsEmpty(errors);
AssertInvalidInterface(new ParameterStruct(interfaceType));
}

[Test]
[TestCase(typeof(ICircularAStruct))]
[TestCase(typeof(ICircularBStruct))]
[TestCase(typeof(ICircularCStruct))]
[TestCase(typeof(ICircularDStruct))]
[TestCase(typeof(ICircularEStruct))]
[TestCase(typeof(ICircularFStruct))]
[TestCase(typeof(ICircularGStruct))]
[TestCase(typeof(ICircularHStruct))]
[TestCase(typeof(ICircularIStruct))]
[TestCase(typeof(ICircularJStruct))]
[TestCase(typeof(ICircularKStruct))]
[TestCase(typeof(ICircularAStruct))]
public void InvalidWithCircularReferences(Type interfaceType)
[TestCase(typeof(IReferenceStructStruct))]
[TestCase(typeof(ICircularIStruct))] // references J with list
[TestCase(typeof(ICircularJStruct))] // references I with list
[TestCase(typeof(ICircularKStruct))] // references K (self) with list
public void ValidListReferences(Type interfaceType)
{
AssertInvalidInterface(new ParameterStruct(interfaceType));
var parameterStruct = new ParameterStruct(interfaceType);
Assert.IsTrue(parameterStruct.Validate(out IReadOnlyList<string> errors));
Assert.IsEmpty(errors);
}
}
}
40 changes: 17 additions & 23 deletions Tests/Editor/Common/Models/TestCode/TestStructs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,55 +123,49 @@ public interface ICircularBStruct : IBaseStruct
ParameterStructReference<ICircularAStruct> Circular { get; }
}

// circular reference in list
public interface ICircularCStruct : IBaseStruct
// circular reference in super class references
public interface ICircularCStruct : ICircularBStruct
{
IReadOnlyList<ParameterStructReference<ICircularAStruct>> Circular { get; }
}

// circular reference in super class references
public interface ICircularDStruct : ICircularBStruct
// circular reference between self (direct reference)
public interface ICircularDStruct : IBaseStruct
{
ParameterStructReference<ICircularDStruct> Circular { get; }
}

// circular reference between list
// deeper circular reference
public interface ICircularEStruct : IBaseStruct
{
IReadOnlyList<ParameterStructReference<ICircularFStruct>> Circular { get; }
ParameterStructReference<ICircularFStruct> Circular { get; }
}

// circular reference between list
// deeper circular reference
public interface ICircularFStruct : IBaseStruct
{
IReadOnlyList<ParameterStructReference<ICircularEStruct>> Circular { get; }
}

// circular reference between self (direct reference)
public interface ICircularGStruct : IBaseStruct
{
ParameterStructReference<ICircularGStruct> Circular { get; }
}

// circular reference between self (list reference)
public interface ICircularHStruct : IBaseStruct
// deeper circular reference
public interface ICircularGStruct : IBaseStruct
{
IReadOnlyList<ParameterStructReference<ICircularHStruct>> Circular { get; }
ParameterStructReference<ICircularEStruct> Circular { get; }
}

// deeper circular reference
// circular reference between list
public interface ICircularIStruct : IBaseStruct
{
ParameterStructReference<ICircularJStruct> Circular { get; }
IReadOnlyList<ParameterStructReference<ICircularJStruct>> Circular { get; }
}

// deeper circular reference
// circular reference between list
public interface ICircularJStruct : IBaseStruct
{
IReadOnlyList<ParameterStructReference<ICircularKStruct>> Circular { get; }
IReadOnlyList<ParameterStructReference<ICircularIStruct>> Circular { get; }
}

// deeper circular reference
// circular reference between self (list reference)
public interface ICircularKStruct : IBaseStruct
{
ParameterStructReference<ICircularIStruct> Circular { get; }
IReadOnlyList<ParameterStructReference<ICircularKStruct>> Circular { get; }
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "com.pocketgems.scriptableobject.flatbuffer",
"version": "4.3.2",
"version": "4.4.0",
"displayName": "Scriptable Object - FlatBuffer",
"description": "Seamless syncing between Scriptable Objects and CSVs. Scriptable Object data built to Google FlatBuffers for optimal runtime loading & access.",
"unity": "2021.3",
Expand Down
Loading