Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
## [5.0.0-pre.1] - 2020-11-02
### Added
- Added bone sharing from other PSDImporter file
  • Loading branch information
Unity Technologies committed Nov 2, 2020
1 parent a5f6b30 commit 88f7b5d
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 65 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Changelog
## [5.0.0-pre.1] - 2020-11-02
### Added
- Added bone sharing from other PSDImporter file

## [4.0.2] - 2020-08-31
### Fixed
- Fixed importing files with vector layers generates textures incorrectly (case 1266986)
Expand Down
4 changes: 3 additions & 1 deletion Documentation~/PSDImporter.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Summary

**Note: Documentation for version 5.0.0 is currently being updated.**

The PSD Importer is an Asset importer that is specialized for importing Adobe Photoshop .psb files into Unity and generating a Prefab made of Sprites based on the source file. The .psb file format is functionally identical to the more common Adobe .psd format and can support much larger images than the .psd format (up to 300,000 by 300,000 pixels in size).

You can save or convert your Photoshop artwork files into the .psb format and import them into Unity with the PSD Importer. When you import .psb files with the PSD Importer, you can use features such as [Mosaic](#Mosaic) to automatically generate a Sprite sheet from the imported layers; or [Character Rig](#Rig) where Unity reassembles the Sprites of a character as they are arranged in their source files.
Expand Down Expand Up @@ -219,4 +221,4 @@ namespace UnityEditor.U2D.PSD
}
}
```
```
144 changes: 114 additions & 30 deletions Editor/PSDImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
using UnityEditor.U2D.Common;
using UnityEditor.U2D.Sprites;
using UnityEngine.Assertions;
using UnityEngine.Experimental.U2D.Animation;
using UnityEngine.U2D;
using UnityEngine.U2D.Animation;
using UnityEngine.Scripting.APIUpdating;
Expand All @@ -20,7 +19,7 @@ namespace UnityEditor.U2D.PSD
/// <summary>
/// ScriptedImporter to import Photoshop files
/// </summary>
[ScriptedImporter(4, "psb")]
[ScriptedImporter(5, "psb")]
[HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.psdimporter@latest")]
[MovedFrom("UnityEditor.Experimental.AssetImporters")]
public class PSDImporter : ScriptedImporter, ISpriteEditorDataProvider
Expand Down Expand Up @@ -114,17 +113,31 @@ struct BoneGO
};

[SerializeField]
// SpriteData for both single and multiple mode
List<SpriteMetaData> m_SpriteImportData = new List<SpriteMetaData>(); // we use index 0 for single sprite and the rest for multiple sprites
[SerializeField]
// SpriteData for Mosaic mode
List<SpriteMetaData> m_MosaicSpriteImportData = new List<SpriteMetaData>();
[SerializeField]
// SpriteData for Rig mode
List<SpriteMetaData> m_RigSpriteImportData = new List<SpriteMetaData>();
[SerializeField]
// CharacterData for Rig mode
CharacterData m_CharacterData = new CharacterData();
[SerializeField]
// SpriteData for shared rig mode
List<SpriteMetaData> m_SharedRigSpriteImportData = new List<SpriteMetaData>();
[SerializeField]
// CharacterData for shared rig mode
CharacterData m_SharedRigCharacterData = new CharacterData();

[SerializeField]
List<TextureImporterPlatformSettings> m_PlatformSettings = new List<TextureImporterPlatformSettings>();
[SerializeField]
bool m_MosaicLayers = true;
[SerializeField]
bool m_CharacterMode = true;
[SerializeField]
Vector2 m_DocumentPivot = Vector2.zero;
[SerializeField]
SpriteAlignment m_DocumentAlignment = SpriteAlignment.BottomCenter;
Expand All @@ -141,7 +154,10 @@ struct BoneGO
bool m_PaperDollMode = false;

[SerializeField]
bool m_KeepDupilcateSpriteName = false;
bool m_KeepDupilcateSpriteName = true;

[SerializeField]
private string m_SkeletonAssetReferenceID = null;

[SerializeField]
SpriteCategoryList m_SpriteCategoryList = new SpriteCategoryList() {categories = new List<SpriteCategory>()};
Expand Down Expand Up @@ -170,16 +186,13 @@ internal int textureActualHeight

[SerializeField]
bool m_ResliceFromLayer = false;
[SerializeField]
bool m_CharacterMode = true;

[SerializeField]
List<PSDLayer> m_MosaicPSDLayers = new List<PSDLayer>();
[SerializeField]
List<PSDLayer> m_RigPSDLayers = new List<PSDLayer>();

[SerializeField]
CharacterData m_CharacterData = new CharacterData();
List<PSDLayer> m_SharedRigPSDLayers = new List<PSDLayer>();

[SerializeField]
bool m_GenerateGOHierarchy = false;
Expand All @@ -192,6 +205,9 @@ internal int textureActualHeight

[SerializeField]
string m_SpriteLibAssetName = null;

[SerializeField]
string m_SkeletonAssetName = null;

[SerializeField]
SecondarySpriteTexture[] m_SecondarySpriteTextures;
Expand Down Expand Up @@ -261,6 +277,15 @@ public override void OnImportAsset(AssetImportContext ctx)
{
ImportFromLayers(ctx, doc);
}

if (!string.IsNullOrEmpty(m_SkeletonAssetReferenceID))
{
var primaryAssetPath = AssetDatabase.GUIDToAssetPath(m_SkeletonAssetReferenceID);
if(!string.IsNullOrEmpty(primaryAssetPath) && primaryAssetPath != assetPath)
{
ctx.DependsOnArtifact(primaryAssetPath);
}
}
}
finally
{
Expand All @@ -271,9 +296,6 @@ public override void OnImportAsset(AssetImportContext ctx)
EditorUtility.SetDirty(this);
}


// Debug Profiler.
// UnityEngine.Profiling.Memory.Experimental.MemoryProfiler.TakeSnapshot("snapshot.snap", MemorySnapshotFinish, CaptureFlags.ManagedObjects | CaptureFlags.NativeObjects | CaptureFlags.NativeAllocations | CaptureFlags.NativeStackTraces);
}

static void ValidatePSDLayerId(List<BitmapLayer> layers, UniqueNameGenerator uniqueNameGenerator)
Expand Down Expand Up @@ -574,12 +596,6 @@ void ImportFromLayers(AssetImportContext ctx, Document doc)
foreach (var l in oldPsdLayers)
l.Dispose();
}

}

void MemorySnapshotFinish(string path, bool done)
{

}

void EnsureSingleSpriteExist()
Expand Down Expand Up @@ -631,6 +647,8 @@ void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
m_PrefabAssetName = GetUniqueName(string.Format("{0} Prefab", assetName), assetNameHash, true);
if (string.IsNullOrEmpty(m_SpriteLibAssetName))
m_SpriteLibAssetName = GetUniqueName(string.Format("{0} Sprite Lib", assetName), assetNameHash, true);
if (string.IsNullOrEmpty(m_SkeletonAssetName))
m_SkeletonAssetName = GetUniqueName(string.Format("{0} Skeleton", assetName), assetNameHash, true);

output.texture.name = assetName;
ctx.AddObjectToAsset(m_TextureAssetName, output.texture, output.thumbNail);
Expand Down Expand Up @@ -666,6 +684,15 @@ void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
slAsset.name = assetName;
ctx.AddObjectToAsset(m_SpriteLibAssetName, slAsset);
}

if (characterMode && skeletonAsset == null)
{
var characterRig = ScriptableObject.CreateInstance<SkeletonAsset>();
characterRig.name = assetName + " Skeleton";
var bones = GetDataProvider<ICharacterDataProvider>().GetCharacterData().bones;
characterRig.SetSpriteBones(bones);
ctx.AddObjectToAsset(m_SkeletonAssetName, characterRig);
}
}
ctx.SetMainObject(mainAsset);
}
Expand Down Expand Up @@ -727,7 +754,7 @@ bool shouldResliceFromLayer

bool characterMode
{
get { return mosaicMode && m_CharacterMode == true; }
get { return mosaicMode && m_CharacterMode; }
}

float definitionScale
Expand Down Expand Up @@ -796,7 +823,7 @@ void CreateBoneGO(int index, SpriteBone[] bones, BoneGO[] bonesGO, Transform def
{
go = go,
index = index
};
};
}

BoneGO[] CreateBonesGO(Transform root)
Expand Down Expand Up @@ -848,12 +875,13 @@ GameObject OnProducePaperDollPrefab(string assetname, Sprite[] sprites, SpriteLi
var boneGOs = CreateBonesGO(root.transform);
if (spriteLib != null)
root.AddComponent<SpriteLibrary>().spriteLibraryAsset = spriteLib;
var currentCharacterData = characterData;
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 spriteBones = currentCharacterData.parts.FirstOrDefault(x => new GUID(x.spriteId) == sprites[i].GetSpriteID()).bones;
var rootBone = root;
if (spriteBones != null && spriteBones.Any())
{
Expand Down Expand Up @@ -910,6 +938,7 @@ GameObject OnProducePrefab(string assetname, Sprite[] sprites, SpriteLibraryAsse
CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider<ICharacterDataProvider>().GetCharacterData()) : null;
if (sprites != null && sprites.Length > 0)
{
var currentCharacterData = characterData;
var spriteImportData = GetSpriteImportData();
root = new GameObject();
root.name = assetname + "_GO";
Expand Down Expand Up @@ -946,7 +975,7 @@ GameObject OnProducePrefab(string assetname, Sprite[] sprites, SpriteLibraryAsse
var spriteSkin = l.gameObject.AddComponent<SpriteSkin>();
if (spriteRenderer.sprite != null && spriteRenderer.sprite.GetBindPoses().Length > 0)
{
var spriteBones = m_CharacterData.parts.FirstOrDefault(x => new GUID(x.spriteId) == spriteRenderer.sprite.GetSpriteID()).bones.Where(x => x >= 0 && x < boneGOs.Length).Select(x => boneGOs[x]);
var spriteBones = currentCharacterData.parts.FirstOrDefault(x => new GUID(x.spriteId) == spriteRenderer.sprite.GetSpriteID()).bones.Where(x => x >= 0 && x < boneGOs.Length).Select(x => boneGOs[x]);
if (spriteBones.Any())
{
spriteSkin.rootBone = spriteBones.OrderBy(x => x.index).First().go.transform;
Expand Down Expand Up @@ -1158,10 +1187,6 @@ internal 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;
}
if (typeof(T) == typeof(ISecondaryTextureDataProvider))
{
return new SecondaryTextureDataProvider() { dataProvider = this } as T;
Expand All @@ -1184,7 +1209,6 @@ internal bool HasDataProvider(Type type)
type == typeof(ISpriteOutlineDataProvider) ||
type == typeof(ISpritePhysicsOutlineDataProvider) ||
type == typeof(ITextureDataProvider) ||
type == typeof(ISpriteLibDataProvider) ||
type == typeof(ISecondaryTextureDataProvider))
{
return true;
Expand Down Expand Up @@ -1272,12 +1296,44 @@ SpriteRect[] ISpriteEditorDataProvider.GetSpriteRects()

List<SpriteMetaData> GetSpriteImportData()
{
return mosaicMode ? (characterMode ? m_RigSpriteImportData : m_MosaicSpriteImportData) : m_SpriteImportData;
if (mosaicMode)
{
if (characterMode)
{
if (skeletonAsset != null)
{
return m_SharedRigSpriteImportData;
}
return m_RigSpriteImportData;
}
return m_MosaicSpriteImportData;
}
return m_SpriteImportData;
}

private SkeletonAsset skeletonAsset
{
get
{
return AssetDatabase.LoadAssetAtPath<SkeletonAsset>(
AssetDatabase.GUIDToAssetPath(m_SkeletonAssetReferenceID));
}
}

internal List<PSDLayer> GetPSDLayers()
{
return mosaicMode ? (characterMode ? m_RigPSDLayers : m_MosaicPSDLayers) : null;
if (mosaicMode)
{
if (characterMode)
{
if (skeletonAsset != null)
return m_SharedRigPSDLayers;
else
return m_RigPSDLayers;
}
return m_MosaicPSDLayers;
}
return null;
}

internal SpriteMetaData[] GetSpriteMetaData()
Expand All @@ -1290,6 +1346,8 @@ internal SpriteMetaData[] GetSpriteMetaData()
internal SpriteRect GetSpriteDataFromAllMode(GUID guid)
{
var spriteMetaData = m_RigSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
if(spriteMetaData == null)
spriteMetaData = m_SharedRigSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
if(spriteMetaData == null)
spriteMetaData = m_MosaicSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
if(spriteMetaData == null)
Expand Down Expand Up @@ -1356,8 +1414,19 @@ bool mosaicMode

internal CharacterData characterData
{
get { return m_CharacterData; }
set { m_CharacterData = value; }
get
{
if (skeletonAsset != null)
return m_SharedRigCharacterData;
return m_CharacterData;
}
set
{
if (skeletonAsset != null)
m_SharedRigCharacterData = value;
else
m_CharacterData = value;
}
}

internal Vector2Int documentSize
Expand All @@ -1378,7 +1447,7 @@ SpriteLibraryAsset ProduceSpriteLibAsset(Sprite[] sprites)
categoryList = x.labels.Select(y =>
{
var sprite = sprites.FirstOrDefault(z => z.GetSpriteID().ToString() == y.spriteId);
return new Categorylabel()
return new SpriteCategoryEntry()
{
name = y.name,
sprite = sprite
Expand All @@ -1404,5 +1473,20 @@ internal void ReadTextureSettings(TextureImporterSettings dest)
{
m_TextureImporterSettings.CopyTo(dest);
}

internal SpriteBone[] mainRigBones
{
get
{
var rig = skeletonAsset;
if (rig != null)
{
return rig.GetSpriteBones();
}

return null;
}
}

}
}
26 changes: 11 additions & 15 deletions Editor/PSDImporterDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,17 @@ public CharacterData GetCharacterData()
}
}


var cd = dataProvider.characterData;
cd.boneReadOnly = false;
var spriteBones = dataProvider.mainRigBones;
if (spriteBones != null)
{
cd.boneReadOnly = true;
cd.bones = spriteBones;
}


var parts = cd.parts == null ? new List<CharacterPart>() : cd.parts.ToList();
var spriteRects = dataProvider.GetSpriteMetaData();
parts.RemoveAll(x => Array.FindIndex(spriteRects, y => y.spriteID == new GUID(x.spriteId)) == -1);
Expand Down Expand Up @@ -263,8 +273,7 @@ public CharacterData GetCharacterData()
else
parts[srIndex] = cp;
}

var layers = dataProvider.GetPSDLayers();

parts.Sort((x, y) =>
{
return x.order.CompareTo(y.order);
Expand All @@ -283,17 +292,4 @@ public void SetCharacterData(CharacterData characterData)
dataProvider.characterData = characterData;
}
}

internal class SpriteLibraryDataProvider : PSDDataProvider, ISpriteLibDataProvider
{
public SpriteCategoryList GetSpriteCategoryList()
{
return dataProvider.spriteCategoryList;
}

public void SetSpriteCategoryList(SpriteCategoryList spriteCategoryList)
{
dataProvider.spriteCategoryList = spriteCategoryList;
}
}
}
Loading

0 comments on commit 88f7b5d

Please sign in to comment.