Hello Guest

Author Topic: CustomPropertyDrawer & sprites & animations  (Read 6998 times)

rakkarage

  • Newbie
  • *
  • Posts: 12
    • View Profile
CustomPropertyDrawer & sprites & animations
« on: June 15, 2014, 02:58:17 pm »
has anyone made tk2dSpriteGuiUtility.SpriteList & SpriteCollectionList
work with CustomPropertyDrawer instead of CustomEditor which means
cannot use GUILayout or EditorGUILayout?

i got the animation drawer working by converting EditorGUILayour.Popup
to EditorGUI.Popup.
but the sprite drawer is more complicated...

thanks
« Last Edit: June 15, 2014, 03:33:47 pm by rakkarage »

rakkarage

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: CustomPropertyDrawer & sprites & animations
« Reply #1 on: June 19, 2014, 03:17:25 pm »
i am just trying to make something like this to edit mobs and items


it would be nice to have standalone sprite and animation pickers to define sprites and animations in scriptableObject asset file databases?
http://catlikecoding.com/unity/tutorials/editor/custom-data/



i got the animation picker working by just making a CustomPropertyDrawer for a custom class with two ints...
- i should prob use a path or guid for collection instead of an int but it works for now
- my rect math seems kinda wonky(?) too but it works

Code: [Select]
[Serializable]
public struct DataAnimation
{
public int Collection;
public int Index;
}

Code: [Select]
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace ca.HenrySoftware.Deko
{
[CustomPropertyDrawer(typeof(DataAnimation))]
public class DataAnimationEditor : PropertyDrawer
{
private static float _offset = EditorGUIUtility.singleLineHeight;
private tk2dGenericIndexItem[] _indexes = null;
private string[] _names = null;
private bool _initialized = false;
private void Init()
{
if (!_initialized)
{
_indexes = tk2dEditorUtility.GetOrCreateIndex().GetSpriteAnimations();
if (_indexes != null)
{
_names = new string[_indexes.Length];
for (int i = 0; i < _indexes.Length; i++)
{
_names[i] = _indexes[i].AssetName;
}
}
_initialized = true;
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
Init();
if ((_indexes == null) || (_indexes.Length == 0))
{
if (GUI.Button(position, "None! Refresh?"))
{
_initialized = false;
Init();
}
}
else
{
var collectionProperty = property.FindPropertyRelative("Collection");
if (collectionProperty == null) return;
int selectedCollection = collectionProperty.intValue;
float indent = _offset * EditorGUI.indentLevel;
Rect region0 = position;
region0.width = ((position.width - _offset) * .5f) + (indent * .5f);
region0.height = _offset;
collectionProperty.intValue = EditorGUI.Popup(region0, string.Empty, selectedCollection, _names);
if (collectionProperty.intValue != selectedCollection)
{
GUI.changed = true;
}
tk2dSpriteAnimation animation = _indexes[selectedCollection].GetAsset<tk2dSpriteAnimation>();
if ((animation != null) && (animation.clips.Length > 0))
{
List<string> clipNames = new List<string>(animation.clips.Length);
List<int> clipIds = new List<int>(animation.clips.Length);
for (int i = 0; i < animation.clips.Length; i++)
{
if (animation.clips[i].name != null && animation.clips[i].name.Length > 0)
{
string name = animation.clips[i].name;
if (tk2dPreferences.inst.showIds)
{
name += "\t[" + i.ToString() + "]";
}
clipNames.Add(name);
clipIds.Add(i);
}
}
var indexProperty = property.FindPropertyRelative("Index");
if (indexProperty == null) return;
int selectedIndex = ((indexProperty == null) ? 0 : indexProperty.intValue);
region0.x += region0.width - indent;
indexProperty.intValue = EditorGUI.IntPopup(region0, string.Empty, selectedIndex, clipNames.ToArray(), clipIds.ToArray());
if (indexProperty.intValue != selectedIndex)
{
GUI.changed = true;
}
if (Event.current.type == EventType.Repaint)
{
Rect background = position;
background.x = _offset + indent;
background.y += _offset;
background.height = _offset * 2;
background.width = position.width - indent;
tk2dGrid.Draw(background);
Rect region1 = position;
region1.x = _offset + indent;
region1.y += _offset;
region1.width = _offset * 2;
region1.height = region1.width;
if (animation != null)
{
tk2dSpriteAnimationClip clip = animation.clips[indexProperty.intValue];
if (clip != null)
{
foreach (var frame in clip.frames)
{
int spriteId = frame.spriteId;
int first = frame.spriteCollection.FirstValidDefinitionIndex;
tk2dSpriteDefinition def = frame.spriteCollection.spriteDefinitions[first + spriteId];
tk2dSpriteThumbnailCache.DrawSpriteTextureInRect(region1, def, Color.white);
region1.x += region1.width;
}
}
}
}
Rect region2 = position;
region2.x = position.width;
region2.width = _offset;
region2.height = _offset;
if (GUI.Button(region2, GUIContent.none))
{
tk2dSpriteAnimationEditorPopup v = EditorWindow.GetWindow(typeof(tk2dSpriteAnimationEditorPopup), false, "Sprite Animation Editor") as tk2dSpriteAnimationEditorPopup;
v.SetSpriteAnimation(animation);
v.Show();
}
}
property.serializedObject.ApplyModifiedProperties();
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return _offset * 3;
}
}
}



but i had more trouble with sprite
i got it working but not without modifying the tk2d source code to remake some methods to not use layout
sure i could have rewritten the cache and buildkeys and Lut and indices and sorting and cache and... but argh... 0 lines of code for a unity3d sprite

if you could add dupes of these two functions that don't use layout and take a rect we could call it from CustomPropertyDrawers without having to edit or recreate the tk2d code

public static tk2dSpriteCollectionData SpriteCollectionList(tk2dSpriteCollectionData currentValue)
public static int SpriteList(string label, int spriteId, tk2dSpriteCollectionData rootSpriteCollection)

thanks a lot

Code: [Select]
[Serializable]
public struct DataSprite
{
public tk2dSpriteCollectionData Collection;
public int Index;
}


Code: [Select]
using UnityEditor;
using UnityEngine;
namespace ca.HenrySoftware.Deko
{
[CustomPropertyDrawer(typeof(DataSprite))]
public class DataSpriteDrawer : PropertyDrawer
{
private static float _offset = EditorGUIUtility.singleLineHeight;
private const string _collectionString = "Collection";
private const string _indexString = "Index";
private tk2dSpriteGuiUtility.SpriteChangedCallback _spriteChangedCallbackInstance = null;
private tk2dSpriteGuiUtility.SpriteChangedCallback spriteChangedCallbackInstance
{
get
{
if (_spriteChangedCallbackInstance == null)
{
_spriteChangedCallbackInstance = new tk2dSpriteGuiUtility.SpriteChangedCallback(SpriteChangedCallbackImpl);
}
return _spriteChangedCallbackInstance;
}
}
private void SpriteChangedCallbackImpl(tk2dSpriteCollectionData spriteCollectionData, int spriteId, object data)
{
SerializedProperty property = data as SerializedProperty;
var collectionProperty = property.FindPropertyRelative(_collectionString);
collectionProperty.objectReferenceValue = spriteCollectionData;
var indexProperty = property.FindPropertyRelative(_indexString);
indexProperty.intValue = spriteId;
property.serializedObject.ApplyModifiedProperties();
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var collectionProperty = property.FindPropertyRelative("Collection");
if (collectionProperty == null) return;
var spriteCollectionData = collectionProperty.objectReferenceValue as tk2dSpriteCollectionData;
var indexProperty = property.FindPropertyRelative("Index");
if (indexProperty == null) return;
var spriteId = indexProperty.intValue;
position.height = _offset;
tk2dSpriteGuiUtility.SpriteSelectorNew(position, spriteCollectionData, spriteId, spriteChangedCallbackInstance, property);
if (spriteCollectionData != null)
{
position.x = _offset + _offset * EditorGUI.indentLevel;
position.y += _offset;
position.width = _offset * 2;
position.height = position.width;
tk2dGrid.Draw(position);
tk2dSpriteDefinition def = spriteCollectionData.spriteDefinitions[spriteId];
tk2dSpriteThumbnailCache.DrawSpriteTextureInRect(position, def, Color.white);
Event ev = Event.current;
if (ev.type == EventType.MouseDown && ev.button == 0 && position.Contains(ev.mousePosition))
{
tk2dSpriteGuiUtility.SpriteSelectorPopup(spriteCollectionData, spriteId, spriteChangedCallbackInstance, property);
}
}
property.serializedObject.ApplyModifiedProperties();
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return _offset * 3;
}
}
}

https://gist.github.com/rakkarage/2e3c01314d276c97f569
« Last Edit: June 19, 2014, 03:44:06 pm by rakkarage »

unikronsoftware

  • Administrator
  • Hero Member
  • *****
  • Posts: 9709
    • View Profile
Re: CustomPropertyDrawer & sprites & animations
« Reply #2 on: June 21, 2014, 08:20:38 pm »
There are no plans to support custom property drawers,  and really no way to change how the back end works at this point. tk2d started in Unity 3.0, way before these features existed. We still maintain backwards compatiblity with 3.5... The back end stuff can't change for backwards compatibility - building up a layer on top like you have is probably the most sensible thing to do.