Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
## [2.0.4] - 2019-08-09
### Added
- Add related test packages
- Add support Secondary Texture Module in Sprite Editor Window

### Fixed
- Texture and SpriteLibraryAsset subassets in PSDImporter now follows the main asset's name.
  • Loading branch information
Unity Technologies committed Aug 8, 2019
1 parent 07e71d8 commit e47fc77
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 46 deletions.
12 changes: 8 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Changelog
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).
## [2.0.4] - 2019-08-09
### Added
- Add related test packages
- Add support Secondary Texture Module in Sprite Editor Window

### Fixed
- Texture and SpriteLibraryAsset subassets in PSDImporter now follows the main asset's name.

## [2.0.3] - 2019-07-20
### Changed
Expand Down Expand Up @@ -63,4 +67,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
25 changes: 12 additions & 13 deletions Documentation~/PSDImporter.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,36 @@

## Summary

The **PSD Importer** is a custom Asset Importer made to import Adobe Photoshop’s PSB files into Unity. The PSB file format is functionally identical to the more common Adobe PSD format, with the additional ability to support much larger images than the PSD format (up to 300,000 by 300,000 pixels in size).
The __PSD Importer__ is a custom Asset Importer made to import Adobe Photoshop’s PSB files into Unity. The PSB file format is functionally identical to the more common Adobe PSD format, with the additional ability to support much larger images than the PSD format (up to 300,000 by 300,000 pixels in size).

Users saving or converting their PSD working files to the PSB format can import their work with the PSD Importer, and take advantage of the additional functionality and features provided by the importer.

## Function
## Supported Functions and Modes

The importer currently supports 2 **Texture Modes** - [Default](https://docs.unity3d.com/Manual/TextureTypes.html#Default) and [Sprite](https://docs.unity3d.com/Manual/TextureTypes.html#Sprite). More Texture Modes will be supported in the future.
The importer currently supports 2 __Texture Modes__ - [Default](https://docs.unity3d.com/Manual/TextureTypes.html#Default) and [Sprite](https://docs.unity3d.com/Manual/TextureTypes.html#Sprite). More Texture Modes will be supported in the future.

The following Photoshop features are **not** supported by the PSD Importer **:**
The following Photoshop features are __not__ supported by the PSD Importer __:__

* Channels

* Blend Modes

* Layer Opacity

* Effects

You can associate additional Textures to Sprites generated by the PSD Importer, with the Sprite Editor’s [Secondary Textures](https://docs.unity3d.com/Manual/SpriteEditor-SecondaryTextures.html) module. A __Shader__ can then sample these secondary Textures to apply additional effects on the Sprite, such as normal mapping. Refer to Sprite Editor: Secondary Textures](https://docs.unity3d.com/Manual/SpriteEditor-SecondaryTextures.html) for more information.

## Inspector settings

### Texture Type - Default

This is the default **Texture Type** usage when an image is imported without a specific Texture Type selected. Refer to the documentation on [Texture Types](https://docs.unity3d.com/Manual/TextureTypes.html) for further information and details.
This is the default __Texture Type__ usage when an image is imported without a specific Texture Type selected. Refer to the documentation on [Texture Types](https://docs.unity3d.com/Manual/TextureTypes.html) for further information and details.

### Texture Type - Sprite (2D and UI)

![PSD Importer inspect settings](images/PSDImporter_settings.png)

To import a PSB file for character animation with the **2D Animation V2** package, set the __Texture Type__ to __Sprite (2D and UI)__ to do so.
To import a PSB file for character animation with the __2D Animation V2__ package, set the __Texture Type__ to __Sprite (2D and UI)__ to do so.

Property settings that are specific to the **PSD Importer** are marked by an *.
Property settings that are specific to the __PSD Importer__ are marked by an *.

| Property | Function |
| ------------------------------- | ------------------------------------------------------------ |
Expand All @@ -55,7 +54,7 @@ Property settings that are specific to the **PSD Importer** are marked by an *.

## SpriteRect data

The **PSD Importer** can store 4 possible sets of SpriteRect data, depending on the properties selected when importing an image.
The __PSD Importer__ can store 4 possible sets of SpriteRect data, depending on the properties selected when importing an image.

The 4 sets are created by enabling the following property combinations:

Expand Down Expand Up @@ -102,11 +101,11 @@ When this is selected, layers that are hidden are imported. The behavior is iden

### Mosaic<a name="Mosaic"></a>

When **Mosaic** is selected, all layers in the PSB file will be imported as separate Sprites.
When __Mosaic__ is selected, all layers in the PSB file will be imported as separate Sprites.

### Character Rig<a name="CharRig"></a>

When this is selected, a Prefab is generated containing a Sprite GameObject with the SpriteRenderer component. If the Sprite contains bone and skin data, the **Sprite Skin** component is added as well. The name of the GameObject is the same as the name specified in it's SpriteRect.
When this is selected, a Prefab is generated containing a Sprite GameObject with the SpriteRenderer component. If the Sprite contains bone and skin data, the __Sprite Skin__ component is added as well. The name of the GameObject is the same as the name specified in it's SpriteRect.

### Use Layer Grouping<a name="Hierarchy"></a>

Expand Down
65 changes: 42 additions & 23 deletions Editor/PSDImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ public int textureActualHeight
[SerializeField]
string m_SpriteLibAssetName = null;

[SerializeField]
SecondarySpriteTexture[] m_SecondarySpriteTextures;

public PSDImporter()
{
m_TextureImporterSettings = new TextureImporterSettings();
Expand Down Expand Up @@ -294,6 +297,7 @@ TextureGenerationOutput ImportTexture(AssetImportContext ctx, NativeArray<Color3
textureSpriteSettings.qualifyForPacking = !string.IsNullOrEmpty(m_SpritePackingTag);
textureSpriteSettings.spriteSheetData = new UnityEditor.Experimental.AssetImporters.SpriteImportData[spriteCount];
textureSettings.npotScale = TextureImporterNPOTScale.None;
textureSettings.secondaryTextures = secondaryTextures;
var spriteImportData = GetSpriteImportData();
for (int i = 0; i < spriteCount; ++i)
{
Expand Down Expand Up @@ -543,9 +547,16 @@ void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
throw new Exception("Texture import fail");
}

var assetName = GetUniqueName(System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath), assetNameHash, true);
// Setup all fixed name on the hash table
if (string.IsNullOrEmpty(m_TextureAssetName))
m_TextureAssetName = GetUniqueName(System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath), assetNameHash, true);
output.texture.name = m_TextureAssetName;
m_TextureAssetName = GetUniqueName(string.Format("{0} Texture",assetName), assetNameHash, true);
if (string.IsNullOrEmpty(m_PrefabAssetName))
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);

output.texture.name = assetName;
ctx.AddObjectToAsset(m_TextureAssetName, output.texture, output.thumbNail);
UnityEngine.Object mainAsset = output.texture;

Expand All @@ -563,9 +574,6 @@ void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
prefab = OnProducePrefab(m_TextureAssetName, output.sprites, slAsset);
if (prefab != null)
{
if (string.IsNullOrEmpty(m_PrefabAssetName))
m_PrefabAssetName = GetUniqueName(prefab.name, assetNameHash, true, prefab);

ctx.AddObjectToAsset(m_PrefabAssetName, prefab);
mainAsset = prefab;
}
Expand All @@ -579,8 +587,7 @@ void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)

if (slAsset != null)
{
if (string.IsNullOrEmpty(m_SpriteLibAssetName))
m_SpriteLibAssetName = GetUniqueName(slAsset.name, assetNameHash, true, slAsset);
slAsset.name = assetName;
ctx.AddObjectToAsset(m_SpriteLibAssetName, slAsset);
}
}
Expand Down Expand Up @@ -789,7 +796,7 @@ GameObject OnProducePaperDollPrefab(string assetname, Sprite[] sprites, SpriteLi
{
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;
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 = "";
Expand Down Expand Up @@ -833,7 +840,7 @@ GameObject OnProducePrefab(string assetname, Sprite[] sprites, SpriteLibraryAsse
spriteRenderer.sortingOrder = psdLayers.Count - i;
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 / sprite.pixelsPerUnit;
spriteMetaData.rect.y - uvTransform.y + (spriteMetaData.pivot.y * spriteMetaData.rect.height)) * definitionScale / sprite.pixelsPerUnit;
l.gameObject.transform.position = new Vector3(outlineOffset.x, outlineOffset.y, 0);

if (characterSkeleton != null)
Expand Down Expand Up @@ -1047,6 +1054,10 @@ public T GetDataProvider<T>() where T : class
{
return new SpriteLibraryDataProvider() { dataProvider = this } as T;
}
if (typeof(T) == typeof(ISecondaryTextureDataProvider))
{
return new SecondaryTextureDataProvider() { dataProvider = this } as T;
}
else
return this as T;
}
Expand All @@ -1060,7 +1071,8 @@ public bool HasDataProvider(Type type)
type == typeof(ISpriteOutlineDataProvider) ||
type == typeof(ISpritePhysicsOutlineDataProvider) ||
type == typeof(ITextureDataProvider) ||
type == typeof(ISpriteLibDataProvider))
type == typeof(ISpriteLibDataProvider) ||
type == typeof(ISecondaryTextureDataProvider))
{
return true;
}
Expand Down Expand Up @@ -1243,26 +1255,33 @@ SpriteLibraryAsset ProduceSpriteLibAsset(Sprite[] sprites)
return null;
var sla = ScriptableObject.CreateInstance<SpriteLibraryAsset>();
sla.name = "Sprite Lib";
sla.labels = m_SpriteCategoryList.categories.Select(x =>
new SpriteLibCategory()
{
name = x.name,
categoryList = x.labels.Select(y =>
sla.categories = m_SpriteCategoryList.categories.Select(x =>
new SpriteLibCategory()
{
var sprite = sprites.FirstOrDefault(z => z.GetSpriteID().ToString() == y.spriteId);
return new Categorylabel()
name = x.name,
categoryList = x.labels.Select(y =>
{
name = y.name,
sprite = sprite
};
}).ToList()
}).ToList();
if (sla.labels.Count > 0)
var sprite = sprites.FirstOrDefault(z => z.GetSpriteID().ToString() == y.spriteId);
return new Categorylabel()
{
name = y.name,
sprite = sprite
};
}).ToList()
}).ToList();
sla.categories.RemoveAll(x => x.categoryList.Count == 0);
if (sla.categories.Count > 0)
{
sla.UpdateHashes();
return sla;
}
return null;
}

internal SecondarySpriteTexture[] secondaryTextures
{
get { return m_SecondarySpriteTextures; }
set { m_SecondarySpriteTextures = value; }
}
}
}
11 changes: 10 additions & 1 deletion Editor/PSDImporterDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public Texture2D GetReadableTexture2D()
{
m_ReadableTexture = InternalEditorBridge.CreateTemporaryDuplicate(texture, texture.width, texture.height);
if (m_ReadableTexture != null)
m_ReadableTexture.filterMode = FilterMode.Point;
m_ReadableTexture.filterMode = texture.filterMode;
}
return m_ReadableTexture;
}
Expand All @@ -72,6 +72,15 @@ public void GetTextureActualWidthAndHeight(out int width, out int height)
}
}

internal class SecondaryTextureDataProvider : PSDDataProvider, ISecondaryTextureDataProvider
{
public SecondarySpriteTexture[] textures
{
get { return dataProvider.secondaryTextures; }
set { dataProvider.secondaryTextures = value; }
}
}

internal class SpriteOutlineDataProvider : PSDDataProvider, ISpriteOutlineDataProvider
{
public List<Vector2[]> GetOutlines(GUID guid)
Expand Down
20 changes: 20 additions & 0 deletions Editor/PSDImporterEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,26 @@ void EnumPopup(SerializedProperty property, System.Type type, GUIContent label)
System.Enum.GetValues(type) as int[]);
}

void ExportMosaicTexture()
{
var assetPath = ((AssetImporter)target).assetPath;
var texture2D = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath);
if (texture2D == null)
return;
if (!texture2D.isReadable)
texture2D = InternalEditorBridge.CreateTemporaryDuplicate(texture2D, texture2D.width, texture2D.height);
var pixelData = texture2D.GetPixels();
texture2D = new Texture2D(texture2D.width, texture2D.height);
texture2D.SetPixels(pixelData);
texture2D.Apply();
byte[] bytes = texture2D.EncodeToPNG();
var fileName = Path.GetFileNameWithoutExtension(assetPath);
var filePath = Path.GetDirectoryName(assetPath);
var savePath = Path.Combine(filePath, fileName + ".png");
File.WriteAllBytes(savePath, bytes);
AssetDatabase.Refresh();
}

internal class Styles
{
public readonly GUIContent textureTypeTitle = new GUIContent("Texture Type", "What will this texture be used for?");
Expand Down
Loading

0 comments on commit e47fc77

Please sign in to comment.