Compare commits

..

75 Commits

Author SHA1 Message Date
github-actions[bot] 362b9add50 feat: Update package.json to 1.6.0 2024-10-27 07:29:43 +00:00
Makihiro 533b4e3f7f Merge pull request #75 from mackysoft/feature/support-contravariance
Support contravariance/covariance
2024-10-27 16:28:44 +09:00
Makihiro 56d0834413 Merge pull request #76 from mackysoft/fix/foldout-layout
Fix foldout layout between Unity versions.
2024-10-27 16:27:27 +09:00
Makihiro c850467b6b Fix foldout layout between Unity versions. 2024-10-27 16:23:50 +09:00
Makihiro a3597f28e0 Merge branch 'main' into feature/support-contravariance 2024-10-27 16:02:43 +09:00
Makihiro 0bbb716864 Fix error 2024-10-27 15:57:50 +09:00
Makihiro edbbe60a6b Update TypeSearch.cs 2024-10-27 15:55:21 +09:00
Makihiro 5ee76f7a92 Update Example.unity 2024-10-27 14:57:26 +09:00
Makihiro 25350f7036 Implement TypeSearch with generics 2024-10-27 14:57:23 +09:00
Makihiro 105f461ba8 Update generics example 2024-10-27 14:56:48 +09:00
Makihiro 44a84ce266 Update feature-request.yaml 2024-10-27 00:28:37 +09:00
Makihiro 343e2d1d54 Update improvement-request.yaml 2024-10-27 00:28:23 +09:00
github-actions[bot] 3386bbbb93 feat: Update package.json to 1.5.0 2024-10-26 15:03:50 +00:00
Makihiro 7ae59bfab7 Add Example_Contravariance 2024-10-27 00:01:16 +09:00
Makihiro 522393cd91 Update Example.cs 2024-10-26 23:44:24 +09:00
Makihiro e61a077f9c Merge branch 'main' of https://github.com/mackysoft/Unity-SerializeReferenceExtensions 2024-10-26 23:41:15 +09:00
Makihiro 2dfbdc0405 Update release.yaml 2024-10-26 23:40:18 +09:00
Makihiro 60adb3e3d3 Merge pull request #74 from mackysoft/feature/use-tostring-as-label
Implement SubclassSelectorAttribute.UseToStringAsLabel
2024-10-26 23:35:48 +09:00
Makihiro 0b79cd7e40 Implement SubclassSelectorAttribute.UseToStringAsLabel 2024-10-26 23:31:00 +09:00
Makihiro d9bc19329f Merge pull request #73 from mackysoft/fix/remove-directive-2019-3
Remove UNITY_2019_3_OR_NEWER directive
2024-10-26 21:33:19 +09:00
Makihiro 6d39db142a Merge branch 'main' into fix/remove-directive-2019-3 2024-10-26 21:28:35 +09:00
Makihiro 97d028ef2a Remove UNITY_2019_3_OR_NEWER directive 2024-10-26 21:27:40 +09:00
Makihiro 9df6eae13c Merge pull request #67 from bulleador/patch-1
fix: foldout arrow rendered out of the inspector in 2022.3 and newer
2024-10-26 21:10:03 +09:00
Makihiro 8f4e361790 Merge pull request #72 from mackysoft/feature/hide-in-type-menu
Feature/hide in type menu
2024-10-26 20:13:10 +09:00
Makihiro 83b67afcc2 Update package.yaml 2024-10-26 20:06:33 +09:00
Makihiro 4cac61d3ed Add HideInTypeMenu example 2024-10-26 20:02:48 +09:00
Makihiro 6269f7f67a Add TypeMenuUtility.GetTypes method 2024-10-26 20:02:37 +09:00
Makihiro 63d2d94953 Add HideInTypeMenuAttribute 2024-10-26 20:01:51 +09:00
Bullet 71fa059b0c fix: foldout arrow rendered out of the inspector in 2022.3 and newer 2024-09-07 15:29:21 +02:00
Makihiro b7d76fb0c5 Update README.md 2024-08-05 18:49:05 +09:00
github-actions[bot] 69943b46c8 feat: Update package.json to 1.4.0 2024-08-03 16:56:21 +00:00
Makihiro 66fc5ae911 Merge pull request #61 from mackysoft/feature/support-nested-private
SubclassSelector now support nested private type
2024-08-04 01:37:48 +09:00
Makihiro 1757747985 SubclassSelector now support nested private type 2024-08-04 01:37:09 +09:00
github-actions[bot] 69f6e31cf1 feat: Update package.json to 1.3.1 2024-04-01 07:34:45 +00:00
Makihiro 3ffef8d1b2 Update packages 2024-04-01 16:33:44 +09:00
Makihiro a9763b033d Fix foldout layout on Unity 2022.2 or newer 2024-04-01 16:32:53 +09:00
Makihiro 2b40c3d26e Merge pull request #56 from theo-rapidfire/fix/use-type-cache
Performance improvement: Use TypeCache instead of manual type iteration
2024-04-01 16:02:36 +09:00
theo-rapidfire f7c1017567 Use TypeCache instead of manual type iteration
fix/use-type-cache
2024-03-28 13:39:48 +01:00
Makihiro 301cb4b12c Update README.md 2024-02-18 04:00:28 +09:00
Makihiro fe02e0fd1e Update text editor packages 2024-02-18 03:35:49 +09:00
github-actions[bot] 05efde5001 feat: Update package.json to 1.3.0 2024-02-17 18:07:18 +00:00
Makihiro f275c468ec Merge pull request #55 from mackysoft/feature/reset-reference
Implement new instance context menu
2024-02-18 03:06:43 +09:00
Makihiro c141acf129 Rename to ManagedReferenceContextualPropertyMenu 2024-02-18 03:03:53 +09:00
Makihiro fdc0a286c8 Implement new instance menu 2024-02-18 03:02:41 +09:00
Makihiro e5627b1caf Merge pull request #54 from mackysoft/fix/dropdown-overlap
Fix dropdown overlap in Unity 2023.2
2024-02-18 02:51:05 +09:00
Makihiro 5f54c254f3 Fix foldout layout 2024-02-18 02:43:01 +09:00
Makihiro b8c11e7836 Create SerializedPropertyExtensions and move method 2024-02-18 02:39:33 +09:00
Makihiro f656cd0f12 Add GetChildProperties 2024-02-18 02:38:00 +09:00
Makihiro f69bfc6773 optimize null check 2024-02-18 02:35:23 +09:00
github-actions[bot] 7f424c0f97 feat: Update package.json to 1.2.2 2024-02-16 12:59:32 +00:00
Makihiro 2934eea84e Merge pull request #52 from mackysoft/fix/nullreference-when-fromjson
Fixed a bug when trying to deserialize a null type with FromJson.
2024-02-16 21:58:54 +09:00
Makihiro f781ad7373 Fixed a bug when trying to deserialize a null type with FromJson. 2024-02-16 21:58:38 +09:00
Makihiro e5a5157b3c Merge pull request #48 from JohannesDeml/bugfix/propertydrawer-allow-inheritance
Add logic to check for inherited PropertyDrawers from base classes and interfaces
2024-02-16 20:53:46 +09:00
Makihiro 69830f3583 Merge pull request #49 from JohannesDeml/bugfix/avoid-label-overlap
Fix label overlapping button
2024-02-16 20:50:55 +09:00
Johannes Deml c9b5193e51 Fix use prefixLabel position right away 2024-02-07 19:31:33 +01:00
Johannes Deml a8bcece352 Fix label overlapping button
By drawing the label first we avoid the overlap. By drawing just the label without the foldout we need to work around a unity problem with indentation and apply that ourselves. The foldout property will then be rendered without gui content
2024-01-17 14:40:52 +01:00
Johannes Deml 70f2cdaf16 Add logic to check for inherited PropertyDrawers from base classes and interfaces
This way an inherited drawer will be used if it exists, which might not be too uncommon in the case of SerializeReference fields
2024-01-17 13:27:49 +01:00
Makihiro 97c4e632bc Update README.md 2024-01-10 16:09:00 +09:00
github-actions[bot] 93d7e13f62 feat: Update package.json to 1.2.1 2024-01-10 07:02:25 +00:00
Makihiro f522e0f285 Merge pull request #47 from mackysoft/fix/compatibility-less-than-2021-3
Fix compatibility for less than Unity 2021.3
2024-01-10 16:01:46 +09:00
Makihiro d061f748b8 Fix compatibility for less than Unity 2021.3 2024-01-10 15:58:31 +09:00
Makihiro afb3089943 Update README.md 2023-12-31 18:56:57 +09:00
github-actions[bot] d2d5c8ed52 feat: Update package.json to 1.2.0 2023-12-31 09:27:46 +00:00
Makihiro 2455229944 Update release.yaml 2023-12-31 18:27:09 +09:00
Makihiro 6ae47efa1d Update package.json 2023-12-31 18:24:42 +09:00
Makihiro 343d930155 Merge pull request #42 from mackysoft/feature/copy-paste-property
Implement copy and paste property
2023-12-31 17:44:18 +09:00
Makihiro 1e52b89dd2 Merge pull request #43 from mackysoft/update-release-workflow
Update release.yaml
2023-12-31 17:44:04 +09:00
Makihiro ba83546f0a Update release.yaml 2023-12-31 17:43:53 +09:00
Makihiro 15a627bd48 Add CopyAndPasteProperty 2023-12-31 17:39:48 +09:00
Makihiro e6f57ed763 Merge pull request #41 from mackysoft/feature/new-object-from-json
Restore values from json on create new managed reference
2023-12-31 16:59:03 +09:00
Makihiro 59da3868b1 Update package.yaml 2023-12-31 16:55:44 +09:00
Makihiro 65b0076c95 Update package.yaml 2023-12-31 16:46:11 +09:00
Makihiro 360c800b25 Revert "Update Unity to 2021.3.32f1"
This reverts commit 5d43ced8cc.
2023-12-31 16:03:32 +09:00
Makihiro cdbc2daf21 Restore values from json on create new managed reference 2023-12-31 16:00:13 +09:00
Makihiro 5d43ced8cc Update Unity to 2021.3.32f1 2023-12-31 15:47:43 +09:00
29 changed files with 738 additions and 127 deletions
+1 -1
View File
@@ -12,6 +12,6 @@ body:
- type: textarea - type: textarea
id: feature-description id: feature-description
attributes: attributes:
label: Feature destription label: Feature description
validations: validations:
required: true required: true
@@ -12,6 +12,6 @@ body:
- type: textarea - type: textarea
id: improvement-description id: improvement-description
attributes: attributes:
label: Improvement destription label: Improvement description
validations: validations:
required: true required: true
+8 -4
View File
@@ -14,7 +14,7 @@ jobs:
steps: steps:
# Checkout # Checkout
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v2 uses: actions/checkout@v4
with: with:
lfs: true lfs: true
@@ -28,14 +28,18 @@ jobs:
# Build # Build
- name: Build .unitypackage - name: Build .unitypackage
uses: game-ci/unity-builder@v2 uses: game-ci/unity-builder@v4
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
with: with:
unityVersion: 2020.3.8f1 unityVersion: 2021.3.29f1
buildMethod: MackySoft.PackageTools.Editor.UnityPackageExporter.Export buildMethod: MackySoft.PackageTools.Editor.UnityPackageExporter.Export
# Upload # Upload
- name: Upload .unitypackage - name: Upload .unitypackage
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v4
with: with:
name: Unity Package name: Unity Package
path: Build path: Build
+11 -9
View File
@@ -18,7 +18,7 @@ jobs:
outputs: outputs:
sha: ${{ steps.commit.outputs.sha }} sha: ${{ steps.commit.outputs.sha }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Output package.json (Before) - name: Output package.json (Before)
run: cat ${{ env.TARGET_FILE}} run: cat ${{ env.TARGET_FILE}}
@@ -61,22 +61,24 @@ jobs:
needs: [update-packagejson] needs: [update-packagejson]
strategy: strategy:
matrix: matrix:
unity: ["2020.3.8f1"] unity: ["2021.3.29f1"]
include: include:
- unityVersion: 2020.3.8f1 - unityVersion: 2021.3.29f1
license: UNITY_LICENSE_2020 license: UNITY_LICENSE
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 15 timeout-minutes: 15
steps: steps:
- run: echo ${{ needs.update-packagejson.outputs.sha }} - run: echo ${{ needs.update-packagejson.outputs.sha }}
- uses: actions/checkout@v2 - uses: actions/checkout@v4
with: with:
ref: ${{ needs.update-packagejson.outputs.sha }} ref: ${{ needs.update-packagejson.outputs.sha }}
- name: Export unitypackage - name: Export unitypackage
uses: game-ci/unity-builder@v2 uses: game-ci/unity-builder@v4
env: env:
UNITY_LICENSE: ${{ secrets[matrix.license] }} UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
with: with:
projectPath: . projectPath: .
unityVersion: ${{ matrix.unityVersion }} unityVersion: ${{ matrix.unityVersion }}
@@ -95,7 +97,7 @@ jobs:
working-directory: . working-directory: .
# Store artifacts. # Store artifacts.
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v4
with: with:
name: SerializeReference-Extensions.unitypackage name: SerializeReference-Extensions.unitypackage
path: ./Build/SerializeReference-Extensions.unitypackage path: ./Build/SerializeReference-Extensions.unitypackage
@@ -117,7 +119,7 @@ jobs:
prerelease: false prerelease: false
# Download(All) Artifacts to current directory # Download(All) Artifacts to current directory
- uses: actions/download-artifact@v2 - uses: actions/download-artifact@v4
# Upload to Releases(unitypackage) # Upload to Releases(unitypackage)
- uses: actions/upload-release-asset@v1 - uses: actions/upload-release-asset@v1
+13 -4
View File
@@ -1,4 +1,3 @@
#if UNITY_2019_3_OR_NEWER
using System.Collections.Generic; using System.Collections.Generic;
using System; using System;
using UnityEditor; using UnityEditor;
@@ -42,6 +41,17 @@ public class Grape : Food
} }
} }
[Serializable]
[HideInTypeMenu]
public class Banana : Food
{
public Banana ()
{
name = "Banana";
kcal = 100f;
}
}
public class Example : MonoBehaviour public class Example : MonoBehaviour
{ {
@@ -60,7 +70,8 @@ public class Example : MonoBehaviour
[SerializeReference, SubclassSelector] [SerializeReference, SubclassSelector]
public Food foodTwo = new Peach(); public Food foodTwo = new Peach();
[SerializeReference, SubclassSelector] // UseToStringAsLabel support on UNITY_2021_3_OR_NEWER
[SerializeReference, SubclassSelector(UseToStringAsLabel = true)]
public Food foodThree = new Grape(); public Food foodThree = new Grape();
[SerializeReference] [SerializeReference]
@@ -116,5 +127,3 @@ public class AppleDrawer : PropertyDrawer
} }
} }
#endif #endif
#endif
+82 -14
View File
@@ -13,7 +13,7 @@ OcclusionCullingSettings:
--- !u!104 &2 --- !u!104 &2
RenderSettings: RenderSettings:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
serializedVersion: 9 serializedVersion: 10
m_Fog: 0 m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3 m_FogMode: 3
@@ -38,13 +38,12 @@ RenderSettings:
m_ReflectionIntensity: 1 m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0} m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0} m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
m_UseRadianceAmbientProbe: 0 m_UseRadianceAmbientProbe: 0
--- !u!157 &3 --- !u!157 &3
LightmapSettings: LightmapSettings:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
serializedVersion: 12 serializedVersion: 12
m_GIWorkflowMode: 1
m_GISettings: m_GISettings:
serializedVersion: 2 serializedVersion: 2
m_BounceScale: 1 m_BounceScale: 1
@@ -67,9 +66,6 @@ LightmapSettings:
m_LightmapParameters: {fileID: 0} m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1 m_LightmapsBakeMode: 1
m_TextureCompression: 1 m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2 m_ReflectionCompression: 2
m_MixedBakeMode: 2 m_MixedBakeMode: 2
m_BakeBackend: 1 m_BakeBackend: 1
@@ -104,7 +100,7 @@ NavMeshSettings:
serializedVersion: 2 serializedVersion: 2
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_BuildSettings: m_BuildSettings:
serializedVersion: 2 serializedVersion: 3
agentTypeID: 0 agentTypeID: 0
agentRadius: 0.5 agentRadius: 0.5
agentHeight: 2 agentHeight: 2
@@ -117,7 +113,7 @@ NavMeshSettings:
cellSize: 0.16666667 cellSize: 0.16666667
manualTileSize: 0 manualTileSize: 0
tileSize: 256 tileSize: 256
accuratePlacement: 0 buildHeightMesh: 0
maxJobWorkers: 0 maxJobWorkers: 0
preserveTilesOutsideBounds: 0 preserveTilesOutsideBounds: 0
debug: debug:
@@ -163,9 +159,17 @@ Camera:
m_projectionMatrixMode: 1 m_projectionMatrixMode: 1
m_GateFitMode: 2 m_GateFitMode: 2
m_FOVAxisMode: 0 m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24} m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0} m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect: m_NormalizedViewPortRect:
serializedVersion: 2 serializedVersion: 2
x: 0 x: 0
@@ -199,13 +203,13 @@ Transform:
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 126803971} m_GameObject: {fileID: 126803971}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 1, z: -10} m_LocalPosition: {x: 0, y: 1, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &586792171 --- !u!1 &586792171
GameObject: GameObject:
@@ -326,13 +330,70 @@ Transform:
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 586792171} m_GameObject: {fileID: 586792171}
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!1 &994260143
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 994260145}
- component: {fileID: 994260144}
m_Layer: 0
m_Name: Example_Generics
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &994260144
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 994260143}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dff76005e1dfac84287448b12c4b160e, type: 3}
m_Name:
m_EditorClassIdentifier:
contravarianceActions:
- rid: 3354424774140624943
covarianceActions:
- rid: 3354424774140624944
references:
version: 2
RefIds:
- rid: 3354424774140624943
type: {class: DerivedAction1, ns: , asm: Assembly-CSharp}
data:
- rid: 3354424774140624944
type: {class: NetworkActorAction1, ns: , asm: Assembly-CSharp}
data:
--- !u!4 &994260145
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 994260143}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1127138992 --- !u!1 &1127138992
GameObject: GameObject:
@@ -359,9 +420,8 @@ Light:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1127138992} m_GameObject: {fileID: 1127138992}
m_Enabled: 1 m_Enabled: 1
serializedVersion: 10 serializedVersion: 11
m_Type: 1 m_Type: 1
m_Shape: 0
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
m_Intensity: 1 m_Intensity: 1
m_Range: 10 m_Range: 10
@@ -420,11 +480,19 @@ Transform:
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1127138992} m_GameObject: {fileID: 1127138992}
serializedVersion: 2
m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261}
m_LocalPosition: {x: 0, y: 3, z: 0} m_LocalPosition: {x: 0, y: 3, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: [] m_Children: []
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1660057539 &9223372036854775807
SceneRoots:
m_ObjectHideFlags: 0
m_Roots:
- {fileID: 126803974}
- {fileID: 1127138994}
- {fileID: 586792173}
- {fileID: 994260145}
+93
View File
@@ -0,0 +1,93 @@
using System;
using System.Collections.Generic;
using UnityEngine;
public interface IActor { }
public interface IStandardActor : IActor { }
public interface INetworkActor : IActor { }
public interface IContravarianceAction<in T> where T : IActor {
void DoAction (T actor);
}
public interface ICovarianceAction<out T> where T : IActor
{
T Actor { get; }
}
public interface IActorAction : IContravarianceAction<IActor>, ICovarianceAction<IActor> { }
public interface IStandardActorAction : IContravarianceAction<IStandardActor>, ICovarianceAction<IStandardActor> { }
public interface INetworkActorAction : IContravarianceAction<INetworkActor>, ICovarianceAction<INetworkActor> { }
[Serializable]
public sealed class StandardActorAction : IContravarianceAction<IStandardActor>, ICovarianceAction<IStandardActor>
{
public void DoAction (IStandardActor actor)
{
}
public IStandardActor Actor => null;
}
[Serializable]
public sealed class ActorAction : IContravarianceAction<IActor>, ICovarianceAction<IActor>
{
public void DoAction (IActor actor)
{
}
public IActor Actor => null;
}
[Serializable]
public abstract class BaseAction<T> : IContravarianceAction<T>, ICovarianceAction<T> where T : IActor
{
public void DoAction (T actor) {
}
public T Actor => default;
}
[Serializable]
public sealed class DerivedAction1 : BaseAction<IActor> { }
[Serializable]
public sealed class DerivedAction2 : BaseAction<INetworkActor> { }
[Serializable]
public sealed class DerivedAction3 : BaseAction<IStandardActor> { }
[Serializable]
public sealed class NetworkActorAction1 : INetworkActorAction
{
public void DoAction (INetworkActor actor)
{
}
public INetworkActor Actor => null;
}
[Serializable]
public sealed class NetworkActorAction2 : IContravarianceAction<INetworkActor>, ICovarianceAction<INetworkActor>
{
public void DoAction (INetworkActor actor)
{
}
public INetworkActor Actor => null;
}
[Serializable]
public sealed class NetworkActorAction3 : IContravarianceAction<IActor>, ICovarianceAction<IActor>
{
public void DoAction (IActor actor)
{
}
public IActor Actor => null;
}
public class Example_Generics : MonoBehaviour
{
[SerializeReference, SubclassSelector]
public List<IContravarianceAction<INetworkActor>> contravarianceActions = new List<IContravarianceAction<INetworkActor>>();
[SerializeReference, SubclassSelector]
public List<ICovarianceAction<INetworkActor>> covarianceActions = new List<ICovarianceAction<INetworkActor>>();
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dff76005e1dfac84287448b12c4b160e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,5 +1,4 @@
#if UNITY_2019_3_OR_NEWER using System;
using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
@@ -138,4 +137,3 @@ namespace MackySoft.SerializeReferenceExtensions.Editor {
} }
} }
#endif
@@ -12,9 +12,7 @@
"overrideReferences": false, "overrideReferences": false,
"precompiledReferences": [], "precompiledReferences": [],
"autoReferenced": true, "autoReferenced": true,
"defineConstraints": [ "defineConstraints": [],
"UNITY_2019_3_OR_NEWER"
],
"versionDefines": [], "versionDefines": [],
"noEngineReferences": false "noEngineReferences": false
} }
@@ -0,0 +1,107 @@
// NOTE: managedReferenceValue getter is available only in Unity 2021.3 or later.
#if UNITY_2021_3_OR_NEWER
using System;
using UnityEditor;
using UnityEngine;
namespace MackySoft.SerializeReferenceExtensions.Editor
{
public static class ManagedReferenceContextualPropertyMenu
{
const string kCopiedPropertyPathKey = "SerializeReferenceExtensions.CopiedPropertyPath";
const string kClipboardKey = "SerializeReferenceExtensions.CopyAndPasteProperty";
static readonly GUIContent kPasteContent = new GUIContent("Paste Property");
static readonly GUIContent kNewInstanceContent = new GUIContent("New Instance");
static readonly GUIContent kResetAndNewInstanceContent = new GUIContent("Reset and New Instance");
[InitializeOnLoadMethod]
static void Initialize ()
{
EditorApplication.contextualPropertyMenu += OnContextualPropertyMenu;
}
static void OnContextualPropertyMenu (GenericMenu menu, SerializedProperty property)
{
if (property.propertyType == SerializedPropertyType.ManagedReference)
{
// NOTE: When the callback function is called, the SerializedProperty is rewritten to the property that was being moused over at the time,
// so a new SerializedProperty instance must be created.
SerializedProperty clonedProperty = property.Copy();
menu.AddItem(new GUIContent($"Copy \"{property.propertyPath}\" property"), false, Copy, clonedProperty);
string copiedPropertyPath = SessionState.GetString(kCopiedPropertyPathKey, string.Empty);
if (!string.IsNullOrEmpty(copiedPropertyPath))
{
menu.AddItem(new GUIContent($"Paste \"{copiedPropertyPath}\" property"), false, Paste, clonedProperty);
}
else
{
menu.AddDisabledItem(kPasteContent);
}
menu.AddSeparator("");
bool hasInstance = clonedProperty.managedReferenceValue != null;
if (hasInstance)
{
menu.AddItem(kNewInstanceContent, false, NewInstance, clonedProperty);
menu.AddItem(kResetAndNewInstanceContent, false, ResetAndNewInstance, clonedProperty);
}
else
{
menu.AddDisabledItem(kNewInstanceContent);
menu.AddDisabledItem(kResetAndNewInstanceContent);
}
}
}
static void Copy (object customData)
{
SerializedProperty property = (SerializedProperty)customData;
string json = JsonUtility.ToJson(property.managedReferenceValue);
SessionState.SetString(kCopiedPropertyPathKey, property.propertyPath);
SessionState.SetString(kClipboardKey, json);
}
static void Paste (object customData)
{
SerializedProperty property = (SerializedProperty)customData;
string json = SessionState.GetString(kClipboardKey, string.Empty);
if (string.IsNullOrEmpty(json))
{
return;
}
Undo.RecordObject(property.serializedObject.targetObject, "Paste Property");
JsonUtility.FromJsonOverwrite(json, property.managedReferenceValue);
property.serializedObject.ApplyModifiedProperties();
}
static void NewInstance (object customData)
{
SerializedProperty property = (SerializedProperty)customData;
string json = JsonUtility.ToJson(property.managedReferenceValue);
Undo.RecordObject(property.serializedObject.targetObject, "New Instance");
property.managedReferenceValue = JsonUtility.FromJson(json, property.managedReferenceValue.GetType());
property.serializedObject.ApplyModifiedProperties();
Debug.Log($"Create new instance of \"{property.propertyPath}\".");
}
static void ResetAndNewInstance (object customData)
{
SerializedProperty property = (SerializedProperty)customData;
Undo.RecordObject(property.serializedObject.targetObject, "Reset and New Instance");
property.managedReferenceValue = Activator.CreateInstance(property.managedReferenceValue.GetType());
property.serializedObject.ApplyModifiedProperties();
Debug.Log($"Reset property and created new instance of \"{property.propertyPath}\".");
}
}
}
#endif
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 734d3eb8da4785b49919aea6db62d877
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,15 +1,34 @@
#if UNITY_2019_3_OR_NEWER using System;
using System;
using System.Reflection; using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEngine;
namespace MackySoft.SerializeReferenceExtensions.Editor
{
namespace MackySoft.SerializeReferenceExtensions.Editor {
public static class ManagedReferenceUtility { public static class ManagedReferenceUtility {
public static object SetManagedReference (this SerializedProperty property,Type type) { public static object SetManagedReference (this SerializedProperty property,Type type) {
object obj = (type != null) ? Activator.CreateInstance(type) : null; object result = null;
property.managedReferenceValue = obj;
return obj; #if UNITY_2021_3_OR_NEWER
// NOTE: managedReferenceValue getter is available only in Unity 2021.3 or later.
if ((type != null) && (property.managedReferenceValue != null))
{
// Restore an previous values from json.
string json = JsonUtility.ToJson(property.managedReferenceValue);
result = JsonUtility.FromJson(json, type);
}
#endif
if (result == null)
{
result = (type != null) ? Activator.CreateInstance(type) : null;
}
property.managedReferenceValue = result;
return result;
} }
public static Type GetType (string typeName) { public static Type GetType (string typeName) {
@@ -25,4 +44,3 @@ namespace MackySoft.SerializeReferenceExtensions.Editor {
} }
} }
#endif
@@ -1,5 +1,4 @@
#if UNITY_2019_3_OR_NEWER using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEditor; using UnityEditor;
using System.Reflection; using System.Reflection;
@@ -25,9 +24,10 @@ namespace MackySoft.SerializeReferenceExtensions.Editor
static Type GetCustomPropertyDrawerType (Type type) static Type GetCustomPropertyDrawerType (Type type)
{ {
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) Type[] interfaceTypes = type.GetInterfaces();
{
foreach (Type drawerType in assembly.GetTypes()) var types = TypeCache.GetTypesWithAttribute<CustomPropertyDrawer>();
foreach (Type drawerType in types)
{ {
var customPropertyDrawerAttributes = drawerType.GetCustomAttributes(typeof(CustomPropertyDrawer), true); var customPropertyDrawerAttributes = drawerType.GetCustomAttributes(typeof(CustomPropertyDrawer), true);
foreach (CustomPropertyDrawer customPropertyDrawer in customPropertyDrawerAttributes) foreach (CustomPropertyDrawer customPropertyDrawer in customPropertyDrawerAttributes)
@@ -36,10 +36,39 @@ namespace MackySoft.SerializeReferenceExtensions.Editor
if (field != null) if (field != null)
{ {
var fieldType = field.GetValue(customPropertyDrawer) as Type; var fieldType = field.GetValue(customPropertyDrawer) as Type;
if (fieldType != null && fieldType == type) if (fieldType != null)
{
if (fieldType == type)
{ {
return drawerType; return drawerType;
} }
// If the property drawer also allows for being applied to child classes, check if they match
var useForChildrenField = customPropertyDrawer.GetType().GetField("m_UseForChildren", BindingFlags.NonPublic | BindingFlags.Instance);
if (useForChildrenField != null)
{
object useForChildrenValue = useForChildrenField.GetValue(customPropertyDrawer);
if (useForChildrenValue is bool && (bool)useForChildrenValue)
{
// Check interfaces
if (Array.Exists(interfaceTypes, interfaceType => interfaceType == fieldType))
{
return drawerType;
}
// Check derived types
Type baseType = type.BaseType;
while (baseType != null)
{
if (baseType == fieldType)
{
return drawerType;
}
baseType = baseType.BaseType;
}
}
}
} }
} }
} }
@@ -49,4 +78,3 @@ namespace MackySoft.SerializeReferenceExtensions.Editor
} }
} }
#endif
@@ -0,0 +1,29 @@
using System.Collections.Generic;
using UnityEditor;
namespace MackySoft.SerializeReferenceExtensions.Editor
{
public static class SerializedPropertyExtensions
{
public static IEnumerable<SerializedProperty> GetChildProperties (this SerializedProperty parent, int depth = 1)
{
parent = parent.Copy();
int depthOfParent = parent.depth;
var enumerator = parent.GetEnumerator();
while (enumerator.MoveNext())
{
if (enumerator.Current is not SerializedProperty childProperty)
{
continue;
}
if (childProperty.depth > (depthOfParent + depth))
{
continue;
}
yield return childProperty.Copy();
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b934aeca38cb7a24cabd6047fe0e298a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,5 +1,4 @@
#if UNITY_2019_3_OR_NEWER using System;
using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
@@ -22,7 +21,7 @@ namespace MackySoft.SerializeReferenceExtensions.Editor
} }
const int k_MaxTypePopupLineCount = 13; const int k_MaxTypePopupLineCount = 13;
static readonly Type k_UnityObjectType = typeof(UnityEngine.Object);
static readonly GUIContent k_NullDisplayName = new GUIContent(TypeMenuUtility.k_NullDisplayName); static readonly GUIContent k_NullDisplayName = new GUIContent(TypeMenuUtility.k_NullDisplayName);
static readonly GUIContent k_IsNotManagedReferenceLabel = new GUIContent("The property type is not manage reference."); static readonly GUIContent k_IsNotManagedReferenceLabel = new GUIContent("The property type is not manage reference.");
@@ -31,48 +30,100 @@ namespace MackySoft.SerializeReferenceExtensions.Editor
SerializedProperty m_TargetProperty; SerializedProperty m_TargetProperty;
public override void OnGUI (Rect position,SerializedProperty property,GUIContent label) { public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property); EditorGUI.BeginProperty(position, label, property);
if (property.propertyType == SerializedPropertyType.ManagedReference) { if (property.propertyType == SerializedPropertyType.ManagedReference)
// Draw the subclass selector popup. {
Rect popupPosition = new Rect(position); // Render label first to avoid label overlap for lists
popupPosition.width -= EditorGUIUtility.labelWidth; Rect foldoutLabelRect = new Rect(position);
popupPosition.x += EditorGUIUtility.labelWidth; foldoutLabelRect.height = EditorGUIUtility.singleLineHeight;
popupPosition.height = EditorGUIUtility.singleLineHeight; foldoutLabelRect = EditorGUI.IndentedRect(foldoutLabelRect);
Rect popupPosition = EditorGUI.PrefixLabel(foldoutLabelRect, label);
if (EditorGUI.DropdownButton(popupPosition,GetTypeName(property),FocusType.Keyboard)) { #if UNITY_2021_3_OR_NEWER
// Override the label text with the ToString() of the managed reference.
var subclassSelectorAttribute = (SubclassSelectorAttribute)attribute;
if (subclassSelectorAttribute.UseToStringAsLabel && !property.hasMultipleDifferentValues)
{
object managedReferenceValue = property.managedReferenceValue;
if (managedReferenceValue != null)
{
label.text = managedReferenceValue.ToString();
}
}
#endif
// Draw the subclass selector popup.
if (EditorGUI.DropdownButton(popupPosition, GetTypeName(property), FocusType.Keyboard))
{
TypePopupCache popup = GetTypePopup(property); TypePopupCache popup = GetTypePopup(property);
m_TargetProperty = property; m_TargetProperty = property;
popup.TypePopup.Show(popupPosition); popup.TypePopup.Show(popupPosition);
} }
// Draw the foldout.
if (!string.IsNullOrEmpty(property.managedReferenceFullTypename))
{
Rect foldoutRect = new Rect(position);
foldoutRect.height = EditorGUIUtility.singleLineHeight;
#if UNITY_2022_2_OR_NEWER && !UNITY_6000_0_OR_NEWER
// NOTE: Position x must be adjusted.
// FIXME: Is there a more essential solution...?
// The most promising is UI Toolkit, but it is currently unable to reproduce all of SubclassSelector features. (Complete provision of contextual menu, e.g.)
// 2021.3: No adjustment
// 2022.1: No adjustment
// 2022.2: Adjustment required
// 2022.3: Adjustment required
// 2023.1: Adjustment required
// 2023.2: Adjustment required
// 6000.0: No adjustment
foldoutRect.x -= 12;
#endif
property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, GUIContent.none, true);
}
// Draw property if expanded.
if (property.isExpanded)
{
using (new EditorGUI.IndentLevelScope())
{
// Check if a custom property drawer exists for this type. // Check if a custom property drawer exists for this type.
PropertyDrawer customDrawer = GetCustomPropertyDrawer(property); PropertyDrawer customDrawer = GetCustomPropertyDrawer(property);
if (customDrawer != null) if (customDrawer != null)
{ {
// Draw the property with custom property drawer. // Draw the property with custom property drawer.
Rect foldoutRect = new Rect(position);
foldoutRect.height = EditorGUIUtility.singleLineHeight;
property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, label, true);
if (property.isExpanded)
{
using (new EditorGUI.IndentLevelScope())
{
Rect indentedRect = position; Rect indentedRect = position;
float foldoutDifference = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; float foldoutDifference = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
indentedRect.height = customDrawer.GetPropertyHeight(property, label); indentedRect.height = customDrawer.GetPropertyHeight(property, label);
indentedRect.y += foldoutDifference; indentedRect.y += foldoutDifference;
customDrawer.OnGUI(indentedRect, property, label); customDrawer.OnGUI(indentedRect, property, label);
} }
else
{
// Draw the properties of the child elements.
// NOTE: In the following code, since the foldout layout isn't working properly, I'll iterate through the properties of the child elements myself.
// EditorGUI.PropertyField(position, property, GUIContent.none, true);
Rect childPosition = position;
childPosition.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
foreach (SerializedProperty childProperty in property.GetChildProperties())
{
float height = EditorGUI.GetPropertyHeight(childProperty, new GUIContent(childProperty.displayName, childProperty.tooltip), true);
childPosition.height = height;
EditorGUI.PropertyField(childPosition, childProperty, true);
childPosition.y += height + EditorGUIUtility.standardVerticalSpacing;
}
}
}
} }
} }
else else
{ {
EditorGUI.PropertyField(position, property, label, true);
}
} else {
EditorGUI.LabelField(position, label, k_IsNotManagedReferenceLabel); EditorGUI.LabelField(position, label, k_IsNotManagedReferenceLabel);
} }
@@ -98,13 +149,7 @@ namespace MackySoft.SerializeReferenceExtensions.Editor
Type baseType = ManagedReferenceUtility.GetType(managedReferenceFieldTypename); Type baseType = ManagedReferenceUtility.GetType(managedReferenceFieldTypename);
var popup = new AdvancedTypePopup( var popup = new AdvancedTypePopup(
TypeCache.GetTypesDerivedFrom(baseType).Append(baseType).Where(p => TypeSearch.GetTypes(baseType),
(p.IsPublic || p.IsNestedPublic) &&
!p.IsAbstract &&
!p.IsGenericType &&
!k_UnityObjectType.IsAssignableFrom(p) &&
Attribute.IsDefined(p,typeof(SerializableAttribute))
),
k_MaxTypePopupLineCount, k_MaxTypePopupLineCount,
state state
); );
@@ -115,7 +160,6 @@ namespace MackySoft.SerializeReferenceExtensions.Editor
foreach (var targetObject in m_TargetProperty.serializedObject.targetObjects) { foreach (var targetObject in m_TargetProperty.serializedObject.targetObjects) {
SerializedObject individualObject = new SerializedObject(targetObject); SerializedObject individualObject = new SerializedObject(targetObject);
SerializedProperty individualProperty = individualObject.FindProperty(m_TargetProperty.propertyPath); SerializedProperty individualProperty = individualObject.FindProperty(m_TargetProperty.propertyPath);
object obj = individualProperty.SetManagedReference(type); object obj = individualProperty.SetManagedReference(type);
individualProperty.isExpanded = (obj != null); individualProperty.isExpanded = (obj != null);
@@ -175,4 +219,3 @@ namespace MackySoft.SerializeReferenceExtensions.Editor
} }
} }
#endif
@@ -1,9 +1,10 @@
#if UNITY_2019_3_OR_NEWER using System;
using System;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEditor;
namespace MackySoft.SerializeReferenceExtensions.Editor { namespace MackySoft.SerializeReferenceExtensions.Editor
{
public static class TypeMenuUtility { public static class TypeMenuUtility {
public const string k_NullDisplayName = "<null>"; public const string k_NullDisplayName = "<null>";
@@ -42,4 +43,3 @@ namespace MackySoft.SerializeReferenceExtensions.Editor {
} }
} }
#endif
@@ -0,0 +1,142 @@
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using System.Reflection;
namespace MackySoft.SerializeReferenceExtensions.Editor
{
public static class TypeSearch
{
#if UNITY_2023_2_OR_NEWER
static readonly Dictionary<Type, List<Type>> m_TypeCache = new Dictionary<Type, List<Type>>();
#endif
public static IEnumerable<Type> GetTypes (Type baseType)
{
#if UNITY_2023_2_OR_NEWER
// NOTE: This is a generics solution for Unity 2023.2 and later.
// 2023.2 because SerializeReference supports generic type instances and because the behaviour is stable.
if (baseType.IsGenericType)
{
return GetTypesWithGeneric(baseType);
}
else
{
return GetTypesUsingTypeCache(baseType);
}
#else
return GetTypesUsingTypeCache(baseType);
#endif
}
static IEnumerable<Type> GetTypesUsingTypeCache (Type baseType)
{
return TypeCache.GetTypesDerivedFrom(baseType)
.Append(baseType)
.Where(IsValidType);
}
#if UNITY_2023_2_OR_NEWER
static IEnumerable<Type> GetTypesWithGeneric (Type baseType)
{
if (m_TypeCache.TryGetValue(baseType, out List<Type> result))
{
return result;
}
result = new List<Type>();
Type genericTypeDefinition = null;
Type[] targetTypeArguments = null;
Type[] genericTypeParameters = null;
if (baseType.IsGenericType)
{
genericTypeDefinition = baseType.GetGenericTypeDefinition();
targetTypeArguments = baseType.GetGenericArguments();
genericTypeParameters = genericTypeDefinition.GetGenericArguments();
}
else
{
genericTypeDefinition = baseType;
targetTypeArguments = Type.EmptyTypes;
genericTypeParameters = Type.EmptyTypes;
}
IEnumerable<Type> types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(IsValidType);
foreach (Type type in types)
{
Type[] interfaceTypes = type.GetInterfaces();
foreach (Type interfaceType in interfaceTypes)
{
if (!interfaceType.IsGenericType || interfaceType.GetGenericTypeDefinition() != genericTypeDefinition)
{
continue;
}
Type[] sourceTypeArguments = interfaceType.GetGenericArguments();
bool allParametersMatch = true;
for (int i = 0; i < genericTypeParameters.Length; i++)
{
var variance = genericTypeParameters[i].GenericParameterAttributes & GenericParameterAttributes.VarianceMask;
Type sourceTypeArgument = sourceTypeArguments[i];
Type targetTypeArgument = targetTypeArguments[i];
if (variance == GenericParameterAttributes.Contravariant)
{
if (!sourceTypeArgument.IsAssignableFrom(targetTypeArgument))
{
allParametersMatch = false;
break;
}
}
else if (variance == GenericParameterAttributes.Covariant)
{
if (!targetTypeArgument.IsAssignableFrom(sourceTypeArgument))
{
allParametersMatch = false;
break;
}
}
else
{
if (sourceTypeArgument != targetTypeArgument)
{
allParametersMatch = false;
break;
}
}
}
if (allParametersMatch)
{
result.Add(type);
break;
}
}
}
m_TypeCache.Add(baseType, result);
return result;
}
#endif
static bool IsValidType (Type type)
{
return
(type.IsPublic || type.IsNestedPublic || type.IsNestedPrivate) &&
!type.IsAbstract &&
!type.IsGenericType &&
!typeof(UnityEngine.Object).IsAssignableFrom(type) &&
Attribute.IsDefined(type, typeof(SerializableAttribute)) &&
!Attribute.IsDefined(type, typeof(HideInTypeMenuAttribute));
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5ea24172520aa2646954c1d246e7ba5d
@@ -1,6 +1,4 @@
#if UNITY_2019_3_OR_NEWER using System;
using System;
/// <summary> /// <summary>
/// An attribute that overrides the name of the type displayed in the SubclassSelector popup. /// An attribute that overrides the name of the type displayed in the SubclassSelector popup.
@@ -35,4 +33,3 @@ public sealed class AddTypeMenuAttribute : Attribute {
} }
} }
#endif
@@ -0,0 +1,9 @@
using System;
/// <summary>
/// An attribute that hides the type in the SubclassSelector.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
public sealed class HideInTypeMenuAttribute : Attribute {
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9f48f5d86a108b94a9c26381f5ce678c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -8,9 +8,7 @@
"overrideReferences": false, "overrideReferences": false,
"precompiledReferences": [], "precompiledReferences": [],
"autoReferenced": true, "autoReferenced": true,
"defineConstraints": [ "defineConstraints": [],
"UNITY_2019_3_OR_NEWER"
],
"versionDefines": [], "versionDefines": [],
"noEngineReferences": false "noEngineReferences": false
} }
@@ -1,12 +1,16 @@
#if UNITY_2019_3_OR_NEWER using System;
using System;
using UnityEngine; using UnityEngine;
/// <summary> /// <summary>
/// Attribute to specify the type of the field serialized by the SerializeReference attribute in the inspector. /// Attribute to specify the type of the field serialized by the SerializeReference attribute in the inspector.
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public sealed class SubclassSelectorAttribute : PropertyAttribute { public sealed class SubclassSelectorAttribute : PropertyAttribute
{
#if UNITY_2021_3_OR_NEWER
// NOTE: Use managedReferenceValue getter to invoke instance method in SubclassSelectorDrawer.
public bool UseToStringAsLabel { get; set; }
#endif
} }
#endif
@@ -1,8 +1,9 @@
{ {
"name": "com.mackysoft.serializereference-extensions", "name": "com.mackysoft.serializereference-extensions",
"displayName": "SerializeReference Extensions", "displayName": "SerializeReference Extensions",
"version": "1.1.9", "author": { "name": "MackySoft", "url": "https://github.com/mackysoft" },
"unity": "2019.4", "version": "1.6.0",
"unity": "2021.3",
"description": "Provide popup to specify the type of the field serialized by the [SerializeReference] attribute in the inspector.", "description": "Provide popup to specify the type of the field serialized by the [SerializeReference] attribute in the inspector.",
"keywords": [ "SerializeReference", "Editor" ], "keywords": [ "SerializeReference", "Editor" ],
"license": "MIT", "license": "MIT",
+2 -2
View File
@@ -1,7 +1,7 @@
{ {
"dependencies": { "dependencies": {
"com.unity.ide.rider": "3.0.24", "com.unity.ide.rider": "3.0.28",
"com.unity.ide.visualstudio": "2.0.18", "com.unity.ide.visualstudio": "2.0.22",
"com.unity.ide.vscode": "1.2.5", "com.unity.ide.vscode": "1.2.5",
"com.unity.test-framework": "1.1.33", "com.unity.test-framework": "1.1.33",
"com.unity.modules.ai": "1.0.0", "com.unity.modules.ai": "1.0.0",
+2 -2
View File
@@ -8,7 +8,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.ide.rider": { "com.unity.ide.rider": {
"version": "3.0.24", "version": "3.0.28",
"depth": 0, "depth": 0,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
@@ -17,7 +17,7 @@
"url": "https://packages.unity.com" "url": "https://packages.unity.com"
}, },
"com.unity.ide.visualstudio": { "com.unity.ide.visualstudio": {
"version": "2.0.18", "version": "2.0.22",
"depth": 0, "depth": 0,
"source": "registry", "source": "registry",
"dependencies": { "dependencies": {
+19 -2
View File
@@ -15,9 +15,19 @@ The `SubclassSelector` attribute allows you to easily set subclasses of those ab
- Easily set subclass by popup. - Easily set subclass by popup.
- **[New]** Type finding by fuzzy finder. - **[New]** Type finding by fuzzy finder.
- **[New]** Override the type name and path by the `AddTypeMenu` attribute. - **[New]** Override the type name and path by the `AddTypeMenu` attribute.
- **[New]** Available `CustomPropertyDrawer` for subclasses.
- **[New]** Restore values of previous object from JSON when subclass is changed. (required Unity 2021.3 or later)
- **[New]** Copy & Paste the subclass properties. (required Unity 2021.3 or later)
- **[New]** Clear & reset the subclass properties. (required Unity 2021.3 or later)
> See below for the reason for the limitation of versions less than Unity 2021.3.
>
> https://blog.unity.com/engine-platform/serializereference-improvements-in-unity-2021-lts
## 📥 Installation ## 📥 Installation
#### Install via `.unitypackage`
Download any version from releases. Download any version from releases.
Releases: https://github.com/mackysoft/Unity-SerializeReferenceExtensions/releases Releases: https://github.com/mackysoft/Unity-SerializeReferenceExtensions/releases
@@ -26,10 +36,17 @@ Releases: https://github.com/mackysoft/Unity-SerializeReferenceExtensions/releas
Or, you can add this package by opening PackageManager and entering Or, you can add this package by opening PackageManager and entering
`https://github.com/mackysoft/Unity-SerializeReferenceExtensions.git?path=Assets/MackySoft/MackySoft.SerializeReferenceExtensions` ```
https://github.com/mackysoft/Unity-SerializeReferenceExtensions.git?path=Assets/MackySoft/MackySoft.SerializeReferenceExtensions
```
from the `Add package from git URL` option. from the `Add package from git URL` option.
If you are specifying a version, enter `#{VERSION}` at the end, as shown below.
```
https://github.com/mackysoft/Unity-SerializeReferenceExtensions.git?path=Assets/MackySoft/MackySoft.SerializeReferenceExtensions#1.1.9
```
#### Install via Open UPM #### Install via Open UPM
@@ -122,7 +139,7 @@ public struct StructCommand : ICommand {
The `SubclassSelector` attribute supports types that meet the following conditions. The `SubclassSelector` attribute supports types that meet the following conditions.
- Public - Public or nested private
- Not abstract - Not abstract
- Not generic - Not generic
- Not unity object - Not unity object