Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
## [1.2.0-preview.1] - 2019-03-15
### Added
- Update support for 2019.2
- Integrate with 2D Animation Sprite Library
- Integrate with new 2D Animation Character Group
- Fix asset name conflict
  • Loading branch information
Unity Technologies committed Mar 14, 2019
1 parent 9d90fe9 commit 82ef230
Show file tree
Hide file tree
Showing 14 changed files with 288 additions and 81 deletions.
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [1.1.0-preview.3] - 2019-04-24
## [1.2.0-preview.1] - 2019-03-15
### Added
- Use latest 2D Animation package for 2019.1
- Update support for 2019.2
- Integrate with 2D Animation Sprite Library
- Integrate with new 2D Animation Character Group
- Fix asset name conflict

## [1.1.0-preview.2] - 2019-04-23
### Added
Expand Down Expand Up @@ -37,4 +40,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Handles include or exclude hidden layers
- Supports Prefab generation that reconstruct generated Sprites to original art asset layout
- Prefab generation supports GameObject grouping based on Adobe Photoshop layer grouping
- Supports 2D Animation v2 single character with multiple Sprites workflow
- Supports 2D Animation v2 single character with multiple Sprites workflow
1 change: 1 addition & 0 deletions Editor/PSDImportPostProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.U2D.Sprites;
using UnityEngine;

namespace UnityEditor.Experimental.U2D.PSD
Expand Down
170 changes: 164 additions & 6 deletions Editor/PSDImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
using System.Linq;
using UnityEditor.Experimental.U2D.Animation;
using UnityEditor.Experimental.U2D.Common;
using UnityEditor.U2D.Sprites;
using UnityEngine.Assertions;
using UnityEngine.Experimental.U2D;
using UnityEngine.Experimental.U2D.Animation;

namespace UnityEditor.Experimental.U2D.PSD
{
[ScriptedImporter(1, "psb")]
[ScriptedImporter(2, "psb")]
public class PSDImporter : ScriptedImporter, ISpriteEditorDataProvider, IAnimationAssetPostProcess
{
class GameObjectCreationFactory
Expand Down Expand Up @@ -61,8 +62,15 @@ struct BoneGO
[SerializeField]
Vector2Int m_DocumentSize;

[SerializeField]
bool m_PaperDollMode = false;

[SerializeField]
SpriteLibrary m_SpriteLibrary = new SpriteLibrary() {categories = new List<SpriteLibCategory>()};
GameObjectCreationFactory m_GameObjectFactory = new GameObjectCreationFactory();

internal SpriteLibrary spriteLibrary { get { return m_SpriteLibrary; } set { m_SpriteLibrary = value; } }

[SerializeField]
int m_TextureActualWidth;
public int textureActualWidth
Expand Down Expand Up @@ -107,6 +115,9 @@ public int textureActualHeight
[SerializeField]
string m_PrefabAssetName = null;

[SerializeField]
string m_SpriteLibAssetName = null;

public PSDImporter()
{
m_TextureImporterSettings = new TextureImporterSettings();
Expand Down Expand Up @@ -541,9 +552,15 @@ void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)

if (output.sprites != null)
{
var slAsset = ProduceSpriteLibAsset(output.sprites);

if (shouldProduceGameObject)
{
var prefab = OnProducePrefab(m_TextureAssetName, output.sprites);
GameObject prefab = null;
if (m_PaperDollMode)
prefab = OnProducePaperDollPrefab(m_TextureAssetName, output.sprites, slAsset);
else
prefab = OnProducePrefab(m_TextureAssetName, output.sprites, slAsset);
if (prefab != null)
{
if (string.IsNullOrEmpty(m_PrefabAssetName))
Expand All @@ -553,22 +570,57 @@ void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
mainAsset = prefab;
}
}

foreach (var s in output.sprites)
{
var spriteAssetName = GetUniqueName(s.GetSpriteID().ToString(), assetNameHash, false, s);
ctx.AddObjectToAsset(spriteAssetName, s);
}

if (slAsset != null)
{
if (string.IsNullOrEmpty(m_SpriteLibAssetName))
m_SpriteLibAssetName = GetUniqueName(slAsset.name, assetNameHash, true, slAsset);
ctx.AddObjectToAsset(m_SpriteLibAssetName, slAsset);
}
}
ctx.SetMainObject(mainAsset);
}

bool SpriteIsMainFromSpriteLib(string spriteId, out string categoryName)
{
categoryName = "";
if (m_SpriteLibrary.categories != null)
{
foreach (var category in m_SpriteLibrary.categories)
{
var index = category.spriteIds.FindIndex(x => x == spriteId);
if (index == 0)
{
categoryName = category.name;
return true;
}
if (index > 0)
return false;
}
}
return true;
}

void BuildGroupGameObject(List<PSDLayer> psdGroup, int index, Transform root)
{
var spriteData = GetSpriteImportData().FirstOrDefault(x => x.spriteID == psdGroup[index].spriteID);
if (psdGroup[index].gameObject == null)
{
if (m_GenerateGOHierarchy || !psdGroup[index].spriteID.Empty())
psdGroup[index].gameObject = m_GameObjectFactory.CreateGameObject(spriteData != null ? spriteData.name : psdGroup[index].name);
{
// Determine if need to create GameObject i.e. if the sprite is not in a SpriteLib or if it is the first one
string categoryName;
var b = SpriteIsMainFromSpriteLib(psdGroup[index].spriteID.ToString(), out categoryName);
string goName = string.IsNullOrEmpty(categoryName) ? spriteData != null ? spriteData.name : psdGroup[index].name : categoryName;
if (b)
psdGroup[index].gameObject = m_GameObjectFactory.CreateGameObject(goName);
}
if (psdGroup[index].parentIndex >= 0 && m_GenerateGOHierarchy)
{
BuildGroupGameObject(psdGroup, psdGroup[index].parentIndex, root);
Expand Down Expand Up @@ -683,7 +735,78 @@ BoneGO[] CreateBonesGO(Transform root)
return new BoneGO[0];
}

GameObject OnProducePrefab(string assetname, Sprite[] sprites)
void GetSpriteLibEntry(string spriteId, out string category, out int index)
{
category = "";
index = -1;
foreach (var cat in m_SpriteLibrary.categories)
{
index = cat.spriteIds.FindIndex(x => x == spriteId);
if (index != -1)
{
category = cat.name;
break;
}
}
}

GameObject OnProducePaperDollPrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
{
GameObject root = null;
CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider<ICharacterDataProvider>().GetCharacterData()) : null;
if (sprites != null && sprites.Length > 0)
{
root = new GameObject();
root.name = assetname + "_GO";
var spriteImportData = GetSpriteImportData();
var psdLayers = GetPSDLayers();
m_BoneGOs = CreateBonesGO(root.transform);
if (spriteLib != null)
root.AddComponent<SpriteLibraryComponent>().spriteLib = spriteLib;
for (int i = 0; i < sprites.Length; ++i)
{
string categoryName;
if (SpriteIsMainFromSpriteLib(sprites[i].GetSpriteID().ToString(), out categoryName))
{
var spriteBones = m_CharacterData.parts.FirstOrDefault(x => new GUID(x.spriteId) == sprites[i].GetSpriteID()).bones;
var rootBone = root;
if (spriteBones != null && spriteBones.Any())
{
var b = spriteBones.Where(x => x >= 0 && x < m_BoneGOs.Length).Select(x => m_BoneGOs[x]).OrderBy(x => x.index);
if (b.Any())
rootBone = b.First().go;
}

var srGameObject = m_GameObjectFactory.CreateGameObject(string.IsNullOrEmpty(categoryName) ? sprites[i].name : categoryName);
var sr = srGameObject.AddComponent<SpriteRenderer>();
sr.sprite = sprites[i];
sr.sortingOrder = psdLayers.Count - psdLayers.FindIndex(x => x.spriteID == sprites[i].GetSpriteID());
srGameObject.transform.parent = rootBone.transform;
var spriteMetaData = spriteImportData.FirstOrDefault(x => x.spriteID == sprites[i].GetSpriteID());
if (spriteMetaData != null)
{
var uvTransform = spriteMetaData.uvTransform;
var outlineOffset = new Vector2(spriteMetaData.rect.x - uvTransform.x + (spriteMetaData.pivot.x * spriteMetaData.rect.width),
spriteMetaData.rect.y - uvTransform.y + (spriteMetaData.pivot.y * spriteMetaData.rect.height)) * definitionScale / sprites[i].pixelsPerUnit;
srGameObject.transform.position = new Vector3(outlineOffset.x, outlineOffset.y, 0);
}
var category = "";
var spriteIndex = -1;
GetSpriteLibEntry(sprites[i].GetSpriteID().ToString(), out category, out spriteIndex);
if (!string.IsNullOrEmpty(category) && spriteIndex >= 0)
{
var sresolver = srGameObject.AddComponent<SpriteResolver>();
sresolver.spriteCategory = category;
sresolver.spriteIndex = spriteIndex;
sresolver.RefreshSpriteFromSpriteKey();
}
}
}
}
return root;
}

GameObject OnProducePrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
{
GameObject root = null;
CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider<ICharacterDataProvider>().GetCharacterData()) : null;
Expand All @@ -692,6 +815,8 @@ GameObject OnProducePrefab(string assetname, Sprite[] sprites)
var spriteImportData = GetSpriteImportData();
root = new GameObject();
root.name = assetname + "_GO";
if (spriteLib != null)
root.AddComponent<SpriteLibraryComponent>().spriteLib = spriteLib;
var psdLayers = GetPSDLayers();
for (int i = 0; i < psdLayers.Count; ++i)
{
Expand All @@ -700,7 +825,7 @@ GameObject OnProducePrefab(string assetname, Sprite[] sprites)
GUID layerSpriteID = l.spriteID;
var sprite = sprites.FirstOrDefault(x => x.GetSpriteID() == layerSpriteID);
var spriteMetaData = spriteImportData.FirstOrDefault(x => x.spriteID == layerSpriteID);
if (sprite != null && spriteMetaData != null)
if (sprite != null && spriteMetaData != null && l.gameObject != null)
{
var spriteRenderer = l.gameObject.AddComponent<SpriteRenderer>();
spriteRenderer.sprite = sprite;
Expand All @@ -718,9 +843,21 @@ GameObject OnProducePrefab(string assetname, Sprite[] sprites)
l.gameObject.AddComponent<SpriteSkin>();
}
}

var category = "";
var spriteIndex = -1;
GetSpriteLibEntry(layerSpriteID.ToString(), out category, out spriteIndex);
if (!string.IsNullOrEmpty(category) && spriteIndex >= 0)
{
var sresolver = l.gameObject.AddComponent<SpriteResolver>();
sresolver.spriteCategory = category;
sresolver.spriteIndex = spriteIndex;
sresolver.RefreshSpriteFromSpriteKey();
}
}
}


m_BoneGOs = CreateBonesGO(root.transform);

var prefabBounds = new Rect(0 , 0, m_DocumentSize.x / pixelsPerUnit, m_DocumentSize.y / pixelsPerUnit);
Expand Down Expand Up @@ -906,6 +1043,10 @@ public T GetDataProvider<T>() where T : class
{
return characterMode ? new CharacterDataProvider { dataProvider = this } as T : null;
}
if (typeof(T) == typeof(ISpriteLibDataProvider))
{
return new SpriteLibraryDataProvider() { dataProvider = this } as T;
}
else
return this as T;
}
Expand All @@ -918,7 +1059,8 @@ public bool HasDataProvider(Type type)
type == typeof(ISpriteMeshDataProvider) ||
type == typeof(ISpriteOutlineDataProvider) ||
type == typeof(ISpritePhysicsOutlineDataProvider) ||
type == typeof(ITextureDataProvider))
type == typeof(ITextureDataProvider) ||
type == typeof(ISpriteLibDataProvider))
{
return true;
}
Expand Down Expand Up @@ -1094,5 +1236,21 @@ internal Vector2Int documentSize
{
get { return m_DocumentSize; }
}

SpriteLibraryAsset ProduceSpriteLibAsset(Sprite[] sprites)
{
if (!characterMode || m_SpriteLibrary.categories == null)
return null;
var sla = ScriptableObject.CreateInstance<SpriteLibraryAsset>();
sla.name = "Sprite Lib";
sla.entries = m_SpriteLibrary.categories.Select(x =>
new LibEntry()
{
category = x.name,
spriteList = x.spriteIds.Select(y => sprites.FirstOrDefault(z => z.GetSpriteID().ToString() == y)).ToList()
}).ToList();
sla.UpdateHashes();
return sla;
}
}
}
41 changes: 41 additions & 0 deletions Editor/PSDImporterDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using UnityEditor.Experimental.U2D.Common;
using UnityEditor.Experimental.U2D.Animation;
using System;
using UnityEditor.U2D.Sprites;

namespace UnityEditor.Experimental.U2D.PSD
{
Expand Down Expand Up @@ -197,8 +198,25 @@ public void SetEdges(GUID guid, Vector2Int[] edges)

public class CharacterDataProvider : PSDDataProvider, ICharacterDataProvider
{
int ParentGroupInFlatten(int parentIndex, List<PSDLayer> psdLayers)
{
int group = -1;
for (int i = 0; i <= parentIndex; ++i)
if (psdLayers[i].isGroup)
++group;

return group;
}

public CharacterData GetCharacterData()
{
var psdLayers = dataProvider.GetPSDLayers();
var groups = psdLayers.Where(x => x.isGroup).Select(y => new CharacterGroup()
{
name = y.name,
parentGroup = ParentGroupInFlatten(y.parentIndex, psdLayers)
}).ToArray();

var cd = dataProvider.characterData;
var parts = cd.parts == null ? new List<CharacterPart>() : cd.parts.ToList();
var spriteRects = dataProvider.GetSpriteMetaData();
Expand All @@ -213,6 +231,15 @@ public CharacterData GetCharacterData()
var outlineOffset = new Vector2(spriteMetaData.rect.x - uvTransform.x, spriteMetaData.rect.y - uvTransform.y);
cp.spritePosition.position = new Vector2Int((int)outlineOffset.x, (int)outlineOffset.y);
cp.spritePosition.size = new Vector2Int((int)spriteMetaData.rect.width, (int)spriteMetaData.rect.height);
cp.parentGroup = -1;
//Find group
var spritePSDLayer = psdLayers.FirstOrDefault(x => x.spriteID == spriteMetaData.spriteID);
if (spritePSDLayer != null)
{
cp.parentGroup = ParentGroupInFlatten(spritePSDLayer.parentIndex, psdLayers);
}


if (srIndex == -1)
parts.Add(cp);
else
Expand All @@ -230,6 +257,7 @@ public CharacterData GetCharacterData()
parts.Reverse();
cd.parts = parts.ToArray();
cd.dimension = dataProvider.documentSize;
cd.characterGroups = groups.ToArray();
return cd;
}

Expand All @@ -239,4 +267,17 @@ public void SetCharacterData(CharacterData characterData)
dataProvider.characterData = characterData;
}
}

public class SpriteLibraryDataProvider : PSDDataProvider, ISpriteLibDataProvider
{
public SpriteLibrary GetSpriteLibrary()
{
return dataProvider.spriteLibrary;
}

public void SetSpriteLibrary(SpriteLibrary spriteLibrary)
{
dataProvider.spriteLibrary = spriteLibrary;
}
}
}
Loading

0 comments on commit 82ef230

Please sign in to comment.