jacobdufault / fullinspector Goto Github PK
View Code? Open in Web Editor NEWFull Inspector supercharges Unity's inspector
License: MIT License
Full Inspector supercharges Unity's inspector
License: MIT License
This will error out in Editor as soon as you uncomment the setter to the char this[...] property.
Example Class:
using UnityEngine;
using FullInspector;
using Newtonsoft.Json;
[JsonObject(MemberSerialization.OptIn)]
public class CharTest : BaseBehavior
{
public int sizeX;
public int sizeY;
public char[,] grid;
protected override void Awake()
{
base.Awake();
grid = new char[sizeX, sizeY];
}
public char this[int x, int y]
{
get { return grid[x, y]; }
// set { grid[x, y] = value; }
}
}
Exception Details:
ArgumentException: method argument length mismatch
System.Delegate.CreateDelegate (System.Type type, System.Object firstArgument, System.Reflection.MethodInfo method, Boolean throwOnBindFailure) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System/Delegate.cs:226)
System.Delegate.CreateDelegate (System.Type type, System.Reflection.MethodInfo method, Boolean throwOnBindFailure) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System/Delegate.cs:291)
System.Delegate.CreateDelegate (System.Type type, System.Reflection.MethodInfo method) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System/Delegate.cs:295)
System.Reflection.MonoProperty.CreateGetterDelegate (System.Reflection.MethodInfo method) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Reflection/MonoProperty.cs:274)
System.Reflection.MonoProperty.GetValue (System.Object obj, System.Object[] index) (at /Users/builduser/buildslave/monoAndRuntimeClassLibs/build/mcs/class/corlib/System.Reflection/MonoProperty.cs:291)
FullInspector.Utilities.PropertyMetadata.Read (System.Object context) (at Assets/FullInspector/FullInspector/Utility/Forge/PropertyMetadata.cs:61)
FullInspector.PropertyEditors.ReflectedPropertyEditor.GetElementHeight (UnityEngine.GUIContent label, System.Object element) (at Assets/FullInspector/FullInspector/Editor/PropertyEditors/Special/ReflectedPropertyEditor.cs:221)
FullInspector.FullInspectorCommonSerializedObjectEditor.OnInspectorGUI () (at Assets/FullInspector/FullInspector/Editor/FullInspectorCommonSerializedObjectEditor.cs:63)
UnityEditor.DockArea:OnGUI()
When an abstract property is collapsible, the type selector for that property can't be interacted with. I'll see if I can find a quick fix.
The serialization system should be abstracted so that custom serialization frameworks can be used.
Currently targeted serializers are:
I just noticed that undo doesn't work with BaseBehavior and BaseScriptableObject inspectors.
From a quick look around it seems that in version 1.2, we now need to use [ShowInInspector]. However, some properties are shown even without the attribute, while others are not. I'm confused?
Isn't [ShowInInspector] redundant with [JsonProperty] anyway though? I could see [JsonProperty] being the equivalent of Unity's [SerializeField], defaulting to being shown in the inspector but with the option to hide it with [HideInInspector]. That covers everything we need, no?
Hmm, I just realized you probably did this to decouple serialization from inspection so we can plug in the serialization framework of our choice. However I still think we should try to find a more consistent solution because it is confusing as it is.
If types (even primitives, strings, vectors, etc.) were all hidden by default, it would be
fine by me. As long as it's consistent.
#13
Unity, by default, shows [Serializable]
classes in a collapsible subsection. Full Inspector should mimic this behavior as much as possible.
Reference type fields and properties marked with both [Hidden] and [JsonProperty] attributes are not serialized. I believe they should, since value type fields marked with the same attributes do.
TypeMetadata class needs to check to see if it is a ScriptableObject type and create the instance via the ScriptableObject.CreateInstance method. I threw a sub optimal check for this locally on Line 81 of TypeMetadata.cs
if (typeof(UnityEngine.ScriptableObject).IsAssignableFrom(ReflectedType)) {
return UnityEngine.ScriptableObject.CreateInstance(ReflectedType);
}
I know it's better to stick to one type of serializer throughout the entire project, but this was a request from someone on my team higher than me.
Example:
public class ProtoBehavior : BaseBehavior<ProtobufNetSerializer> { }
public class JsonBehavior : BaseBehavior<ProtobufNetSerializer> { }
Since I updated to version 2.0, struct and non-null abstract properties don't show a foldout anymore. See the following code. Full Inspector should show a foldout for the someStruct
property but it doesn't.
[JsonObject(MemberSerialization.OptIn)]
public struct SomeStruct
{
[JsonProperty]
[ShowInInspector]
private int someInt { get; set; }
[JsonProperty]
[ShowInInspector]
private float someFloat { get; set; }
[JsonProperty]
[ShowInInspector]
private string someString { get; set; }
[JsonProperty]
[ShowInInspector]
private Color someColor { get; set; }
}
public class SomeBehavior : BaseBehavior
{
[SerializeField]
[ShowInInspector]
private SomeStruct someStruct { get; set; }
}
Note that replacing SomeStruct
with a class instead, it does work.
When adding a new field whose type is a class, the instance created by the inspector is editable but it's not serialized until something (anything) is edited.
When accessing a prefab reference at runtime, I can check the values of unity-serialized fields. But since RestoreState hasn't been called for prefabs before they're instantiated, I can't access any FI handled fields.
At the moment I'm calling RestoreState manually on prefabs before accessing them, but would it be possible for this not to be necessary? (and is this workaround safe?)
I get a compiler error if this is installed and I set to web player. it is a reflection error but it does not give me any details about where it is is. They all say file unknown.
When a new object has been created, it may contain a number of reference fields. What should happen in this scenario?
The current behavior is to leave these references as null, and just assume the user will take care of it. However, perhaps the inspector should require the user to manually construct reference instances (this would also help the inspector deal with recursive class definitions).
This is more of a nice to have built in since this can be done using a simple property editor.
Original Topic: Support System.Flags attribute with EditorGUI.EnumMaskField
Just a small display artifact in the inspector. When the inspector window is not wide enough such that vector properties cannot be displayed on a single line, the x,y,z text boxes overlap the following property.
Gameobjects created from a prefab with the following behavior don't sync with the prefab like you would expect. For example, changing someInt
in the prefab should be reflected in the gameobject, but it's not.
using UnityEngine;
using FullInspector;
public class SomeBehavior : BaseBehavior
{
[SerializeField]
[ShowInInspector]
private int someInt { get; set; }
[SerializeField]
[ShowInInspector]
private float someFloat { get; set; }
}
Note that if you replace each C# property by a normal field of the same type, it behaves as expected. Well, except that out-of-sync fields aren't emphasized in bold like in the default inspector. That would be nice too :)
For example, it would be nice if defining a button in the inspector was as simple as:
class Item {
[Button]
void InvokedMethod() {
Debug.Log("hello from " + this);
}
}
Right now, this can be done (and is included in one of the samples), but the process is painful and doesn't work as nicely. This requires direct integration into TypeMetadata
and the ReflectedPropertyEditor
.
One potential issue with this is ordering. Reflection will not give the order of fields/properties/methods in the same order they are declared as. This can be resolved by explicit ordering via the Order
attribute.
When changing the signature of a serialized field (e.g. changing its type), its old data is persisted and causes errors if the new type doesn't match the existing data. The old data can't seem to be overwritten unless you change the signature back so the type matches.
When using Visual Studio 2012 to code for Unity with Full Inspector 1.10 installed, it's throwing compile errors with the UnityEngine side of things which blocks it from ever compiling the UnityEditor, thus you never get a chance to see if your code is throwing any errors in the Editor.
Best I can tell is that this is due the dll being compiled with a different .net version, however after trying all the different versions, I'm a bit stuck.
Warning 1 The predefined type 'System.Runtime.CompilerServices.ExtensionAttribute' is defined in multiple assemblies in the global alias; using definition from 'c:\Users\r.caltabiano\Documents\WordSearch\Assets\FullInspector\FullInspector\Serializers\JsonNet\DLLs\Newtonsoft.Json.dll' C:\Users\r.caltabiano\Documents\WordSearch\CSC UnityVS.WordSearch.CSharp
Error 2 Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor' C:\Users\r.caltabiano\Documents\WordSearch\CSC UnityVS.WordSearch.CSharp
Error 3 Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor' C:\Users\r.caltabiano\Documents\WordSearch\CSC UnityVS.WordSearch.CSharp
Error 4 Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor' C:\Users\r.caltabiano\Documents\WordSearch\CSC UnityVS.WordSearch.CSharp
Error 5 Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor' C:\Users\r.caltabiano\Documents\WordSearch\CSC UnityVS.WordSearch.CSharp
Error 6 Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor' C:\Users\r.caltabiano\Documents\WordSearch\CSC UnityVS.WordSearch.CSharp
Error 7 Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor' C:\Users\r.caltabiano\Documents\WordSearch\CSC UnityVS.WordSearch.CSharp
Error 8 Missing compiler required member 'System.Runtime.CompilerServices.ExtensionAttribute..ctor' C:\Users\r.caltabiano\Documents\WordSearch\CSC UnityVS.WordSearch.CSharp
Investigate adding a 4th serializer, JsonFX for Unity3d.
It would be nice if FullInspector also exposed other integer data types to the inspector, rather than just (int).
Edit: They only seem to be hidden on ScriptableObjects. MonoBehaviours work, but they're capped.
This is just a minor request, if you don't agree just close this.
I often change a script which was originally a MonoBehaviour
to a BaseBehavior
by simply exchanging the word Mono
to Base
. The different notation lead to compile errors (type not found
) a few times for me.
Consider removing Ref<T>
. This is the biggest stumbling block with Full Inspector and is non-intuitive. Ref<T>
is used internally within serialization to disambiguate between references to UnityEngine.Objects
and an actual serialized UnityEngine.Object
.
The proposed alternative is require [SerializeField]
or similar annotations only on the UnityEngine.Object
derived type, where all other types use the serialization library of choice. For example,
[JsonObject(MemberSerialization.OptIn)]
struct MyStruct<T> {
[JsonProperty]
public T Value;
[JsonProperty]
public GameObject MyObject;
[JsonProperty]
public MyBehavior MyBehavior;
}
class MyBehavior : BaseBehavior<JsonNetSerializer> {
[SerializeField]
private MyStruct<float> Data;
}
This causes a loss of serialization customization over MyBehavior
and requires custom reflection over behavior types to discover which properties to serialize. However, it means that whenever a serializer encounters a UnityEngine.Object
reference it knows it is always serialized as a reference.
This will break current serialization data.
Currently all fields will appear in the inspector window regardless of public, private, serialization flags, hide in inspector, etc. This is different than Unity's default, which is that only serialized fields will appear in the inspector window. While not a big deal, I can't even hide fields using the [HideInInspector] flag.
Fixing this will require a custom implementation of ISurrogateSelector
.
For reference, here is the Mono SurrogateSelector
implementation from reflection:
// Type: System.Runtime.Serialization.SurrogateSelector
// Assembly: mscorlib, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
// MVID: F7DE7BB6-83A9-4F92-BD7A-366EC18B3DE9
// Assembly location: C:\Program Files (x86)\Unity\Editor\Data\Mono\lib\mono\unity\mscorlib.dll
using System;
using System.Collections;
using System.Runtime.InteropServices;
namespace System.Runtime.Serialization
{
/// <summary>
/// Assists formatters in selection of the serialization surrogate to delegate the serialization or deserialization process to.
/// </summary>
[ComVisible(true)]
public class SurrogateSelector : ISurrogateSelector
{
private Hashtable Surrogates = new Hashtable();
private ISurrogateSelector nextSelector;
/// <summary>
/// Adds a surrogate to the list of checked surrogates.
/// </summary>
/// <param name="type">The <see cref="T:System.Type"/> for which the surrogate is required.</param><param name="context">The context-specific data. </param><param name="surrogate">The surrogate to call for this type. </param><exception cref="T:System.ArgumentNullException">The <paramref name="type"/> or <paramref name="surrogate"/> parameter is null. </exception><exception cref="T:System.ArgumentException">A surrogate already exists for this type and context. </exception>
public virtual void AddSurrogate(Type type, StreamingContext context, ISerializationSurrogate surrogate)
{
if (type == null || surrogate == null)
throw new ArgumentNullException("Null reference.");
string str = type.FullName + "#" + context.ToString();
if (this.Surrogates.ContainsKey((object) str))
throw new ArgumentException("A surrogate for " + type.FullName + " already exists.");
this.Surrogates.Add((object) str, (object) surrogate);
}
/// <summary>
/// Adds the specified <see cref="T:System.Runtime.Serialization.ISurrogateSelector"/> that can handle a particular object type to the list of surrogates.
/// </summary>
/// <param name="selector">The surrogate selector to add. </param><exception cref="T:System.ArgumentNullException">The <paramref name="selector"/> parameter is null. </exception><exception cref="T:System.Runtime.Serialization.SerializationException">The selector is already on the list of selectors. </exception><exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
public virtual void ChainSelector(ISurrogateSelector selector)
{
if (selector == null)
throw new ArgumentNullException("Selector is null.");
if (this.nextSelector != null)
selector.ChainSelector(this.nextSelector);
this.nextSelector = selector;
}
/// <summary>
/// Returns the next selector on the chain of selectors.
/// </summary>
///
/// <returns>
/// The next <see cref="T:System.Runtime.Serialization.ISurrogateSelector"/> on the chain of selectors.
/// </returns>
/// <exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception>
public virtual ISurrogateSelector GetNextSelector()
{
return this.nextSelector;
}
/// <summary>
/// Returns the surrogate for a particular type.
/// </summary>
///
/// <returns>
/// The surrogate for a particular type.
/// </returns>
/// <param name="type">The <see cref="T:System.Type"/> for which the surrogate is requested. </param><param name="context">The streaming context. </param><param name="selector">The surrogate to use. </param><exception cref="T:System.ArgumentNullException">The <paramref name="type"/> parameter is null. </exception><exception cref="T:System.Security.SecurityException">The caller does not have the required permission. </exception><PermissionSet><IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="SerializationFormatter"/></PermissionSet>
public virtual ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector)
{
if (type == null)
throw new ArgumentNullException("type is null.");
ISerializationSurrogate serializationSurrogate = (ISerializationSurrogate) this.Surrogates[(object) (type.FullName + "#" + context.ToString())];
if (serializationSurrogate != null)
{
selector = (ISurrogateSelector) this;
return serializationSurrogate;
}
else
{
if (this.nextSelector != null)
return this.nextSelector.GetSurrogate(type, context, out selector);
selector = (ISurrogateSelector) null;
return (ISerializationSurrogate) null;
}
}
/// <summary>
/// Removes the surrogate associated with a given type.
/// </summary>
/// <param name="type">The <see cref="T:System.Type"/> for which to remove the surrogate. </param><param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> for the current surrogate. </param><exception cref="T:System.ArgumentNullException">The <paramref name="type"/> parameter is null. </exception>
public virtual void RemoveSurrogate(Type type, StreamingContext context)
{
if (type == null)
throw new ArgumentNullException("type is null.");
this.Surrogates.Remove((object) (type.FullName + "#" + context.ToString()));
}
}
}
In the inspector view, format property names such that propertyName
becomes "Property Name".
In the inspector view again, injected Object
references should display the type of the property in parentheses. So if you drag and drop a gameobject named "SomeGameObject" into the Transform
property of another game object, it should say "SomeGameObject (Transform)" in the label box of the property.
It would be nice to have, but requires a rework of the editor metadata storage system
Support using [JsonProperty]
, [ProtoMember]
, etc, inside of a BaseBehavior
to mark a field/property as serializable (instead of just [SerializeField]
).
Hey, noticed a weird bug where all the enums on my BaseBehavior will turn bold as if their values have been edited whenever I add an item to a list or array -- tested with arrays of class instances and with a list of strings, both triggered all the of enum fields.
For BaseBehavior derived scripts that reference unity objects with Ref<>, the inspector code keeps adding new object references when doing completely unrelated changes in the inspector view. Anytime you edit a property in the script's inspector, a new object reference is added at the end of the array and the old one is not discarded. The serialized state always points to the most recent one.
This looks like unnecessary bloat, perhaps I'm wrong though. You can see what I'm talking about by activating the debug view mode of the standard inspector.
Allow ordering of properties in the inspector so that partial classes can be customized w.r.t. field/property order
In particular, investigate Meshes
and Textures
.
Give the user an option to construct an unformatted instance. Otherwise, leave the property as null.
This issue primarily resides in the ReflectedPropertyEditor
. SerializationHelpers.InstantiateReferences
properly handles non-default constructor objects.
This will require a couple of changes:
BaseScriptableObject
. It looks like OnEnable
might always be called, so that's one avenue for deserialization.Ref<T>
and ComponentConverter
need to also support ScriptableObjectI have a BaseScriptableObject
with a Dictionary
-property:
[JsonObject(MemberSerialization.OptIn)]
public class MeshInfo : BaseScriptableObject
{
[JsonProperty]
public Dictionary<string, bool>
Properties;
}
I create an instance of if in an AssetPostprocessor
and write it to a new .asset-file:
public class MyPostprocessor : AssetPostprocessor
{
void OnPostprocessGameObjectWithUserProperties (GameObject go, string[] propNames, System.Object[] values)
{
Dictionary<string, bool> properties = new Dictionary<string, bool> ();
for (int i = 0; i < propNames.Length; i++) {
if (values [i].GetType () == typeof(bool))
properties.Add (propNames [i], (bool)values [i]);
}
MeshInfo meshInfo = ScriptableObject.CreateInstance<MeshInfo> ();
meshInfo.Properties = properties;
AssetDatabase.CreateAsset (meshInfo, assetPath + ".asset");
AssetDatabase.SaveAssets ();
meshInfo.SaveState ();
FullInspector.FullInspectorSaveManager.SaveAll ();
}
}
The file gets created and I see my bool dictionary in the inspector. But when I press play the content of the dictionary property is lost. So it is not serialized. When I manually add en entry to the dictionary in the inspector it is correctly written to disk.
As you can see I tried all Save
-methods I can think of. Do you what is missing?
Thanks a lot! Btw. FullInspector is a really nice package!
C# properties still throw Ref<> errors for non-BaseBehavior
component types. For example, properties of type RigidBody
or any custom MonoBehaviour
still throw errors. Weirdly enough, Transform
properties are ok.
So in this code, everything works fine except that SomeBehavior.body
and SomeBehavior.normalBehavior
cause the following errors to show in the console:
A property of type UnityEngine.Rigidbody needs to be wrapped in Ref<>
UnityEngine.Debug:LogError(Object)
A property of type NormalBehavior needs to be wrapped in Ref<>
UnityEngine.Debug:LogError(Object)
SomeBehavior.target
and SomeBehavior.anotherBehavior
don't cause any error.
Note that replacing C# properties with fields of the same type gets rid of any error. Note also that all four Debug.Log()
successfully print out their injected instance, regardless of errors being thrown.
Here's the code:
public class NormalBehavior : MonoBehaviour
{
public Vector3 someVector;
}
public class AnotherBehavior : BaseBehavior
{
[SerializeField]
[ShowInInspector]
private int someInt { get; set; }
[SerializeField]
[ShowInInspector]
private float someFloat { get; set; }
}
public class SomeBehavior : BaseBehavior
{
[SerializeField]
[ShowInInspector]
private Transform target { get; set; }
[SerializeField]
[ShowInInspector]
private Rigidbody body { get; set; }
[SerializeField]
[ShowInInspector]
private NormalBehavior normalBehavior { get; set; }
[SerializeField]
[ShowInInspector]
private AnotherBehavior anotherBehavior { get; set; }
void Start()
{
Debug.Log(target);
Debug.Log(body);
Debug.Log(normalBehavior);
Debug.Log(anotherBehavior);
}
}
This will primarily be done via caching indexes into the collections (changing lots of O(n) lookups into O(1) lookups, at the cost of O(n) memory).
This is more feature request than an issue, feel free to close this if this is not the appropriate place for it.
The topic of covariance and contravariance is quite counter-intuitive so hopefully my example will make some sense. The "in" is really important. Say I have the following definitions.
[JsonObject(MemberSerialization.OptIn)]
public interface IAction<in T>
{
void Act(T data);
}
[JsonObject(MemberSerialization.OptIn)]
public class DestroyGameObject : IAction<object>
{
[JsonProperty]
private GameObject gameObject;
public void Act(object data)
{
// we ignore the data object in this case, just destroy the game object
// but you can imagine a PrintMessage : IAction<string> action which prints
// the given (at runtime) message
GameObject.Destroy(gameObject);
}
}
Given this, because T is contravariant in IAction, the following assignment is valid: (and that makes sense because DestroyGameObject.Act() should be able to accept a string parameter if it expects an object)
[JsonProperty]
IAction<string> action = new DestroyGameObject();
In other words, DestroyGameObject is a valid implementation of IAction, and so should appear in the dropdown list of concrete implementations of a IAction property in the inspector.
I imagine that making this work would only be a matter of doing more precise reflection by considering covariance and contravariance. More info on covariance and contravariance here:
http://msdn.microsoft.com/en-us/library/dd799517(v=vs.110).aspx
Create a property editor for types which derive from ICollection
, such as HashSet
.
I'm stuck trying to inject custom ScriptableObject assets in a script. Maybe I'm just doing something wrong. I have the following asset definition:
[JsonObject(MemberSerialization.OptIn)]
public class SpellDescriptor : BaseScriptableObject
{
[MenuItem("Assets/Create/SpellDescriptor")]
public static void CreateAsset()
{
ScriptableObjectUtility.CreateAsset<SpellDescriptor>();
}
[JsonProperty]
public string spellName { get; private set; }
[JsonProperty]
public int manaCost { get; private set; }
}
Then I have a SpellCaster component in which I want to be able to inject a spell descriptor
[JsonObject(MemberSerialization.OptIn)]
public class SpellCaster : BaseBehavior
{
[JsonProperty]
private Ref<SpellDescriptor> spellDescriptor { get; set; }
void Start()
{
Debug.Log(spellDescriptor.Value); // prints out Null
}
}
At design time, I drag-and-drop the asset I created onto the spellDescriptor property of my SpellCaster. Sadly, when I start the game, I get the following warning:
Json.NET had an error. Continuing with deserialization.
Exception: System.InvalidCastException: Cannot cast from source type to destination type.
So the spellDescriptor property stays null at runtime, and even goes back to "None" in the editor.
I use this script to create ScriptableObjects: http://wiki.unity3d.com/index.php?title=CreateScriptableObjectAsset
AbstractTypePropertyEditor
logs an error if it contains an object instance that does not have a default constructor.
The AbstractTypePropertyEditor
does not consider the object's type as selectable, so when it goes to find the index of the type of the object it fails.
A number of types which should not be exposed to the public are available in namespace FullInspector
. Changing their visibility to Internal
does not do anything, as they are compiled into the same Assembly-CSharp
DLL with all of the other code.
Building a 2d char array at runtime and then select the object after awake has been called.
Example Class:
using UnityEngine;
using FullInspector;
using Newtonsoft.Json;
[JsonObject(MemberSerialization.OptIn)]
public class CharTest : BaseBehavior
{
public int sizeX;
public int sizeY;
public char[,] grid;
protected override void Awake()
{
base.Awake();
grid = new char[sizeX, sizeY];
}
}
Exception Details:
InvalidCastException: Cannot cast from source type to destination type.
FullInspector.PropertyEditor`1[System.Char[]].FullInspector.IPropertyEditor.GetElementHeight (UnityEngine.GUIContent label, System.Object element) (at Assets/FullInspector/FullInspector/Editor/IPropertyEditor.cs:65)
FullInspector.PropertyEditors.ReflectedPropertyEditor.GetElementHeight (UnityEngine.GUIContent label, System.Object element) (at Assets/FullInspector/FullInspector/Editor/PropertyEditors/Special/ReflectedPropertyEditor.cs:223)
FullInspector.FullInspectorCommonSerializedObjectEditor.OnInspectorGUI () (at Assets/FullInspector/FullInspector/Editor/FullInspectorCommonSerializedObjectEditor.cs:63)
UnityEditor.DockArea:OnGUI()
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.