diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ab0187..72fcc50 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,114 +1,123 @@
-# Changelog
-## [3.1.4] - 2020-04-09
-### Fixed
-- Fix PSD import issues with PSD file without unique layer id
-- Fix crash on importing huge PSD files
-- Fix metafile not updated when reimporting
-- Fix error when importing PSB files with 32-bit color
-
-### Changed
-- Improve PSD file import performance
-
-## [3.1.3] - 2020-03-20
-### Changed
-- Update 2D Animation dependency
-
-## [3.1.2] - 2020-02-27
-### Fixed
-- Fixed broken documentation links in inspectors
-- Fixed empty GameObjects created in certain cases
-
-## [3.1.1] - 2020-01-09
-### Fixed
-- Fix wrong dependency version
-
-## [3.1.0] - 2019-12-16
-### Added
-- Expose PSDImporter class to be accessible via scripting
-- Added example in manual to show how to set PSDImporter as default importer for PSD files.
-
-## [3.0.0] - 2019-11-06
-### Changed
-- Update version number for Unity 2020.1
-- Update documentation
-
-## [2.0.6] - 2019-10-18
-### Fixed
-- Fixed SpriteRect name clash when Photoshop layer is renamed to the same name as an exisiting user created SpriteRect
-
-## [2.0.5] - 2019-08-06
-### Fixed
-- Physics Shape not saved into Sprite when importing with AssetDatabase V2
-
-### Added
-- Experimental feature to have Sprites with same name generated from source file
-- Support for providing Layer and Group order to Animation Skinning Module
-
-## [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
-- Update 2D Animation dependency
-
-## [2.0.2] - 2019-07-13
-### Changed
-- Mark package to support Unity 2019.3.0a10 onwards.
-
-## [2.0.1] - 2019-06-12
-### Changed
-- Update 2D Animation dependency
-
-## [2.0.0] - 2019-06-17
-### Changed
-- Remove preview tag
-- Remove experimental namespace
-
-## [1.2.0-preview.2] - 2019-06-07
-### Added
-- Change API to internal access
-- Only generate Sprite Library Asset if there is entry
-- Do not reset Reslice checkbox after Inspector apply
-
-## [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
-
-## [1.1.0-preview.2] - 2019-04-23
-### Added
-- Fix potential name clashing issues with ScriptedImporter
-- Fix Prefab asset using wrong name. Note this will break Prefab references if upgrading from previous versions.
-
-## [1.1.0-preview.1] - 2019-02-19
-### Added
-- Update dependency for 2019.1 support
-
-## [1.0.0-preview.3] - 2019-02-19
-### Added
-- Fix compilation error in .NET 3.5
-
-## [1.0.0-preview.2] - 2019-01-25
-### Added
-- Fix unable to rig Sprites created manually
-- Remove legacy packing tag
-- Default Texture Type is changed to 'Sprite (2D and UI)'
-- Default Sprite Mode is changed to 'Multiple'
-
-## [1.0.0-preview.1] - 2018-11-20
-### Added
-- New release
-- ScriptedImporter for importing Adobe Photoshop file
-- Supports handling of Adobe Photoshop layers
- - Creates Sprites from individual layers
- - 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
+# Changelog
+
+## [4.0.0] - 2020-05-11
+### Changed
+- Version bump for Unity 2020.2
+
+## [3.1.4] - 2020-04-09
+### Fixed
+- Fix PSD import issues with PSD file without unique layer id
+- Fix crash on importing huge PSD files
+- Fix metafile not updated when reimporting
+- Fix error when importing PSB files with 32-bit color
+
+### Changed
+- Improve PSD file import performance
+
+## [3.1.3] - 2020-03-20
+### Changed
+- Update 2D Animation dependency
+
+## [4.0.0] - 2020-03-11
+### Changed
+- Version bump for Unity 2020.2
+
+## [3.1.2] - 2020-02-27
+### Fixed
+- Fixed broken documentation links in inspectors
+- Fixed empty GameObjects created in certain cases
+
+## [3.1.1] - 2020-01-09
+### Fixed
+- Fix wrong dependency version
+
+## [3.1.0] - 2019-12-16
+### Added
+- Expose PSDImporter class to be accessible via scripting
+- Added example in manual to show how to set PSDImporter as default importer for PSD files.
+
+## [3.0.0] - 2019-11-06
+### Changed
+- Update version number for Unity 2020.1
+- Update documentation
+
+## [2.0.6] - 2019-10-18
+### Fixed
+- Fixed SpriteRect name clash when Photoshop layer is renamed to the same name as an exisiting user created SpriteRect
+
+## [2.0.5] - 2019-08-06
+### Fixed
+- Physics Shape not saved into Sprite when importing with AssetDatabase V2
+
+### Added
+- Experimental feature to have Sprites with same name generated from source file
+- Support for providing Layer and Group order to Animation Skinning Module
+
+## [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
+- Update 2D Animation dependency
+
+## [2.0.2] - 2019-07-13
+### Changed
+- Mark package to support Unity 2019.3.0a10 onwards.
+
+## [2.0.1] - 2019-06-12
+### Changed
+- Update 2D Animation dependency
+
+## [2.0.0] - 2019-06-17
+### Changed
+- Remove preview tag
+- Remove experimental namespace
+
+## [1.2.0-preview.2] - 2019-06-07
+### Added
+- Change API to internal access
+- Only generate Sprite Library Asset if there is entry
+- Do not reset Reslice checkbox after Inspector apply
+
+## [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
+
+## [1.1.0-preview.2] - 2019-04-23
+### Added
+- Fix potential name clashing issues with ScriptedImporter
+- Fix Prefab asset using wrong name. Note this will break Prefab references if upgrading from previous versions.
+
+## [1.1.0-preview.1] - 2019-02-19
+### Added
+- Update dependency for 2019.1 support
+
+## [1.0.0-preview.3] - 2019-02-19
+### Added
+- Fix compilation error in .NET 3.5
+
+## [1.0.0-preview.2] - 2019-01-25
+### Added
+- Fix unable to rig Sprites created manually
+- Remove legacy packing tag
+- Default Texture Type is changed to 'Sprite (2D and UI)'
+- Default Sprite Mode is changed to 'Multiple'
+
+## [1.0.0-preview.1] - 2018-11-20
+### Added
+- New release
+- ScriptedImporter for importing Adobe Photoshop file
+- Supports handling of Adobe Photoshop layers
+ - Creates Sprites from individual layers
+ - 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
diff --git a/CHANGELOG.md.meta b/CHANGELOG.md.meta
index d288b53..6d4519a 100644
--- a/CHANGELOG.md.meta
+++ b/CHANGELOG.md.meta
@@ -1,7 +1,7 @@
-fileFormatVersion: 2
-guid: 2e891b338ba9c514b871d785976f600e
-TextScriptImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 2e891b338ba9c514b871d785976f600e
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Documentation~/PSDImporter.md b/Documentation~/PSDImporter.md
index ceb6e5d..bd5d7df 100644
--- a/Documentation~/PSDImporter.md
+++ b/Documentation~/PSDImporter.md
@@ -1,222 +1,222 @@
-# Summary
-
-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.
-
-## Non-importable Photoshop effects
-
-The PSD Importer only supports two [Texture Modes](https://docs.unity3d.com/Manual/TextureTypes.html): [Default](https://docs.unity3d.com/Manual/TextureTypes.html#Default) and [Sprite](https://docs.unity3d.com/Manual/TextureTypes.html#Sprite). Other Texture Modes might be supported in the future.
-
-The following Photoshop features are not supported by the PSD Importer and it ignores the following layer effects and features while it generates Sprites:
-
-* Channels
-
-* Blend Modes
-
-* Layer Opacity
-
-* Effects
-
-You can also add additional Textures to the Sprites with the [Sprite Edito](https://docs.unity3d.com/Manual/SpriteEditor.html)r’s [Secondary Textures](https://docs.unity3d.com/Manual/SpriteEditor-SecondaryTextures.html) module. Shaders can sample these Secondary Textures to apply additional effects to the Sprite, such as normal mapping. For more information, see documentation on [Sprite Editor: Secondary Textures](https://docs.unity3d.com/Manual/SpriteEditor-SecondaryTextures.html).
-
-## Inspector properties
-
-After importing a .psb file into your Project, select the Asset file to find the following properties in its Inspector window.
-
-### Texture Type - Default
-
-This is the default Texture Type that Unity uses when you import an image without a specific Texture Type selected. For more information, refer to the documentation on [Texture Types](https://docs.unity3d.com/Manual/TextureTypes.html).
-
-### Texture Type - Sprite (2D and UI)
-
-![](images/propertysettings.png)
_Importer Inspector properties_
-
-Set the Texture Type to __Sprite (2D and UI)__ when you want to import a .psb file with character graphics on multiple layers. The following property settings are available:
-
-| Property | Function |
-| ------------------------------------------------------------ | ------------------------------------------------------------ |
-| __Texture Type__ | Select [Sprite (2D and UI)](https://docs.unity3d.com/Manual/TextureTypes.html#Sprite) to import the Texture as a [Sprite](https://docs.unity3d.com/Manual/Sprites.html). This is required to begin using the imported images with the [2D Animation](https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/) package. |
-| __Sprite Mode__ | Use this property to specify how Unity extracts the Sprite graphic from the image. The default option is __Multiple__. |
-| Single | Choose this option if the imported image contains a single element. |
-| Multiple | This is the default option. Choose this option if the imported image contains multiple elements. Choose this option when importing artwork meant for animation with the [2D Animation](https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/) package. |
-| __Pixels Per Unit__ | The number of pixels that equal to one Unity unit. |
-| __Mesh Type__ | This defines the __Mesh__ type that Unity generates for the __Sprite__. This is set to __Tight__ by default. |
-| [Full Rect](https://docs.unity3d.com/Documentation/ScriptReference/SpriteMeshType.FullRect.html) | Unity maps the Sprite onto a rectangular Mesh. |
-| [Tight](https://docs.unity3d.com/Documentation/ScriptReference/SpriteMeshType.Tight.html) | Unity generates a Mesh based on the outline of the Sprite. If the Sprite is smaller than 32 x 32 pixels, Unity always maps it onto a __Full Rect__ quad Mesh, even if you select __Tight__. |
-| [__Extrude Edges__](https://docs.unity3d.com/Manual/Glossary.html#ExtrudeEdges) | Use the slider to determine how much to extend the Mesh from the edge of the Sprite. |
-| __Import Hidden__ | Enable this property to include the hidden [layers](https://helpx.adobe.com/photoshop/using/layer-basics.html#layers_panel_overview) of the .psb file in the import. This produces the same import result as making all layers visible in the source file unhiding all layers in the source file before you importing it into Unity. Clear this option if you want to only import the visible layers in the .psb file. |
-| __Mosaic__ | This setting is only available if you set the __Texture Type__ to __Multiple__. Enable this setting to make the PSD Importer generate Sprites from the imported layers and combine them into a single Texture in a Sprite sheet layout. |
-| [__Character Rig__](#Rig) | Enable this property to make the importer generate a [Prefab](https://docs.unity3d.com/Manual/Prefabs.html) based on the imported source file. The PSD Importer generates Sprites from the imported layers of the source file, and the Sprites’ [hierarchy](https://docs.unity3d.com/Manual/Hierarchy.html) and positions are based on their [layer hierarchy](https://helpx.adobe.com/photoshop/using/layer-basics.html#layers_panel_overview) and their positions in the .psb file. |
-| __Use Layer Grouping__ | This setting is only available when you enable __Character Rig__. Enable this setting to make the importer generate a Prefab that follows the layer and grouping hierarchy of the imported .psb. file. |
-| __Pivot__ | Choose the pivot point of the Sprite. |
-| Custom | Define the X and Y coordinates of a custom __Pivot__ location. |
-| [__Reslice__](#Reslice) | Available only when you enable __Mosaic__. Enable this setting to regenerate the Sprite from the imported layers and clear any changes you have made to the Sprite and its metadata. |
-| __Experimental__ | The following feature is experimental and might be changed or removed in the future. It is only available for the following Editor and package versions:
- __Unity 2019.2__: 2D PSD Importer version 1.2.0-preview.4 or newer.
- __Unity 2019.3__: 2D PSD Importer version 2.0.5 or newer. |
-| [Keep Duplicate Name](#Duplicate) | Enable this setting to make the PSD Importer generate Sprites from the source files with the exact same name as their source layers, even when there are multiple layers with the same name. |
-
-
-
-## Property details
-
-### Character Rig
-
-The __Character Rig__ setting makes the PSD Importer generate a Prefab that contains [Sprites](https://docs.unity3d.com/Manual/Sprites.html) it generates from each layer of the imported source file. The PSD Importer automatically gives the Sprites an [Order in Layer](https://docs.unity3d.com/Manual/2DSorting.html#sortlayer) value that sorts them according to the layer hierarchy in the source file. This ensures that Unity recreates the character artwork in the correct order in the Prefab.
-
-The name of each Sprite in the Prefab is the same as their respective source layer, unless a [name collision error](#NameCollision) occurs, which is usually due to duplicate names in the source layers.
-
-If the Sprite contains bone or weight data, the PSD Importer automatically adds the __Sprite Skin__ component to it. This happens if the Sprite has been [rigged](https://docs.unity3d.com/Packages/com.unity.2d.animation@3.0/manual/CharacterRig.html) with bones and weights in the [Skinning Editor](https://docs.unity3d.com/Packages/com.unity.2d.animation@3.0/manual/SkinningEditor.html) already and the source file is being reimported, or you have manually [copied and pasted](https://docs.unity3d.com/Packages/com.unity.2d.animation@3.0/manual/CopyPasteSkele.html) the bone and weight data onto the Sprites.
-
-Refer to the examples below of a character designed in Photoshop with its various parts and limbs separated onto different layers.
-
-![](images/PhotoshopSetup.png)
_Character artwork in Photoshop with different parts separated into different Photoshop layers._
-
-![](images/LayerHierarchy.png)
_The generated Prefab with Sprites sorted according to the source file’s layer hierarchy._
-
-![](images/LayerGrouping.png)
_The Prefab with the Layer Grouping setting enabled._
-
-### Reslice
-
-Enable this setting to discard all user modifications for the current set of SpriteRect data and regenerate all SpriteRects based on the current source file. Extra SpriteRect metadata (such as weights and bones data) persist if they remain valid with the regenerated SpriteRects.
-
-
-
-## How the PSD Importer uses SpriteRect data
-
-The PSD Importer can store four separate sets of [SpriteRect](https://docs.unity3d.com/ScriptReference/Sprite-rect.html) data, with a set for each of the four combinations of importer property settings below:
-
-1. __Sprite Mode__ set to __Single__.
-
-2. __Sprite Mode__ set to __Multiple__.
-
-3. __Sprite Mode__ set to __Multiple,__ and __Mosaic__ enabled.
-
-4. __Sprite Mode__ set to __Multiple__, and both __Mosaic__ and __Character Rig__ enabled.
-
-Each set of data is persistent, and does not affect or overwrite the data of other sets. This means you can save different SpriteRect data for different importer settings for the same source file. The SpriteRect data persists even if you modify the dimensions and position of images in the source file, as long as the original [Layer ID](https://github.com/adobe-photoshop/generator-core/wiki/Understanding-Layer-IDs-and-Layer-Indices) of the source layers remain the same.
-
-
-
-### Modifying the SpriteRect data
-
-The SpriteRect defines the location of the Sprite on the Texture that Unity generates from the imported source file. You can modify the location and size of each SpriteRect in the Sprite Editor.
-
-![](images/SpriteRect1.png)
_Original SpriteRect location of the ‘head’ Sprite on the combined Sprite sheet Texture._
-
-![](images/SpriteRect2.png)
_Drag the corners of the SpriteRect to modify its dimensions and location, or enter the coordinates and dimensions in the Sprite panel._
-
-A SpriteRect’s modified dimensions and location on the Texture is reflected for its respective Sprite in the Scene view.
-
-| ![](images/SpriteRect_table1.png) | ![](images/SpriteRect_table2.png) |
-| ------------------------------------------------------------ | ------------------------------------------------------------ |
-| _Original character prefab and its ‘head’ Sprite with unmodified SpriteRect data._ | _Character prefab with its ‘head’ Sprite’s SpriteRect data modified._ |
-
-
-When you enable the [Mosaic](#Mosaic) importer setting, the PSD Importer arranges the different layers of the source file together to form a single combined Texture when you import it. The importer generates a SpriteRect for each of these imported layers, and follows the position of its associated layer wherever it is placed in the Mosaic Texture.
-
-![](images/MovedSpriteRect.png)
_The SpriteRect of the ‘head’ layer. The SpriteRect has been moved from its original position._
-
-![](images/SpriteRect_following.png)
_The source file reimported after hiding several layers. The SpriteRect follows the ‘head’ layer’s placement in the new Texture._
-
-However, a SpriteRect’s size and position remains the same if you change the image or canvas size of its source layer in the source file. You must manually edit the size and position of the SpriteRect in the Sprite Editor, or select and apply the [Reslice](#heading=h.i7pxu2xdxrji) option to regenerate it from the source file.
-
-![](images/OriginalSpriteRect.png)
_Original position and size of the SpriteRect for the generated ‘head’ Sprite._
-
-![image alt text](images/IncreaseSize.png)
_Position and size of the SpriteRect remains the same after increasing the image size of its source layer._
-
-SpriteRect data persists until you manually delete the SpriteRect, or select the [Reslice](#heading=h.i7pxu2xdxrji) option and apply it in the importer settings. When you do this, Unity discards all user modifications for the current set of SpriteRect data and regenerates all the SpriteRects from the current source file.
-
-### Summary of source file modifications and their effects on SpriteRect data
-
-| __Modification to the source file__ | __Effect on SpriteRect data__ |
-| ----------------------------------------------- | ------------------------------------------------------------ |
-| __New layer added /layer visibility turned on__ | The PSD importer automatically generates a new Sprite from the new layer, or newly visible layer, with its associated SpriteRect. |
-| __Layer deleted /layer visibility turned off__ | The Sprite and SpriteRect that the PSD Importer generated from the deleted or previously visible layer are also deleted from the Project file. |
-| __Layer is renamed__ | By default, the SpriteRect copies the new name of its source layer. However if you rename the SpriteRect in the Sprite Editor, then it retains its modified name and does not copy the source layer’s new name. |
-| __Layer or canvas size changed__ | When a source layer is resized, the size and position of its related SpriteRect remains the same and does not reflect the changes made to its source layer. To make the SpriteRect reflect the changes made to its source layer, manually edit the SpriteRect’s dimensions in the Sprite Editor or select and apply the [Reslice](#Reslice) option in the PSD Importer settings. |
-
-
-
-## Name collision errors
-
-A name collision error can happen due to the following :
-
-1. Two or more layers in the imported source file have the same name. However, Photoshop [group layers](https://helpx.adobe.com/photoshop/using/selecting-grouping-linking-layers.html#group_and_link_layers) with the same names do not cause this issue.
-
-2. A new layer that the PSD Importer creates in the source file has the same name as a SpriteRect you have created or modified.
-
-3. A layer is renamed to the same name as a SpriteRect you have modified.
-
-4. A previously hidden layer is made visible and imported, and it has the same name as an existing SpriteRect.
-
-When a name collision occurs, one SpriteRect retains the original name while the other is appended with a running number. Which SpriteRect retains their original name is based on the following priority:
-
-1. A SpriteRect you have created or modified.
-
-2. The first layer in the source file, starting from the bottom of the layer stack.
-
-3. Currently existing SpriteRects in the Project.
-
-## Experimental feature: Keep duplicate names
-
-Unity’s default import behavior when there are duplicate names is to append "_[number]" to Sprites and SpriteRects it generates from source layers with identical names. Enable this experimental feature to instead have Unity give both Sprites/SpriteRects the exact same name as their source layer even if they have duplicate names.
-
-
-## PSD File Importer Override
-
-In Unity 2019.30f1, it is possible to use PSDImporter to import files with 'psd' extensions.
-To do that you will need to have custom scripts that allows you to do that by calling the `AssetDatabaseExperimental.SetImporterOverride` method.
-The following is an example on how to use the API
-
-#### PSDImporterOverride.cs
-```
-using System.IO;
-using UnityEditor.Experimental;
-using UnityEditor.Experimental.AssetImporters;
-using UnityEngine;
-
-namespace UnityEditor.U2D.PSD
-{
- [ScriptedImporter(1, "psd", AutoSelect = false)]
- internal class PSDImporterOverride : PSDImporter
- {
-
- [MenuItem("Assets/2D Importer", false, 30)]
- [MenuItem("Assets/2D Importer/Change PSD File Importer", false, 30)]
- static void ChangeImporter()
- {
- foreach (var obj in Selection.objects)
- {
- var path = AssetDatabase.GetAssetPath(obj);
- var ext = System.IO.Path.GetExtension(path);
- if (ext == ".psd")
- {
- var importer = AssetImporter.GetAtPath(path);
- if (importer is PSDImporterOverride)
- {
- Debug.Log(string.Format("{0} is now imported with TextureImporter", path));
- AssetDatabaseExperimental.ClearImporterOverride(path);
- }
- else
- {
- Debug.Log(string.Format("{0} is now imported with PSDImporter", path));
- AssetDatabaseExperimental.SetImporterOverride(path);
- }
- }
- }
- }
- }
-}
-```
-
-#### PSDImporterOverrideEditor.cs
-```
-namespace UnityEditor.U2D.PSD
-{
- [CustomEditor(typeof(UnityEditor.U2D.PSD.PSDImporterOverride))]
- internal class PSDImporterOverrideEditor : PSDImporterEditor
- {
- }
-
-}
+# Summary
+
+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.
+
+## Non-importable Photoshop effects
+
+The PSD Importer only supports two [Texture Modes](https://docs.unity3d.com/Manual/TextureTypes.html): [Default](https://docs.unity3d.com/Manual/TextureTypes.html#Default) and [Sprite](https://docs.unity3d.com/Manual/TextureTypes.html#Sprite). Other Texture Modes might be supported in the future.
+
+The following Photoshop features are not supported by the PSD Importer and it ignores the following layer effects and features while it generates Sprites:
+
+* Channels
+
+* Blend Modes
+
+* Layer Opacity
+
+* Effects
+
+You can also add additional Textures to the Sprites with the [Sprite Edito](https://docs.unity3d.com/Manual/SpriteEditor.html)r’s [Secondary Textures](https://docs.unity3d.com/Manual/SpriteEditor-SecondaryTextures.html) module. Shaders can sample these Secondary Textures to apply additional effects to the Sprite, such as normal mapping. For more information, see documentation on [Sprite Editor: Secondary Textures](https://docs.unity3d.com/Manual/SpriteEditor-SecondaryTextures.html).
+
+## Inspector properties
+
+After importing a .psb file into your Project, select the Asset file to find the following properties in its Inspector window.
+
+### Texture Type - Default
+
+This is the default Texture Type that Unity uses when you import an image without a specific Texture Type selected. For more information, refer to the documentation on [Texture Types](https://docs.unity3d.com/Manual/TextureTypes.html).
+
+### Texture Type - Sprite (2D and UI)
+
+![](images/propertysettings.png)
_Importer Inspector properties_
+
+Set the Texture Type to __Sprite (2D and UI)__ when you want to import a .psb file with character graphics on multiple layers. The following property settings are available:
+
+| Property | Function |
+| ------------------------------------------------------------ | ------------------------------------------------------------ |
+| __Texture Type__ | Select [Sprite (2D and UI)](https://docs.unity3d.com/Manual/TextureTypes.html#Sprite) to import the Texture as a [Sprite](https://docs.unity3d.com/Manual/Sprites.html). This is required to begin using the imported images with the [2D Animation](https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/) package. |
+| __Sprite Mode__ | Use this property to specify how Unity extracts the Sprite graphic from the image. The default option is __Multiple__. |
+| Single | Choose this option if the imported image contains a single element. |
+| Multiple | This is the default option. Choose this option if the imported image contains multiple elements. Choose this option when importing artwork meant for animation with the [2D Animation](https://docs.unity3d.com/Packages/com.unity.2d.animation@latest/) package. |
+| __Pixels Per Unit__ | The number of pixels that equal to one Unity unit. |
+| __Mesh Type__ | This defines the __Mesh__ type that Unity generates for the __Sprite__. This is set to __Tight__ by default. |
+| [Full Rect](https://docs.unity3d.com/Documentation/ScriptReference/SpriteMeshType.FullRect.html) | Unity maps the Sprite onto a rectangular Mesh. |
+| [Tight](https://docs.unity3d.com/Documentation/ScriptReference/SpriteMeshType.Tight.html) | Unity generates a Mesh based on the outline of the Sprite. If the Sprite is smaller than 32 x 32 pixels, Unity always maps it onto a __Full Rect__ quad Mesh, even if you select __Tight__. |
+| [__Extrude Edges__](https://docs.unity3d.com/Manual/Glossary.html#ExtrudeEdges) | Use the slider to determine how much to extend the Mesh from the edge of the Sprite. |
+| __Import Hidden__ | Enable this property to include the hidden [layers](https://helpx.adobe.com/photoshop/using/layer-basics.html#layers_panel_overview) of the .psb file in the import. This produces the same import result as making all layers visible in the source file unhiding all layers in the source file before you importing it into Unity. Clear this option if you want to only import the visible layers in the .psb file. |
+| __Mosaic__ | This setting is only available if you set the __Texture Type__ to __Multiple__. Enable this setting to make the PSD Importer generate Sprites from the imported layers and combine them into a single Texture in a Sprite sheet layout. |
+| [__Character Rig__](#Rig) | Enable this property to make the importer generate a [Prefab](https://docs.unity3d.com/Manual/Prefabs.html) based on the imported source file. The PSD Importer generates Sprites from the imported layers of the source file, and the Sprites’ [hierarchy](https://docs.unity3d.com/Manual/Hierarchy.html) and positions are based on their [layer hierarchy](https://helpx.adobe.com/photoshop/using/layer-basics.html#layers_panel_overview) and their positions in the .psb file. |
+| __Use Layer Grouping__ | This setting is only available when you enable __Character Rig__. Enable this setting to make the importer generate a Prefab that follows the layer and grouping hierarchy of the imported .psb. file. |
+| __Pivot__ | Choose the pivot point of the Sprite. |
+| Custom | Define the X and Y coordinates of a custom __Pivot__ location. |
+| [__Reslice__](#Reslice) | Available only when you enable __Mosaic__. Enable this setting to regenerate the Sprite from the imported layers and clear any changes you have made to the Sprite and its metadata. |
+| __Experimental__ | The following feature is experimental and might be changed or removed in the future. It is only available for the following Editor and package versions:
- __Unity 2019.2__: 2D PSD Importer version 1.2.0-preview.4 or newer.
- __Unity 2019.3__: 2D PSD Importer version 2.0.5 or newer. |
+| [Keep Duplicate Name](#Duplicate) | Enable this setting to make the PSD Importer generate Sprites from the source files with the exact same name as their source layers, even when there are multiple layers with the same name. |
+
+
+
+## Property details
+
+### Character Rig
+
+The __Character Rig__ setting makes the PSD Importer generate a Prefab that contains [Sprites](https://docs.unity3d.com/Manual/Sprites.html) it generates from each layer of the imported source file. The PSD Importer automatically gives the Sprites an [Order in Layer](https://docs.unity3d.com/Manual/2DSorting.html#sortlayer) value that sorts them according to the layer hierarchy in the source file. This ensures that Unity recreates the character artwork in the correct order in the Prefab.
+
+The name of each Sprite in the Prefab is the same as their respective source layer, unless a [name collision error](#NameCollision) occurs, which is usually due to duplicate names in the source layers.
+
+If the Sprite contains bone or weight data, the PSD Importer automatically adds the __Sprite Skin__ component to it. This happens if the Sprite has been [rigged](https://docs.unity3d.com/Packages/com.unity.2d.animation@3.0/manual/CharacterRig.html) with bones and weights in the [Skinning Editor](https://docs.unity3d.com/Packages/com.unity.2d.animation@3.0/manual/SkinningEditor.html) already and the source file is being reimported, or you have manually [copied and pasted](https://docs.unity3d.com/Packages/com.unity.2d.animation@3.0/manual/CopyPasteSkele.html) the bone and weight data onto the Sprites.
+
+Refer to the examples below of a character designed in Photoshop with its various parts and limbs separated onto different layers.
+
+![](images/PhotoshopSetup.png)
_Character artwork in Photoshop with different parts separated into different Photoshop layers._
+
+![](images/LayerHierarchy.png)
_The generated Prefab with Sprites sorted according to the source file’s layer hierarchy._
+
+![](images/LayerGrouping.png)
_The Prefab with the Layer Grouping setting enabled._
+
+### Reslice
+
+Enable this setting to discard all user modifications for the current set of SpriteRect data and regenerate all SpriteRects based on the current source file. Extra SpriteRect metadata (such as weights and bones data) persist if they remain valid with the regenerated SpriteRects.
+
+
+
+## How the PSD Importer uses SpriteRect data
+
+The PSD Importer can store four separate sets of [SpriteRect](https://docs.unity3d.com/ScriptReference/Sprite-rect.html) data, with a set for each of the four combinations of importer property settings below:
+
+1. __Sprite Mode__ set to __Single__.
+
+2. __Sprite Mode__ set to __Multiple__.
+
+3. __Sprite Mode__ set to __Multiple,__ and __Mosaic__ enabled.
+
+4. __Sprite Mode__ set to __Multiple__, and both __Mosaic__ and __Character Rig__ enabled.
+
+Each set of data is persistent, and does not affect or overwrite the data of other sets. This means you can save different SpriteRect data for different importer settings for the same source file. The SpriteRect data persists even if you modify the dimensions and position of images in the source file, as long as the original [Layer ID](https://github.com/adobe-photoshop/generator-core/wiki/Understanding-Layer-IDs-and-Layer-Indices) of the source layers remain the same.
+
+
+
+### Modifying the SpriteRect data
+
+The SpriteRect defines the location of the Sprite on the Texture that Unity generates from the imported source file. You can modify the location and size of each SpriteRect in the Sprite Editor.
+
+![](images/SpriteRect1.png)
_Original SpriteRect location of the ‘head’ Sprite on the combined Sprite sheet Texture._
+
+![](images/SpriteRect2.png)
_Drag the corners of the SpriteRect to modify its dimensions and location, or enter the coordinates and dimensions in the Sprite panel._
+
+A SpriteRect’s modified dimensions and location on the Texture is reflected for its respective Sprite in the Scene view.
+
+| ![](images/SpriteRect_table1.png) | ![](images/SpriteRect_table2.png) |
+| ------------------------------------------------------------ | ------------------------------------------------------------ |
+| _Original character prefab and its ‘head’ Sprite with unmodified SpriteRect data._ | _Character prefab with its ‘head’ Sprite’s SpriteRect data modified._ |
+
+
+When you enable the [Mosaic](#Mosaic) importer setting, the PSD Importer arranges the different layers of the source file together to form a single combined Texture when you import it. The importer generates a SpriteRect for each of these imported layers, and follows the position of its associated layer wherever it is placed in the Mosaic Texture.
+
+![](images/MovedSpriteRect.png)
_The SpriteRect of the ‘head’ layer. The SpriteRect has been moved from its original position._
+
+![](images/SpriteRect_following.png)
_The source file reimported after hiding several layers. The SpriteRect follows the ‘head’ layer’s placement in the new Texture._
+
+However, a SpriteRect’s size and position remains the same if you change the image or canvas size of its source layer in the source file. You must manually edit the size and position of the SpriteRect in the Sprite Editor, or select and apply the [Reslice](#heading=h.i7pxu2xdxrji) option to regenerate it from the source file.
+
+![](images/OriginalSpriteRect.png)
_Original position and size of the SpriteRect for the generated ‘head’ Sprite._
+
+![image alt text](images/IncreaseSize.png)
_Position and size of the SpriteRect remains the same after increasing the image size of its source layer._
+
+SpriteRect data persists until you manually delete the SpriteRect, or select the [Reslice](#heading=h.i7pxu2xdxrji) option and apply it in the importer settings. When you do this, Unity discards all user modifications for the current set of SpriteRect data and regenerates all the SpriteRects from the current source file.
+
+### Summary of source file modifications and their effects on SpriteRect data
+
+| __Modification to the source file__ | __Effect on SpriteRect data__ |
+| ----------------------------------------------- | ------------------------------------------------------------ |
+| __New layer added /layer visibility turned on__ | The PSD importer automatically generates a new Sprite from the new layer, or newly visible layer, with its associated SpriteRect. |
+| __Layer deleted /layer visibility turned off__ | The Sprite and SpriteRect that the PSD Importer generated from the deleted or previously visible layer are also deleted from the Project file. |
+| __Layer is renamed__ | By default, the SpriteRect copies the new name of its source layer. However if you rename the SpriteRect in the Sprite Editor, then it retains its modified name and does not copy the source layer’s new name. |
+| __Layer or canvas size changed__ | When a source layer is resized, the size and position of its related SpriteRect remains the same and does not reflect the changes made to its source layer. To make the SpriteRect reflect the changes made to its source layer, manually edit the SpriteRect’s dimensions in the Sprite Editor or select and apply the [Reslice](#Reslice) option in the PSD Importer settings. |
+
+
+
+## Name collision errors
+
+A name collision error can happen due to the following :
+
+1. Two or more layers in the imported source file have the same name. However, Photoshop [group layers](https://helpx.adobe.com/photoshop/using/selecting-grouping-linking-layers.html#group_and_link_layers) with the same names do not cause this issue.
+
+2. A new layer that the PSD Importer creates in the source file has the same name as a SpriteRect you have created or modified.
+
+3. A layer is renamed to the same name as a SpriteRect you have modified.
+
+4. A previously hidden layer is made visible and imported, and it has the same name as an existing SpriteRect.
+
+When a name collision occurs, one SpriteRect retains the original name while the other is appended with a running number. Which SpriteRect retains their original name is based on the following priority:
+
+1. A SpriteRect you have created or modified.
+
+2. The first layer in the source file, starting from the bottom of the layer stack.
+
+3. Currently existing SpriteRects in the Project.
+
+## Experimental feature: Keep duplicate names
+
+Unity’s default import behavior when there are duplicate names is to append "_[number]" to Sprites and SpriteRects it generates from source layers with identical names. Enable this experimental feature to instead have Unity give both Sprites/SpriteRects the exact same name as their source layer even if they have duplicate names.
+
+
+## PSD File Importer Override
+
+In Unity 2019.30f1, it is possible to use PSDImporter to import files with 'psd' extensions.
+To do that you will need to have custom scripts that allows you to do that by calling the `AssetDatabaseExperimental.SetImporterOverride` method.
+The following is an example on how to use the API
+
+#### PSDImporterOverride.cs
+```
+using System.IO;
+using UnityEditor.Experimental;
+using UnityEditor.Experimental.AssetImporters;
+using UnityEngine;
+
+namespace UnityEditor.U2D.PSD
+{
+ [ScriptedImporter(1, "psd", AutoSelect = false)]
+ internal class PSDImporterOverride : PSDImporter
+ {
+
+ [MenuItem("Assets/2D Importer", false, 30)]
+ [MenuItem("Assets/2D Importer/Change PSD File Importer", false, 30)]
+ static void ChangeImporter()
+ {
+ foreach (var obj in Selection.objects)
+ {
+ var path = AssetDatabase.GetAssetPath(obj);
+ var ext = System.IO.Path.GetExtension(path);
+ if (ext == ".psd")
+ {
+ var importer = AssetImporter.GetAtPath(path);
+ if (importer is PSDImporterOverride)
+ {
+ Debug.Log(string.Format("{0} is now imported with TextureImporter", path));
+ AssetDatabaseExperimental.ClearImporterOverride(path);
+ }
+ else
+ {
+ Debug.Log(string.Format("{0} is now imported with PSDImporter", path));
+ AssetDatabaseExperimental.SetImporterOverride(path);
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+#### PSDImporterOverrideEditor.cs
+```
+namespace UnityEditor.U2D.PSD
+{
+ [CustomEditor(typeof(UnityEditor.U2D.PSD.PSDImporterOverride))]
+ internal class PSDImporterOverrideEditor : PSDImporterEditor
+ {
+ }
+
+}
```
\ No newline at end of file
diff --git a/Editor.meta b/Editor.meta
index 8f026e5..9486471 100644
--- a/Editor.meta
+++ b/Editor.meta
@@ -1,8 +1,8 @@
-fileFormatVersion: 2
-guid: 23888dc58bcb0814389c9fd915521b77
-folderAsset: yes
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 23888dc58bcb0814389c9fd915521b77
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/Analytics.cs b/Editor/Analytics.cs
index 0ee3ff0..015c2f4 100644
--- a/Editor/Analytics.cs
+++ b/Editor/Analytics.cs
@@ -1,64 +1,64 @@
-using System;
-using PhotoshopFile;
-using UnityEngine;
-using UnityEngine.Analytics;
-
-namespace UnityEditor.U2D.PSD
-{
- [Serializable]
- internal struct PSDApplyEvent
- {
- public int instance_id;
- public int texture_type;
- public int sprite_mode;
- public bool mosaic_layer;
- public bool import_hidden_layer;
- public bool character_mode;
- public bool generate_go_hierarchy;
- public bool reslice_from_layer;
- public bool is_character_rigged;
- public SpriteAlignment character_alignment;
- public bool is_psd;
- public PsdColorMode color_mode;
-
- }
-
- internal interface IAnalytics
- {
- AnalyticsResult SendApplyEvent(PSDApplyEvent evt);
- }
-
- internal static class AnalyticFactory
- {
- static IAnalytics s_Analytics;
- static public IAnalytics analytics
- {
- get
- {
- if (s_Analytics == null)
- s_Analytics = new Analytics();
- return s_Analytics;
- }
- set { s_Analytics = value; }
- }
- }
-
- [InitializeOnLoad]
- internal class Analytics : IAnalytics
- {
- const int k_MaxEventsPerHour = 100;
- const int k_MaxNumberOfElements = 1000;
- const string k_VendorKey = "unity.2d.psdimporter";
- const int k_Version = 1;
-
- static Analytics()
- {
- EditorAnalytics.RegisterEventWithLimit("psdImporterApply", k_MaxEventsPerHour, k_MaxNumberOfElements, k_VendorKey, k_Version);
- }
-
- public AnalyticsResult SendApplyEvent(PSDApplyEvent evt)
- {
- return EditorAnalytics.SendEventWithLimit("psdImporterApply", evt, k_Version);
- }
- }
-}
+using System;
+using PhotoshopFile;
+using UnityEngine;
+using UnityEngine.Analytics;
+
+namespace UnityEditor.U2D.PSD
+{
+ [Serializable]
+ internal struct PSDApplyEvent
+ {
+ public int instance_id;
+ public int texture_type;
+ public int sprite_mode;
+ public bool mosaic_layer;
+ public bool import_hidden_layer;
+ public bool character_mode;
+ public bool generate_go_hierarchy;
+ public bool reslice_from_layer;
+ public bool is_character_rigged;
+ public SpriteAlignment character_alignment;
+ public bool is_psd;
+ public PsdColorMode color_mode;
+
+ }
+
+ internal interface IAnalytics
+ {
+ AnalyticsResult SendApplyEvent(PSDApplyEvent evt);
+ }
+
+ internal static class AnalyticFactory
+ {
+ static IAnalytics s_Analytics;
+ static public IAnalytics analytics
+ {
+ get
+ {
+ if (s_Analytics == null)
+ s_Analytics = new Analytics();
+ return s_Analytics;
+ }
+ set { s_Analytics = value; }
+ }
+ }
+
+ [InitializeOnLoad]
+ internal class Analytics : IAnalytics
+ {
+ const int k_MaxEventsPerHour = 100;
+ const int k_MaxNumberOfElements = 1000;
+ const string k_VendorKey = "unity.2d.psdimporter";
+ const int k_Version = 1;
+
+ static Analytics()
+ {
+ EditorAnalytics.RegisterEventWithLimit("psdImporterApply", k_MaxEventsPerHour, k_MaxNumberOfElements, k_VendorKey, k_Version);
+ }
+
+ public AnalyticsResult SendApplyEvent(PSDApplyEvent evt)
+ {
+ return EditorAnalytics.SendEventWithLimit("psdImporterApply", evt, k_Version);
+ }
+ }
+}
diff --git a/Editor/Analytics.cs.meta b/Editor/Analytics.cs.meta
index 746b657..42d8343 100644
--- a/Editor/Analytics.cs.meta
+++ b/Editor/Analytics.cs.meta
@@ -1,11 +1,11 @@
-fileFormatVersion: 2
-guid: 9c2f00f81f6586446909cd337be9a6c7
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 9c2f00f81f6586446909cd337be9a6c7
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/AssemblyInfo.cs b/Editor/AssemblyInfo.cs
index 9b1adea..4061cce 100644
--- a/Editor/AssemblyInfo.cs
+++ b/Editor/AssemblyInfo.cs
@@ -1,2 +1,2 @@
-using System.Runtime.CompilerServices;
-[assembly: InternalsVisibleTo("Unity.2D.Psdimporter.Tests.EditorTests")]
+using System.Runtime.CompilerServices;
+[assembly: InternalsVisibleTo("Unity.2D.Psdimporter.Tests.EditorTests")]
diff --git a/Editor/AssemblyInfo.cs.meta b/Editor/AssemblyInfo.cs.meta
index 9ff8a2f..ed3981f 100644
--- a/Editor/AssemblyInfo.cs.meta
+++ b/Editor/AssemblyInfo.cs.meta
@@ -1,11 +1,11 @@
-fileFormatVersion: 2
-guid: 3073eb37881ce394f83060fd73c2d98d
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 3073eb37881ce394f83060fd73c2d98d
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDImportPostProcessor.cs b/Editor/PSDImportPostProcessor.cs
index 0bfb1e4..3726445 100644
--- a/Editor/PSDImportPostProcessor.cs
+++ b/Editor/PSDImportPostProcessor.cs
@@ -1,48 +1,72 @@
-using System.Collections.Generic;
-using System.Linq;
-using UnityEditor.U2D;
-using UnityEditor.U2D.Sprites;
-using UnityEngine;
-
-namespace UnityEditor.U2D.PSD
-{
- internal class PSDImportPostProcessor : AssetPostprocessor
- {
- void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
- {
- var dataProviderFactories = new SpriteDataProviderFactories();
- dataProviderFactories.Init();
- ISpriteEditorDataProvider importer = dataProviderFactories.GetSpriteEditorDataProviderFromObject(AssetImporter.GetAtPath(assetPath));
- if (importer != null)
- {
- importer.InitSpriteEditorDataProvider();
- var physicsOutlineDataProvider = importer.GetDataProvider();
- var textureDataProvider = importer.GetDataProvider();
- int actualWidth = 0, actualHeight = 0;
- textureDataProvider.GetTextureActualWidthAndHeight(out actualWidth, out actualHeight);
- float definitionScaleW = (float)texture.width / actualWidth;
- float definitionScaleH = (float)texture.height / actualHeight;
- float definitionScale = Mathf.Min(definitionScaleW, definitionScaleH);
- foreach (var sprite in sprites)
- {
- var guid = sprite.GetSpriteID();
- var outline = physicsOutlineDataProvider.GetOutlines(guid);
- var outlineOffset = sprite.rect.size / 2;
- if (outline != null && outline.Count > 0)
- {
- var convertedOutline = new Vector2[outline.Count][];
- for (int i = 0; i < outline.Count; ++i)
- {
- convertedOutline[i] = new Vector2[outline[i].Length];
- for (int j = 0; j < outline[i].Length; ++j)
- {
- convertedOutline[i][j] = outline[i][j] * definitionScale + outlineOffset;
- }
- }
- sprite.OverridePhysicsShape(convertedOutline);
- }
- }
- }
- }
- }
-}
+using System.Collections.Generic;
+using System.Linq;
+using UnityEditor.U2D;
+using UnityEditor.U2D.Sprites;
+using UnityEngine;
+
+namespace UnityEditor.U2D.PSD
+{
+ internal class PSDImportPostProcessor : AssetPostprocessor
+ {
+ private static string s_CurrentApplyAssetPath = null;
+
+ void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
+ {
+ var dataProviderFactories = new SpriteDataProviderFactories();
+ dataProviderFactories.Init();
+ ISpriteEditorDataProvider importer = dataProviderFactories.GetSpriteEditorDataProviderFromObject(AssetImporter.GetAtPath(assetPath));
+ if (importer != null)
+ {
+ importer.InitSpriteEditorDataProvider();
+ var physicsOutlineDataProvider = importer.GetDataProvider();
+ var textureDataProvider = importer.GetDataProvider();
+ int actualWidth = 0, actualHeight = 0;
+ textureDataProvider.GetTextureActualWidthAndHeight(out actualWidth, out actualHeight);
+ float definitionScaleW = (float)texture.width / actualWidth;
+ float definitionScaleH = (float)texture.height / actualHeight;
+ float definitionScale = Mathf.Min(definitionScaleW, definitionScaleH);
+ foreach (var sprite in sprites)
+ {
+ var guid = sprite.GetSpriteID();
+ var outline = physicsOutlineDataProvider.GetOutlines(guid);
+ var outlineOffset = sprite.rect.size / 2;
+ if (outline != null && outline.Count > 0)
+ {
+ var convertedOutline = new Vector2[outline.Count][];
+ for (int i = 0; i < outline.Count; ++i)
+ {
+ convertedOutline[i] = new Vector2[outline[i].Length];
+ for (int j = 0; j < outline[i].Length; ++j)
+ {
+ convertedOutline[i][j] = outline[i][j] * definitionScale + outlineOffset;
+ }
+ }
+ sprite.OverridePhysicsShape(convertedOutline);
+ }
+ }
+ }
+ }
+
+ public static string currentApplyAssetPath
+ {
+ set { s_CurrentApplyAssetPath = value; }
+ }
+ static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromPath)
+ {
+ if (!string.IsNullOrEmpty(s_CurrentApplyAssetPath))
+ {
+ foreach (var asset in importedAssets)
+ {
+ if (asset == s_CurrentApplyAssetPath)
+ {
+ var obj = AssetDatabase.LoadMainAssetAtPath(asset);
+ Selection.activeObject = obj;
+ Unsupported.SceneTrackerFlushDirty();
+ s_CurrentApplyAssetPath = null;
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Editor/PSDImportPostProcessor.cs.meta b/Editor/PSDImportPostProcessor.cs.meta
index 76ceb50..370ee65 100644
--- a/Editor/PSDImportPostProcessor.cs.meta
+++ b/Editor/PSDImportPostProcessor.cs.meta
@@ -1,11 +1,11 @@
-fileFormatVersion: 2
-guid: 96feaa0b12eabfe44b345be97ea0029c
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 96feaa0b12eabfe44b345be97ea0029c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDImporter.cs b/Editor/PSDImporter.cs
index 278fa4d..0314a6b 100644
--- a/Editor/PSDImporter.cs
+++ b/Editor/PSDImporter.cs
@@ -1,1380 +1,1408 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using PDNWrapper;
-using UnityEngine;
-using Unity.Collections;
-using System.Linq;
-using UnityEditor.Experimental.AssetImporters;
-using UnityEditor.U2D.Animation;
-using UnityEditor.U2D.Common;
-using UnityEditor.U2D.Sprites;
-using UnityEngine.Assertions;
-using UnityEngine.Experimental.U2D.Animation;
-using UnityEngine.U2D;
-using UnityEngine.U2D.Animation;
-using UnityEditor.MemoryProfiler;
-using UnityEngine.Profiling.Memory.Experimental;
-
-namespace UnityEditor.U2D.PSD
-{
- ///
- /// ScriptedImporter to import Photoshop files
- ///
- [ScriptedImporter(4, "psb")]
- [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.psdimporter@3.1/manual/index.html")]
- public class PSDImporter : ScriptedImporter, ISpriteEditorDataProvider
- {
- class UniqueNameGenerator
- {
- List m_NameHash = new List();
-
- public bool ContainHash(int i)
- {
- return m_NameHash.Contains(i);
- }
-
- public void AddHash(int i)
- {
- m_NameHash.Add(i);
- }
-
- public string GetUniqueName(string name)
- {
- return PSDImporter.GetUniqueName(name, m_NameHash);
- }
- }
-
- class GameObjectCreationFactory : UniqueNameGenerator
- {
-
- public GameObject CreateGameObject(string name, params System.Type[] components)
- {
- var newName = GetUniqueName(name);
- return new GameObject(newName, components);
- }
- }
-
- struct BoneGO
- {
- public GameObject go;
- public int index;
- }
-
- [SerializeField]
- TextureImporterSettings m_TextureImporterSettings = new TextureImporterSettings() {
- mipmapEnabled = true,
- mipmapFilter = TextureImporterMipFilter.BoxFilter,
- sRGBTexture = true,
- borderMipmap = false,
- mipMapsPreserveCoverage = false,
- alphaTestReferenceValue = 0.5f,
- readable = false,
-
-#if ENABLE_TEXTURE_STREAMING
- streamingMipmaps = true,
-#endif
-
- fadeOut = false,
- mipmapFadeDistanceStart = 1,
- mipmapFadeDistanceEnd = 3,
-
- convertToNormalMap = false,
- heightmapScale = 0.25F,
- normalMapFilter = 0,
-
- generateCubemap = TextureImporterGenerateCubemap.AutoCubemap,
- cubemapConvolution = 0,
-
- seamlessCubemap = false,
-
- npotScale = TextureImporterNPOTScale.ToNearest,
-
- spriteMode = (int)SpriteImportMode.Multiple,
- spriteExtrude = 1,
- spriteMeshType = SpriteMeshType.Tight,
- spriteAlignment = (int)SpriteAlignment.Center,
- spritePivot = new Vector2(0.5f, 0.5f),
- spritePixelsPerUnit = 100.0f,
- spriteBorder = new Vector4(0.0f, 0.0f, 0.0f, 0.0f),
-
- alphaSource = TextureImporterAlphaSource.FromInput,
- alphaIsTransparency = true,
- spriteTessellationDetail = -1.0f,
-
- textureType = TextureImporterType.Sprite,
- textureShape = TextureImporterShape.Texture2D,
-
- filterMode = FilterMode.Bilinear,
- aniso = 1,
- mipmapBias = 0.0f,
- wrapModeU = TextureWrapMode.Repeat,
- wrapModeV = TextureWrapMode.Repeat,
- wrapModeW = TextureWrapMode.Repeat,
- };
-
- [SerializeField]
- List m_SpriteImportData = new List(); // we use index 0 for single sprite and the rest for multiple sprites
- [SerializeField]
- List m_MosaicSpriteImportData = new List();
- [SerializeField]
- List m_RigSpriteImportData = new List();
-
- [SerializeField]
- List m_PlatformSettings = new List();
- [SerializeField]
- bool m_MosaicLayers = true;
- [SerializeField]
- Vector2 m_DocumentPivot = Vector2.zero;
- [SerializeField]
- SpriteAlignment m_DocumentAlignment = SpriteAlignment.BottomCenter;
- [SerializeField]
- bool m_ImportHiddenLayers = false;
- [SerializeField]
- int m_ImportedTextureWidth;
- [SerializeField]
- int m_ImportedTextureHeight;
- [SerializeField]
- Vector2Int m_DocumentSize;
-
- [SerializeField]
- bool m_PaperDollMode = false;
-
- [SerializeField]
- bool m_KeepDupilcateSpriteName = false;
-
- [SerializeField]
- SpriteCategoryList m_SpriteCategoryList = new SpriteCategoryList() {categories = new List()};
- GameObjectCreationFactory m_GameObjectFactory = new GameObjectCreationFactory();
-
- internal SpriteCategoryList spriteCategoryList { get { return m_SpriteCategoryList; } set { m_SpriteCategoryList = value; } }
-
- [SerializeField]
- int m_TextureActualWidth;
- internal int textureActualWidth
- {
- get { return m_TextureActualWidth; }
- private set { m_TextureActualWidth = value; }
- }
-
- [SerializeField]
- int m_TextureActualHeight;
- internal int textureActualHeight
- {
- get { return m_TextureActualHeight; }
- private set { m_TextureActualHeight = value; }
- }
-
- [SerializeField]
- string m_SpritePackingTag = "";
-
- [SerializeField]
- bool m_ResliceFromLayer = false;
- [SerializeField]
- bool m_CharacterMode = true;
-
- [SerializeField]
- List m_MosaicPSDLayers = new List();
- [SerializeField]
- List m_RigPSDLayers = new List();
-
- [SerializeField]
- CharacterData m_CharacterData = new CharacterData();
-
- [SerializeField]
- bool m_GenerateGOHierarchy = false;
-
- [SerializeField]
- string m_TextureAssetName = null;
-
- [SerializeField]
- string m_PrefabAssetName = null;
-
- [SerializeField]
- string m_SpriteLibAssetName = null;
-
- [SerializeField]
- SecondarySpriteTexture[] m_SecondarySpriteTextures;
-
- ///
- /// Implementation of ScriptedImporter.OnImportAsset
- ///
- ///
- /// This argument contains all the contextual information needed to process the import
- /// event and is also used by the custom importer to store the resulting Unity Asset.
- ///
- public override void OnImportAsset(AssetImportContext ctx)
- {
- FileStream fileStream = new FileStream(ctx.assetPath, FileMode.Open, FileAccess.Read);
- Document doc = null;
- try
- {
- UnityEngine.Profiling.Profiler.BeginSample("OnImportAsset");
-
- UnityEngine.Profiling.Profiler.BeginSample("PsdLoad");
- doc = PaintDotNet.Data.PhotoshopFileType.PsdLoad.Load(fileStream);
- UnityEngine.Profiling.Profiler.EndSample();
-
- ValidatePSDLayerId(doc);
-
- m_DocumentSize = new Vector2Int(doc.width, doc.height);
- bool singleSpriteMode = m_TextureImporterSettings.textureType == TextureImporterType.Sprite && m_TextureImporterSettings.spriteMode != (int)SpriteImportMode.Multiple;
- EnsureSingleSpriteExist();
-
- if (m_TextureImporterSettings.textureType != TextureImporterType.Sprite ||
- m_MosaicLayers == false || singleSpriteMode)
- {
- var image = new NativeArray(doc.width * doc.height, Allocator.Persistent);
- try
- {
- var spriteImportData = GetSpriteImportData();
- FlattenImageTask.Execute(doc.Layers, m_ImportHiddenLayers, doc.width, doc.height, image);
-
- int spriteCount = spriteDataCount;
- int spriteIndexStart = 1;
-
- if (spriteImportData.Count <= 0 || spriteImportData[0] == null)
- {
- spriteImportData.Add(new SpriteMetaData());
- }
- spriteImportData[0].name = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath) + "_1";
- spriteImportData[0].alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
- spriteImportData[0].border = m_TextureImporterSettings.spriteBorder;
- spriteImportData[0].pivot = m_TextureImporterSettings.spritePivot;
- spriteImportData[0].rect = new Rect(0, 0, doc.width, doc.height);
- if (singleSpriteMode)
- {
- spriteCount = 1;
- spriteIndexStart = 0;
- }
- textureActualWidth = doc.width;
- textureActualHeight = doc.height;
- var output = ImportTexture(ctx, image, doc.width, doc.height, spriteIndexStart, spriteCount);
- RegisterAssets(ctx, output);
- }
- finally
- {
- image.Dispose();
- }
- }
- else
- {
- ImportFromLayers(ctx, doc);
- }
- }
- finally
- {
- fileStream.Close();
- if (doc != null)
- doc.Dispose();
- UnityEngine.Profiling.Profiler.EndSample();
- 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 layers, UniqueNameGenerator uniqueNameGenerator)
- {
- for (int i = 0; i < layers.Count; ++i)
- {
- if (uniqueNameGenerator.ContainHash(layers[i].LayerID))
- {
- var importWarning = string.Format("Layer {0}: LayerId is not unique. Mapping will be done by Layer's name.", layers[i].Name);
- var layerName = uniqueNameGenerator.GetUniqueName(layers[i].Name);
- if (layerName != layers[i].Name)
- importWarning += "\nLayer names are not unique. Please ensure they are unique to for SpriteRect to be mapped back correctly.";
- layers[i].LayerID = layerName.GetHashCode();
- Debug.LogWarning(importWarning);
- }
- else
- uniqueNameGenerator.AddHash(layers[i].LayerID);
- if (layers[i].ChildLayer != null)
- {
- ValidatePSDLayerId(layers[i].ChildLayer, uniqueNameGenerator);
- }
- }
- }
-
-
- void ValidatePSDLayerId(Document doc)
- {
- UniqueNameGenerator uniqueNameGenerator = new UniqueNameGenerator();
-
- ValidatePSDLayerId(doc.Layers, uniqueNameGenerator);
- }
-
- TextureGenerationOutput ImportTexture(AssetImportContext ctx, NativeArray imageData, int textureWidth, int textureHeight, int spriteStart, int spriteCount)
- {
- if (!imageData.IsCreated || imageData.Length == 0)
- return new TextureGenerationOutput();
-
- UnityEngine.Profiling.Profiler.BeginSample("ImportTexture");
- var platformSettings = GetPlatformTextureSettings(ctx.selectedBuildTarget);
-
- var textureSettings = m_TextureImporterSettings.ExtractTextureSettings();
- textureSettings.assetPath = ctx.assetPath;
- textureSettings.enablePostProcessor = true;
- textureSettings.containsAlpha = true;
- textureSettings.hdr = false;
-
- var textureAlphaSettings = m_TextureImporterSettings.ExtractTextureAlphaSettings();
- var textureMipmapSettings = m_TextureImporterSettings.ExtractTextureMipmapSettings();
- var textureCubemapSettings = m_TextureImporterSettings.ExtractTextureCubemapSettings();
- var textureWrapSettings = m_TextureImporterSettings.ExtractTextureWrapSettings();
-
- TextureGenerationOutput output;
- switch (m_TextureImporterSettings.textureType)
- {
- case TextureImporterType.Default:
- output = TextureGeneratorHelper.GenerateTextureDefault(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
- break;
- case TextureImporterType.NormalMap:
- var textureNormalSettings = m_TextureImporterSettings.ExtractTextureNormalSettings();
- output = TextureGeneratorHelper.GenerateNormalMap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureNormalSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
- break;
- case TextureImporterType.GUI:
- output = TextureGeneratorHelper.GenerateTextureGUI(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
- break;
- case TextureImporterType.Sprite:
- var textureSpriteSettings = m_TextureImporterSettings.ExtractTextureSpriteSettings();
- textureSpriteSettings.packingTag = m_SpritePackingTag;
- 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)
- {
- //AutoGenerateSpriteSkinData(m_SpriteImportData[spriteStart + i]);
- textureSpriteSettings.spriteSheetData[i] = spriteImportData[spriteStart + i];
- }
- output = TextureGeneratorHelper.GenerateTextureSprite(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureSpriteSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
- break;
- case TextureImporterType.Cursor:
- output = TextureGeneratorHelper.GenerateTextureCursor(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
- break;
- case TextureImporterType.Cookie:
- output = TextureGeneratorHelper.GenerateCookie(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
- break;
- case TextureImporterType.Lightmap:
- output = TextureGeneratorHelper.GenerateLightmap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureMipmapSettings, textureWrapSettings);
- break;
- case TextureImporterType.SingleChannel:
- output = TextureGeneratorHelper.GenerateTextureSingleChannel(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
- break;
- default:
- Debug.LogAssertion("Unknown texture type for import");
- output = default(TextureGenerationOutput);
- break;
- }
- UnityEngine.Profiling.Profiler.EndSample();
- return output;
- }
-
- void AutoGenerateSpriteSkinData(SpriteMetaData metaData)
- {
- //If bone data exist but skinning data doesn't exist, auto generate them
- if (metaData.spriteBone != null && metaData.spriteBone.Count > 0 &&
- (metaData.vertices == null || metaData.vertices.Count == 0))
- {
- var spriteMeshDataController = new SpriteMeshDataController();
- var smd = new SpriteMeshData();
- smd.spriteID = metaData.spriteID;
- smd.frame = metaData.rect;
- smd.pivot = metaData.pivot;
- smd.bones = ModuleUtility.CreateSpriteBoneData(metaData.spriteBone.ToArray(), Matrix4x4.TRS(metaData.rect.position, Quaternion.identity, Vector3.one));
- spriteMeshDataController.spriteMeshData = smd;
- spriteMeshDataController.OutlineFromAlpha(new OutlineGenerator(), GetDataProvider(), 0.05f, 200);
- spriteMeshDataController.Triangulate(new Triangulator());
- spriteMeshDataController.Subdivide(new Triangulator(), 0.25f);
- spriteMeshDataController.CalculateWeights(new BoundedBiharmonicWeightsGenerator(), null, 0.01f);
- spriteMeshDataController.SortTrianglesByDepth();
-
- List vmd = new List(smd.vertices.Count);
- foreach (var v in smd.vertices)
- vmd.Add(new Vertex2DMetaData() { position = v.position - smd.frame.position, boneWeight = v.editableBoneWeight.ToBoneWeight(true) });
- List emd = new List(smd.edges.Count);
- foreach (var e in smd.edges)
- emd.Add(new Vector2Int(e.index1, e.index2));
-
- metaData.vertices = vmd;
- metaData.indices = smd.indices.ToArray();
- metaData.edges = emd.ToArray();
- }
- }
-
- string GetUniqueSpriteName(string name, List namehash)
- {
- if (m_KeepDupilcateSpriteName)
- return name;
- return GetUniqueName(name, namehash);
- }
-
- void ImportFromLayers(AssetImportContext ctx, Document doc)
- {
- NativeArray output = default(NativeArray);
-
- List layerIndex = new List();
- List spriteNameHash = new List();
- var oldPsdLayers = GetPSDLayers();
- try
- {
- var psdLayers = new List();
- ExtractLayerTask.Execute(psdLayers, doc.Layers, m_ImportHiddenLayers);
- var removedLayersSprite = oldPsdLayers.Where(x => psdLayers.FirstOrDefault(y => y.layerID == x.layerID) == null).Select(z => z.spriteID).ToArray();
- for (int i = 0; i < psdLayers.Count; ++i)
- {
- int j = 0;
- var psdLayer = psdLayers[i];
- for (; j < oldPsdLayers.Count; ++j)
- {
- if (psdLayer.layerID == oldPsdLayers[j].layerID)
- {
- psdLayer.spriteID = oldPsdLayers[j].spriteID;
- psdLayer.spriteName = oldPsdLayers[j].spriteName;
- psdLayer.mosaicPosition = oldPsdLayers[j].mosaicPosition;
- break;
- }
- }
- }
-
- int expectedBufferLength = doc.width * doc.height;
- var layerBuffers = new List>();
- for (int i = 0; i < psdLayers.Count; ++i)
- {
- var l = psdLayers[i];
- if (l.texture.IsCreated && l.texture.Length == expectedBufferLength)
- {
- layerBuffers.Add(l.texture);
- layerIndex.Add(i);
- }
- }
-
- RectInt[] spritedata;
- int width, height;
- int padding = 4;
- Vector2Int[] uvTransform;
- ImagePacker.Pack(layerBuffers.ToArray(), doc.width, doc.height, padding, out output, out width, out height, out spritedata, out uvTransform);
- var spriteImportData = GetSpriteImportData();
- if (spriteImportData.Count <= 0 || shouldResliceFromLayer)
- {
- var newSpriteMeta = new List();
-
- for (int i = 0; i < spritedata.Length && i < layerIndex.Count; ++i)
- {
- var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[layerIndex[i]].spriteID);
- if (spriteSheet == null)
- {
- spriteSheet = new SpriteMetaData();
- spriteSheet.border = Vector4.zero;
- spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
- spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
- }
-
- psdLayers[layerIndex[i]].spriteName = GetUniqueSpriteName(psdLayers[layerIndex[i]].name, spriteNameHash);
- spriteSheet.name = psdLayers[layerIndex[i]].spriteName;
- spriteSheet.rect = new Rect(spritedata[i].x, spritedata[i].y, spritedata[i].width, spritedata[i].height);
- spriteSheet.uvTransform = uvTransform[i];
-
- psdLayers[layerIndex[i]].spriteID = spriteSheet.spriteID;
- psdLayers[layerIndex[i]].mosaicPosition = spritedata[i].position;
- newSpriteMeta.Add(spriteSheet);
- }
- spriteImportData.Clear();
- spriteImportData.AddRange(newSpriteMeta);
- }
- else
- {
- spriteImportData.RemoveAll(x => removedLayersSprite.Contains(x.spriteID));
-
- // First look for any user created SpriteRect and add those into the name hash
- foreach (var spriteData in spriteImportData)
- {
- var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == spriteData.spriteID);
- if (psdLayer == null)
- spriteNameHash.Add(spriteData.name.GetHashCode());
- }
-
- foreach (var spriteData in spriteImportData)
- {
- var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == spriteData.spriteID);
- if (psdLayer == null)
- spriteData.uvTransform = new Vector2Int((int)spriteData.rect.position.x, (int)spriteData.rect.position.y);
- // If it is user created rect or the name has been changed before
- // add it into the spriteNameHash and we don't copy it over from the layer
- if (psdLayer == null || psdLayer.spriteName != spriteData.name)
- spriteNameHash.Add(spriteData.name.GetHashCode());
-
- // If the sprite name has not been changed, we ensure the new
- // layer name is still unique and use it as the sprite name
- if (psdLayer != null && psdLayer.spriteName == spriteData.name)
- {
- psdLayer.spriteName = GetUniqueSpriteName(psdLayer.name, spriteNameHash);
- spriteData.name = psdLayer.spriteName;
- }
- }
-
- //Update names for those user has not changed and add new sprite rect based on PSD file.
- for (int k = 0; k < layerIndex.Count; ++k)
- {
- int i = layerIndex[k];
- var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[i].spriteID);
- var inOldLayer = oldPsdLayers.FindIndex(x => x.layerID == psdLayers[i].layerID) != -1;
- if (spriteSheet == null && !inOldLayer)
- {
- spriteSheet = new SpriteMetaData();
- spriteImportData.Add(spriteSheet);
- spriteSheet.rect = new Rect(spritedata[k].x, spritedata[k].y, spritedata[k].width, spritedata[k].height);
- spriteSheet.border = Vector4.zero;
- spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
- spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
- psdLayers[i].spriteName = GetUniqueSpriteName(psdLayers[i].name, spriteNameHash);
- spriteSheet.name = psdLayers[i].spriteName;
- }
- else if (spriteSheet != null)
- {
- var r = spriteSheet.rect;
- r.position = spriteSheet.rect.position - psdLayers[i].mosaicPosition + spritedata[k].position;
- spriteSheet.rect = r;
- }
-
- if (spriteSheet != null)
- {
- spriteSheet.uvTransform = uvTransform[k];
- psdLayers[i].spriteID = spriteSheet.spriteID;
- psdLayers[i].mosaicPosition = spritedata[k].position;
- }
- }
- }
-
- foreach (var l in oldPsdLayers)
- l.Dispose();
- oldPsdLayers.Clear();
-
- oldPsdLayers.AddRange(psdLayers);
- m_ImportedTextureHeight = textureActualHeight = height;
- m_ImportedTextureWidth = textureActualWidth = width;
- var generatedTexture = ImportTexture(ctx, output, width, height, 0, spriteImportData.Count);
-
- if (generatedTexture.texture)
- {
- m_ImportedTextureHeight = generatedTexture.texture.height;
- m_ImportedTextureWidth = generatedTexture.texture.width;
- }
-
- RegisterAssets(ctx, generatedTexture);
- }
- finally
- {
- if (output.IsCreated)
- output.Dispose();
- foreach (var l in oldPsdLayers)
- l.Dispose();
- }
-
- }
-
- void MemorySnapshotFinish(string path, bool done)
- {
-
- }
-
- void EnsureSingleSpriteExist()
- {
- if (m_SpriteImportData.Count <= 0)
- m_SpriteImportData.Add(new SpriteMetaData()); // insert default for single sprite mode
- }
-
- internal TextureImporterPlatformSettings GetPlatformTextureSettings(BuildTarget buildTarget)
- {
- var buildTargetName = TexturePlatformSettingsModal.kValidBuildPlatform.FirstOrDefault(x => x.buildTarget.Contains(buildTarget));
- var defaultTargetName = TexturePlatformSettingsModal.kValidBuildPlatform.FirstOrDefault(x => x.buildTarget.Contains(BuildTarget.NoTarget));
- TextureImporterPlatformSettings platformSettings = null;
- platformSettings = m_PlatformSettings.SingleOrDefault(x => x.name == buildTargetName.buildTargetName);
- platformSettings = platformSettings ?? m_PlatformSettings.SingleOrDefault(x => x.name == defaultTargetName.buildTargetName);
-
- if (platformSettings == null)
- {
- platformSettings = new TextureImporterPlatformSettings();
- platformSettings.name = name;
- platformSettings.overridden = false;
- }
- return platformSettings;
- }
-
- void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
- {
- List assetNameHash = new List();
- if (!string.IsNullOrEmpty(output.importInspectorWarnings))
- {
- Debug.LogWarning(output.importInspectorWarnings);
- }
- if (output.importWarnings != null && output.importWarnings.Length != 0)
- {
- foreach (var warning in output.importWarnings)
- Debug.LogWarning(warning);
- }
- if (output.thumbNail == null)
- Debug.LogWarning("Thumbnail generation fail");
- if (output.texture == null)
- {
- 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(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;
-
-
- if (output.sprites != null)
- {
- var slAsset = ProduceSpriteLibAsset(output.sprites);
-
- if (shouldProduceGameObject)
- {
- GameObject prefab = null;
- if (m_PaperDollMode)
- prefab = OnProducePaperDollPrefab(m_TextureAssetName, output.sprites, slAsset);
- else
- prefab = OnProducePrefab(m_TextureAssetName, output.sprites, slAsset);
- if (prefab != null)
- {
- ctx.AddObjectToAsset(m_PrefabAssetName, prefab);
- mainAsset = prefab;
- }
- }
-
- foreach (var s in output.sprites)
- {
- var spriteAssetName = GetUniqueName(s.GetSpriteID().ToString(), assetNameHash, false, s);
- ctx.AddObjectToAsset(spriteAssetName, s);
- }
-
- if (slAsset != null)
- {
- slAsset.name = assetName;
- ctx.AddObjectToAsset(m_SpriteLibAssetName, slAsset);
- }
- }
- ctx.SetMainObject(mainAsset);
- }
-
- bool SpriteIsMainFromSpriteLib(string spriteId, out string categoryName)
- {
- categoryName = "";
- if (m_SpriteCategoryList.categories != null)
- {
- foreach (var category in m_SpriteCategoryList.categories)
- {
- var index = category.labels.FindIndex(x => x.spriteId == spriteId);
- if (index == 0)
- {
- categoryName = category.name;
- return true;
- }
- if (index > 0)
- return false;
- }
- }
- return true;
- }
-
- void BuildGroupGameObject(List 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].isGroup == false))
- {
- // 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);
- root = psdGroup[psdGroup[index].parentIndex].gameObject.transform;
- }
-
- if (psdGroup[index].gameObject != null)
- psdGroup[index].gameObject.transform.SetParent(root);
- }
- }
-
- bool shouldProduceGameObject
- {
- get { return m_CharacterMode && m_MosaicLayers && spriteImportMode == SpriteImportMode.Multiple; }
- }
-
- bool shouldResliceFromLayer
- {
- get { return m_ResliceFromLayer && m_MosaicLayers && spriteImportMode == SpriteImportMode.Multiple; }
- }
-
- bool characterMode
- {
- get { return mosaicMode && m_CharacterMode == true; }
- }
-
- float definitionScale
- {
- get
- {
- float definitionScaleW = m_ImportedTextureWidth / (float)textureActualWidth;
- float definitionScaleH = m_ImportedTextureHeight / (float)textureActualHeight;
- return Mathf.Min(definitionScaleW, definitionScaleH);
- }
- }
-
- private Vector2 GetPivotPoint(Rect rect, SpriteAlignment alignment)
- {
- switch (alignment)
- {
- case SpriteAlignment.TopLeft:
- return new Vector2(rect.xMin, rect.yMax);
-
- case SpriteAlignment.TopCenter:
- return new Vector2(rect.center.x, rect.yMax);
-
- case SpriteAlignment.TopRight:
- return new Vector2(rect.xMax, rect.yMax);
-
- case SpriteAlignment.LeftCenter:
- return new Vector2(rect.xMin, rect.center.y);
-
- case SpriteAlignment.Center:
- return new Vector2(rect.center.x, rect.center.y);
-
- case SpriteAlignment.RightCenter:
- return new Vector2(rect.xMax, rect.center.y);
-
- case SpriteAlignment.BottomLeft:
- return new Vector2(rect.xMin, rect.yMin);
-
- case SpriteAlignment.BottomCenter:
- return new Vector2(rect.center.x, rect.yMin);
-
- case SpriteAlignment.BottomRight:
- return new Vector2(rect.xMax, rect.yMin);
-
- case SpriteAlignment.Custom:
- return new Vector2(m_DocumentPivot.x * rect.width, m_DocumentPivot.y * rect.height);
- }
- return Vector2.zero;
- }
-
- void CreateBoneGO(int index, SpriteBone[] bones, BoneGO[] bonesGO, Transform defaultRoot)
- {
- if (bonesGO[index].go != null)
- return;
- var bone = bones[index];
- if (bone.parentId != -1 && bonesGO[bone.parentId].go == null)
- CreateBoneGO(bone.parentId, bones, bonesGO, defaultRoot);
-
- var go = m_GameObjectFactory.CreateGameObject(bone.name);
- if (bone.parentId == -1)
- go.transform.SetParent(defaultRoot);
- else
- go.transform.SetParent(bonesGO[bone.parentId].go.transform);
- go.transform.localPosition = bone.position * 1 / pixelsPerUnit;
- go.transform.localRotation = bone.rotation;
- bonesGO[index] = new BoneGO()
- {
- go = go,
- index = index
- };
- }
-
- BoneGO[] CreateBonesGO(Transform root)
- {
- if (characterMode)
- {
- var characterSkeleton = GetDataProvider().GetCharacterData();
- var bones = characterSkeleton.bones;
- if (bones != null)
- {
- var boneGOs = new BoneGO[bones.Length];
- for (int i = 0; i < bones.Length; ++i)
- {
- CreateBoneGO(i, bones, boneGOs, root);
- }
- return boneGOs;
- }
- }
- return new BoneGO[0];
- }
-
- void GetSpriteLiblabel(string spriteId, out string category, out string label)
- {
- category = "";
- label = "";
- var index = -1;
- foreach (var cat in m_SpriteCategoryList.categories)
- {
- index = cat.labels.FindIndex(x => x.spriteId == spriteId);
- if (index != -1)
- {
- category = cat.name;
- label = cat.labels[index].name;
- break;
- }
- }
- }
-
- GameObject OnProducePaperDollPrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
- {
- GameObject root = null;
- CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider().GetCharacterData()) : null;
- if (sprites != null && sprites.Length > 0)
- {
- root = new GameObject();
- root.name = assetname + "_GO";
- var spriteImportData = GetSpriteImportData();
- var psdLayers = GetPSDLayers();
- var boneGOs = CreateBonesGO(root.transform);
- if (spriteLib != null)
- root.AddComponent().spriteLibraryAsset = 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 < boneGOs.Length).Select(x => 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();
- 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 labelName = "";
- GetSpriteLiblabel(sprites[i].GetSpriteID().ToString(), out category, out labelName);
- if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
- {
- var sresolver = srGameObject.AddComponent();
- sresolver.SetCategoryAndLabel(category, labelName);
- sresolver.ResolveSpriteToSpriteRenderer();
- }
- }
- }
- }
- return root;
- }
-
- GameObject OnProducePrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
- {
- GameObject root = null;
- CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider().GetCharacterData()) : null;
- if (sprites != null && sprites.Length > 0)
- {
- var spriteImportData = GetSpriteImportData();
- root = new GameObject();
- root.name = assetname + "_GO";
- if (spriteLib != null)
- root.AddComponent().spriteLibraryAsset = spriteLib;
-
- var psdLayers = GetPSDLayers();
- for (int i = 0; i < psdLayers.Count; ++i)
- {
- BuildGroupGameObject(psdLayers, i, root.transform);
- }
- var boneGOs = CreateBonesGO(root.transform);
- for (int i = 0; i < psdLayers.Count; ++i)
- {
- var l = psdLayers[i];
- 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 && l.gameObject != null)
- {
- var spriteRenderer = l.gameObject.AddComponent();
- spriteRenderer.sprite = sprite;
- 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;
- l.gameObject.transform.position = new Vector3(outlineOffset.x, outlineOffset.y, 0);
-
- if (characterSkeleton != null)
- {
- var part = characterSkeleton.Value.parts.FirstOrDefault(x => x.spriteId == spriteMetaData.spriteID.ToString());
- if (part.bones != null && part.bones.Length > 0)
- {
- var spriteSkin = l.gameObject.AddComponent();
- 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]);
- if (spriteBones.Any())
- {
- spriteSkin.rootBone = spriteBones.OrderBy(x => x.index).First().go.transform;
- spriteSkin.boneTransforms = spriteBones.Select(x => x.go.transform).ToArray();
- if (spriteSkin.isValid)
- spriteSkin.CalculateBounds();
- }
- }
- }
- }
-
- var category = "";
- var labelName = "";
- GetSpriteLiblabel(layerSpriteID.ToString(), out category, out labelName);
- if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
- {
- var sresolver = l.gameObject.AddComponent();
- sresolver.SetCategoryAndLabel(category, labelName);
- sresolver.ResolveSpriteToSpriteRenderer();
- }
- }
- }
-
- var prefabBounds = new Rect(0 , 0, m_DocumentSize.x / pixelsPerUnit, m_DocumentSize.y / pixelsPerUnit);
- var documentPivot = (Vector3)GetPivotPoint(prefabBounds, m_DocumentAlignment);
- for (int i = 0; i < psdLayers.Count; ++i)
- {
- var l = psdLayers[i];
- if (l.gameObject == null || l.gameObject.GetComponent() == null)
- continue;
- var p = l.gameObject.transform.localPosition;
- p -= documentPivot;
- l.gameObject.transform.localPosition = p;
- }
- for (int i = 0; i < boneGOs.Length; ++i)
- {
- if (boneGOs[i].go.transform.parent != root.transform)
- continue;
- var p = boneGOs[i].go.transform.position;
- p -= documentPivot;
- boneGOs[i].go.transform.position = p;
- }
- }
-
- return root;
- }
-
- Bounds? GetBoundingBox(GameObject root)
- {
- Bounds? prefabBounds1 = null;
- var sr = root.GetComponent();
- if (sr != null)
- {
- prefabBounds1 = sr.bounds;
- }
- for (int i = 0; i < root.transform.childCount; ++i)
- {
- var b = GetBoundingBox(root.transform.GetChild(i).gameObject);
- if (prefabBounds1 == null)
- prefabBounds1 = b;
- else
- {
- if (b.HasValue)
- {
- var bb = prefabBounds1.Value;
- bb.Encapsulate(b.Value);
- prefabBounds1 = bb;
- }
- }
- }
- return prefabBounds1;
- }
-
- bool CleanUpGameobjectsWithOutRig(GameObject root)
- {
- var sr = root.GetComponent();
- var canDelete = true;
- if (sr != null && sr.sprite != null)
- {
- try
- {
- var bones = GetDataProvider().GetBones(sr.sprite.GetSpriteID());
- canDelete = bones == null || bones.Count == 0;
- }
- catch (Exception e)
- {
- Debug.LogError(e);
- }
- }
-
-
- List cleanup = new List();
- for (int i = 0; i < root.transform.childCount; ++i)
- {
- var go = root.transform.GetChild(i);
- if (CleanUpGameobjectsWithOutRig(go.gameObject))
- cleanup.Add(go.gameObject);
- }
-
- for (int i = 0; i < cleanup.Count; ++i)
- GameObject.DestroyImmediate(cleanup[i]);
- cleanup.Clear();
-
- if (root.transform.childCount == 0 && canDelete)
- return true;
-
- return false;
- }
-
- static string SanitizeName(string name)
- {
- string newName = null;
- // We can't create asset name with these name.
- if ((name.Length == 2 && name[0] == '.' && name[1] == '.')
- || (name.Length == 1 && name[0] == '.')
- || (name.Length == 1 && name[0] == '/'))
- newName += name + "_";
-
- if (!string.IsNullOrEmpty(newName))
- {
- Debug.LogWarning(string.Format("File contains layer with invalid name for generating asset. {0} is renamed to {1}", name, newName));
- return newName;
- }
- return name;
- }
-
- static string GetUniqueName(string name, List stringHash, bool logNewNameGenerated = false, UnityEngine.Object context = null)
- {
- string uniqueName = string.Copy(SanitizeName(name));
- int index = 1;
- while (true)
- {
- int hash = uniqueName.GetHashCode();
- var p = stringHash.Where(x => x == hash);
- if (!p.Any())
- {
- stringHash.Add(hash);
- if (logNewNameGenerated && name != uniqueName)
- Debug.Log(string.Format("Asset name {0} is changed to {1} to ensure uniqueness", name, uniqueName), context);
- return uniqueName;
- }
- uniqueName = string.Format("{0}_{1}", name, index);
- ++index;
- }
- }
-
- // ISpriteEditorDataProvider interface
- internal SpriteImportMode spriteImportMode
- {
- get
- {
- return m_TextureImporterSettings.textureType != TextureImporterType.Sprite ?
- SpriteImportMode.None :
- (SpriteImportMode)m_TextureImporterSettings.spriteMode;
- }
- }
-
- SpriteImportMode ISpriteEditorDataProvider.spriteImportMode => spriteImportMode;
-
- internal int spriteDataCount
- {
- get
- {
- var spriteImportData = GetSpriteImportData();
- if (mosaicMode)
- return spriteImportData.Count;
- if (spriteImportMode != SpriteImportMode.Multiple)
- return 1;
- return spriteImportData.Count - 1;
- }
- }
-
- internal UnityEngine.Object targetObject
- {
- get { return this; }
- }
- UnityEngine.Object ISpriteEditorDataProvider.targetObject => targetObject;
-
- internal float pixelsPerUnit
- {
- get { return m_TextureImporterSettings.spritePixelsPerUnit; }
- }
-
- float ISpriteEditorDataProvider.pixelsPerUnit =>pixelsPerUnit;
-
- internal T GetDataProvider() where T : class
- {
- if (typeof(T) == typeof(ISpriteBoneDataProvider))
- {
- return new SpriteBoneDataProvider { dataProvider = this } as T;
- }
- if (typeof(T) == typeof(ISpriteMeshDataProvider))
- {
- return new SpriteMeshDataProvider { dataProvider = this } as T;
- }
- if (typeof(T) == typeof(ISpriteOutlineDataProvider))
- {
- return new SpriteOutlineDataProvider { dataProvider = this } as T;
- }
- if (typeof(T) == typeof(ISpritePhysicsOutlineDataProvider))
- {
- return new SpritePhysicsOutlineProvider { dataProvider = this } as T;
- }
- if (typeof(T) == typeof(ITextureDataProvider))
- {
- return new TextureDataProvider { dataProvider = this } as T;
- }
- if (typeof(T) == typeof(ICharacterDataProvider))
- {
- 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;
- }
- else
- return this as T;
- }
-
- T ISpriteEditorDataProvider.GetDataProvider()
- {
- return GetDataProvider();
- }
-
- internal bool HasDataProvider(Type type)
- {
- if (characterMode && type == typeof(ICharacterDataProvider))
- return true;
- if (type == typeof(ISpriteBoneDataProvider) ||
- type == typeof(ISpriteMeshDataProvider) ||
- type == typeof(ISpriteOutlineDataProvider) ||
- type == typeof(ISpritePhysicsOutlineDataProvider) ||
- type == typeof(ITextureDataProvider) ||
- type == typeof(ISpriteLibDataProvider) ||
- type == typeof(ISecondaryTextureDataProvider))
- {
- return true;
- }
- else
- return type.IsAssignableFrom(GetType());
- }
-
- bool ISpriteEditorDataProvider.HasDataProvider(Type type)
- {
- return HasDataProvider(type);
- }
-
- internal void AddSpriteData(SpriteRect spriteRect)
- {
- if (spriteImportMode != SpriteImportMode.Multiple)
- Debug.LogWarning("Can only add sprite data when import mode is multiple");
- else
- {
- GetSpriteImportData().Add(new SpriteMetaData(spriteRect));
- }
- }
-
- internal void DeleteSpriteData(SpriteRect spriteRect)
- {
- if (spriteImportMode != SpriteImportMode.Multiple)
- Debug.LogWarning("Can only add sprite data when import mode is multiple");
- else
- {
- var spriteImportData = GetSpriteImportData();
- int index = spriteImportData.FindIndex(x => x.spriteID == spriteRect.spriteID);
- Assert.AreEqual(0, index, "Cannot delete Sprite from single sprite mode");
- spriteImportData.RemoveAt(index);
- }
- }
-
- internal int GetSpriteDataIndex(GUID guid)
- {
- switch (spriteImportMode)
- {
- case SpriteImportMode.Single:
- case SpriteImportMode.Polygon:
- return 0;
- case SpriteImportMode.Multiple:
- {
- var spriteImportData = GetSpriteImportData();
- return spriteImportData.FindIndex(x => x.spriteID == guid);
- }
- default:
- throw new InvalidOperationException("GUID not found");
- }
- }
-
- internal void Apply()
- {
- // Do this so that asset change save dialog will not show
- var originalValue = EditorPrefs.GetBool("VerifySavingAssets", false);
- EditorPrefs.SetBool("VerifySavingAssets", false);
- AssetDatabase.ForceReserializeAssets(new string[] { assetPath }, ForceReserializeAssetsOptions.ReserializeMetadata);
- EditorPrefs.SetBool("VerifySavingAssets", originalValue);
- }
-
- void ISpriteEditorDataProvider.Apply()
- {
- Apply();
- }
-
- internal void InitSpriteEditorDataProvider() {}
- void ISpriteEditorDataProvider.InitSpriteEditorDataProvider()
- {
- InitSpriteEditorDataProvider();
- }
-
- internal SpriteRect[] GetSpriteRects()
- {
- var spriteImportData = GetSpriteImportData();
- var skip = mosaicMode ? 0 : 1;
- return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).Select(x => new SpriteMetaData(x) as SpriteRect).ToArray() : new[] {new SpriteMetaData(spriteImportData[0]) };
- }
-
- SpriteRect[] ISpriteEditorDataProvider.GetSpriteRects()
- {
- return GetSpriteRects();
- }
-
- List GetSpriteImportData()
- {
- return mosaicMode ? (characterMode ? m_RigSpriteImportData : m_MosaicSpriteImportData) : m_SpriteImportData;
- }
-
- internal List GetPSDLayers()
- {
- return mosaicMode ? (characterMode ? m_RigPSDLayers : m_MosaicPSDLayers) : null;
- }
-
- internal SpriteMetaData[] GetSpriteMetaData()
- {
- var spriteImportData = GetSpriteImportData();
- var skip = mosaicMode ? 0 : 1;
- return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).ToArray() : new[] { new SpriteMetaData(spriteImportData[0]) };
- }
-
- internal SpriteRect GetSpriteData(GUID guid)
- {
- var spriteImportData = GetSpriteImportData();
- var skip = mosaicMode ? 0 : 1;
- return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).FirstOrDefault(x => x.spriteID == guid) : spriteImportData[0];
- }
-
- internal void SetSpriteRects(SpriteRect[] spriteRects)
- {
- var spriteImportData = GetSpriteImportData();
- if (spriteImportMode == SpriteImportMode.Multiple)
- {
- var singleSpriteID = mosaicMode ? new GUID() : spriteImportData[0].spriteID;
- spriteImportData.RemoveAll(data => data.spriteID != singleSpriteID && spriteRects.FirstOrDefault(x => x.spriteID == data.spriteID) == null);
- foreach (var sr in spriteRects)
- {
- var importData = spriteImportData.FirstOrDefault(x => x.spriteID == sr.spriteID);
- if (importData == null)
- spriteImportData.Add(new SpriteMetaData(sr));
- else
- {
- importData.name = sr.name;
- importData.alignment = sr.alignment;
- importData.border = sr.border;
- importData.pivot = sr.pivot;
- importData.rect = sr.rect;
- }
- }
- }
- else if (spriteRects.Length == 1 && (spriteImportMode == SpriteImportMode.Single || spriteImportMode == SpriteImportMode.Polygon))
- {
- if (spriteImportData[0].spriteID == spriteRects[0].spriteID)
- {
- spriteImportData[0].name = spriteRects[0].name;
- spriteImportData[0].alignment = spriteRects[0].alignment;
- m_TextureImporterSettings.spriteAlignment = (int)spriteRects[0].alignment;
- m_TextureImporterSettings.spriteBorder = spriteImportData[0].border = spriteRects[0].border;
- m_TextureImporterSettings.spritePivot = spriteImportData[0].pivot = spriteRects[0].pivot;
- spriteImportData[0].rect = spriteRects[0].rect;
- }
- else
- {
- spriteImportData[0] = new SpriteMetaData(spriteRects[0]);
- }
- }
- }
-
- void ISpriteEditorDataProvider.SetSpriteRects(SpriteRect[] spriteRects)
- {
- SetSpriteRects(spriteRects);
- }
-
- bool mosaicMode
- {
- get { return spriteImportMode == SpriteImportMode.Multiple && m_MosaicLayers; }
- }
-
- internal CharacterData characterData
- {
- get { return m_CharacterData; }
- set { m_CharacterData = value; }
- }
-
- internal Vector2Int documentSize
- {
- get { return m_DocumentSize; }
- }
-
- SpriteLibraryAsset ProduceSpriteLibAsset(Sprite[] sprites)
- {
- if (!characterMode || m_SpriteCategoryList.categories == null)
- return null;
- var sla = ScriptableObject.CreateInstance();
- sla.name = "Sprite Lib";
- sla.categories = m_SpriteCategoryList.categories.Select(x =>
- new SpriteLibCategory()
- {
- name = x.name,
- categoryList = x.labels.Select(y =>
- {
- 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; }
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.IO;
+using PDNWrapper;
+using UnityEngine;
+using Unity.Collections;
+using System.Linq;
+using UnityEditor.Experimental.AssetImporters;
+using UnityEditor.U2D.Animation;
+using UnityEditor.U2D.Common;
+using UnityEditor.U2D.Sprites;
+using UnityEngine.Assertions;
+using UnityEngine.Experimental.U2D.Animation;
+using UnityEngine.U2D;
+using UnityEngine.U2D.Animation;
+using UnityEditor.MemoryProfiler;
+using UnityEngine.Profiling.Memory.Experimental;
+
+namespace UnityEditor.U2D.PSD
+{
+ ///
+ /// ScriptedImporter to import Photoshop files
+ ///
+ [ScriptedImporter(4, "psb")]
+ [HelpURL("https://docs.unity3d.com/Packages/com.unity.2d.psdimporter@3.1/manual/index.html")]
+ public class PSDImporter : ScriptedImporter, ISpriteEditorDataProvider
+ {
+ class UniqueNameGenerator
+ {
+ List m_NameHash = new List();
+
+ public bool ContainHash(int i)
+ {
+ return m_NameHash.Contains(i);
+ }
+
+ public void AddHash(int i)
+ {
+ m_NameHash.Add(i);
+ }
+
+ public string GetUniqueName(string name)
+ {
+ return PSDImporter.GetUniqueName(name, m_NameHash);
+ }
+ }
+
+ class GameObjectCreationFactory : UniqueNameGenerator
+ {
+
+ public GameObject CreateGameObject(string name, params System.Type[] components)
+ {
+ var newName = GetUniqueName(name);
+ return new GameObject(newName, components);
+ }
+ }
+
+ struct BoneGO
+ {
+ public GameObject go;
+ public int index;
+ }
+
+ [SerializeField]
+ TextureImporterSettings m_TextureImporterSettings = new TextureImporterSettings() {
+ mipmapEnabled = true,
+ mipmapFilter = TextureImporterMipFilter.BoxFilter,
+ sRGBTexture = true,
+ borderMipmap = false,
+ mipMapsPreserveCoverage = false,
+ alphaTestReferenceValue = 0.5f,
+ readable = false,
+
+#if ENABLE_TEXTURE_STREAMING
+ streamingMipmaps = true,
+#endif
+
+ fadeOut = false,
+ mipmapFadeDistanceStart = 1,
+ mipmapFadeDistanceEnd = 3,
+
+ convertToNormalMap = false,
+ heightmapScale = 0.25F,
+ normalMapFilter = 0,
+
+ generateCubemap = TextureImporterGenerateCubemap.AutoCubemap,
+ cubemapConvolution = 0,
+
+ seamlessCubemap = false,
+
+ npotScale = TextureImporterNPOTScale.ToNearest,
+
+ spriteMode = (int)SpriteImportMode.Multiple,
+ spriteExtrude = 1,
+ spriteMeshType = SpriteMeshType.Tight,
+ spriteAlignment = (int)SpriteAlignment.Center,
+ spritePivot = new Vector2(0.5f, 0.5f),
+ spritePixelsPerUnit = 100.0f,
+ spriteBorder = new Vector4(0.0f, 0.0f, 0.0f, 0.0f),
+
+ alphaSource = TextureImporterAlphaSource.FromInput,
+ alphaIsTransparency = true,
+ spriteTessellationDetail = -1.0f,
+
+ textureType = TextureImporterType.Sprite,
+ textureShape = TextureImporterShape.Texture2D,
+
+ filterMode = FilterMode.Bilinear,
+ aniso = 1,
+ mipmapBias = 0.0f,
+ wrapModeU = TextureWrapMode.Repeat,
+ wrapModeV = TextureWrapMode.Repeat,
+ wrapModeW = TextureWrapMode.Repeat,
+ };
+
+ [SerializeField]
+ List m_SpriteImportData = new List(); // we use index 0 for single sprite and the rest for multiple sprites
+ [SerializeField]
+ List m_MosaicSpriteImportData = new List();
+ [SerializeField]
+ List m_RigSpriteImportData = new List();
+
+ [SerializeField]
+ List m_PlatformSettings = new List();
+ [SerializeField]
+ bool m_MosaicLayers = true;
+ [SerializeField]
+ Vector2 m_DocumentPivot = Vector2.zero;
+ [SerializeField]
+ SpriteAlignment m_DocumentAlignment = SpriteAlignment.BottomCenter;
+ [SerializeField]
+ bool m_ImportHiddenLayers = false;
+ [SerializeField]
+ int m_ImportedTextureWidth;
+ [SerializeField]
+ int m_ImportedTextureHeight;
+ [SerializeField]
+ Vector2Int m_DocumentSize;
+
+ [SerializeField]
+ bool m_PaperDollMode = false;
+
+ [SerializeField]
+ bool m_KeepDupilcateSpriteName = false;
+
+ [SerializeField]
+ SpriteCategoryList m_SpriteCategoryList = new SpriteCategoryList() {categories = new List()};
+ GameObjectCreationFactory m_GameObjectFactory = new GameObjectCreationFactory();
+
+ internal SpriteCategoryList spriteCategoryList { get { return m_SpriteCategoryList; } set { m_SpriteCategoryList = value; } }
+
+ [SerializeField]
+ int m_TextureActualWidth;
+ internal int textureActualWidth
+ {
+ get { return m_TextureActualWidth; }
+ private set { m_TextureActualWidth = value; }
+ }
+
+ [SerializeField]
+ int m_TextureActualHeight;
+ internal int textureActualHeight
+ {
+ get { return m_TextureActualHeight; }
+ private set { m_TextureActualHeight = value; }
+ }
+
+ [SerializeField]
+ string m_SpritePackingTag = "";
+
+ [SerializeField]
+ bool m_ResliceFromLayer = false;
+ [SerializeField]
+ bool m_CharacterMode = true;
+
+ [SerializeField]
+ List m_MosaicPSDLayers = new List();
+ [SerializeField]
+ List m_RigPSDLayers = new List();
+
+ [SerializeField]
+ CharacterData m_CharacterData = new CharacterData();
+
+ [SerializeField]
+ bool m_GenerateGOHierarchy = false;
+
+ [SerializeField]
+ string m_TextureAssetName = null;
+
+ [SerializeField]
+ string m_PrefabAssetName = null;
+
+ [SerializeField]
+ string m_SpriteLibAssetName = null;
+
+ [SerializeField]
+ SecondarySpriteTexture[] m_SecondarySpriteTextures;
+
+ ///
+ /// Implementation of ScriptedImporter.OnImportAsset
+ ///
+ ///
+ /// This argument contains all the contextual information needed to process the import
+ /// event and is also used by the custom importer to store the resulting Unity Asset.
+ ///
+ public override void OnImportAsset(AssetImportContext ctx)
+ {
+ FileStream fileStream = new FileStream(ctx.assetPath, FileMode.Open, FileAccess.Read);
+ Document doc = null;
+ try
+ {
+ UnityEngine.Profiling.Profiler.BeginSample("OnImportAsset");
+
+ UnityEngine.Profiling.Profiler.BeginSample("PsdLoad");
+ doc = PaintDotNet.Data.PhotoshopFileType.PsdLoad.Load(fileStream);
+ UnityEngine.Profiling.Profiler.EndSample();
+
+ ValidatePSDLayerId(doc);
+
+ m_DocumentSize = new Vector2Int(doc.width, doc.height);
+ bool singleSpriteMode = m_TextureImporterSettings.textureType == TextureImporterType.Sprite && m_TextureImporterSettings.spriteMode != (int)SpriteImportMode.Multiple;
+ EnsureSingleSpriteExist();
+
+ if (m_TextureImporterSettings.textureType != TextureImporterType.Sprite ||
+ m_MosaicLayers == false || singleSpriteMode)
+ {
+ var image = new NativeArray(doc.width * doc.height, Allocator.Persistent);
+ try
+ {
+ var spriteImportData = GetSpriteImportData();
+ FlattenImageTask.Execute(doc.Layers, m_ImportHiddenLayers, doc.width, doc.height, image);
+
+ int spriteCount = spriteDataCount;
+ int spriteIndexStart = 1;
+
+ if (spriteImportData.Count <= 0 || spriteImportData[0] == null)
+ {
+ spriteImportData.Add(new SpriteMetaData());
+ }
+ spriteImportData[0].name = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath) + "_1";
+ spriteImportData[0].alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
+ spriteImportData[0].border = m_TextureImporterSettings.spriteBorder;
+ spriteImportData[0].pivot = m_TextureImporterSettings.spritePivot;
+ spriteImportData[0].rect = new Rect(0, 0, doc.width, doc.height);
+ if (singleSpriteMode)
+ {
+ spriteCount = 1;
+ spriteIndexStart = 0;
+ }
+ textureActualWidth = doc.width;
+ textureActualHeight = doc.height;
+ var output = ImportTexture(ctx, image, doc.width, doc.height, spriteIndexStart, spriteCount);
+ RegisterAssets(ctx, output);
+ }
+ finally
+ {
+ image.Dispose();
+ }
+ }
+ else
+ {
+ ImportFromLayers(ctx, doc);
+ }
+ }
+ finally
+ {
+ fileStream.Close();
+ if (doc != null)
+ doc.Dispose();
+ UnityEngine.Profiling.Profiler.EndSample();
+ 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 layers, UniqueNameGenerator uniqueNameGenerator)
+ {
+ for (int i = 0; i < layers.Count; ++i)
+ {
+ if (uniqueNameGenerator.ContainHash(layers[i].LayerID))
+ {
+ var importWarning = string.Format("Layer {0}: LayerId is not unique. Mapping will be done by Layer's name.", layers[i].Name);
+ var layerName = uniqueNameGenerator.GetUniqueName(layers[i].Name);
+ if (layerName != layers[i].Name)
+ importWarning += "\nLayer names are not unique. Please ensure they are unique to for SpriteRect to be mapped back correctly.";
+ layers[i].LayerID = layerName.GetHashCode();
+ Debug.LogWarning(importWarning);
+ }
+ else
+ uniqueNameGenerator.AddHash(layers[i].LayerID);
+ if (layers[i].ChildLayer != null)
+ {
+ ValidatePSDLayerId(layers[i].ChildLayer, uniqueNameGenerator);
+ }
+ }
+ }
+
+
+ void ValidatePSDLayerId(Document doc)
+ {
+ UniqueNameGenerator uniqueNameGenerator = new UniqueNameGenerator();
+
+ ValidatePSDLayerId(doc.Layers, uniqueNameGenerator);
+ }
+
+ TextureGenerationOutput ImportTexture(AssetImportContext ctx, NativeArray imageData, int textureWidth, int textureHeight, int spriteStart, int spriteCount)
+ {
+ if (!imageData.IsCreated || imageData.Length == 0)
+ return new TextureGenerationOutput();
+
+ UnityEngine.Profiling.Profiler.BeginSample("ImportTexture");
+ var platformSettings = GetPlatformTextureSettings(ctx.selectedBuildTarget);
+
+ var textureSettings = m_TextureImporterSettings.ExtractTextureSettings();
+ textureSettings.assetPath = ctx.assetPath;
+ textureSettings.enablePostProcessor = true;
+ textureSettings.containsAlpha = true;
+ textureSettings.hdr = false;
+
+ var textureAlphaSettings = m_TextureImporterSettings.ExtractTextureAlphaSettings();
+ var textureMipmapSettings = m_TextureImporterSettings.ExtractTextureMipmapSettings();
+ var textureCubemapSettings = m_TextureImporterSettings.ExtractTextureCubemapSettings();
+ var textureWrapSettings = m_TextureImporterSettings.ExtractTextureWrapSettings();
+
+ TextureGenerationOutput output;
+ switch (m_TextureImporterSettings.textureType)
+ {
+ case TextureImporterType.Default:
+ output = TextureGeneratorHelper.GenerateTextureDefault(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
+ break;
+ case TextureImporterType.NormalMap:
+ var textureNormalSettings = m_TextureImporterSettings.ExtractTextureNormalSettings();
+ output = TextureGeneratorHelper.GenerateNormalMap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureNormalSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
+ break;
+ case TextureImporterType.GUI:
+ output = TextureGeneratorHelper.GenerateTextureGUI(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
+ break;
+ case TextureImporterType.Sprite:
+ var textureSpriteSettings = m_TextureImporterSettings.ExtractTextureSpriteSettings();
+ textureSpriteSettings.packingTag = m_SpritePackingTag;
+ 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)
+ {
+ //AutoGenerateSpriteSkinData(m_SpriteImportData[spriteStart + i]);
+ textureSpriteSettings.spriteSheetData[i] = spriteImportData[spriteStart + i];
+ }
+ output = TextureGeneratorHelper.GenerateTextureSprite(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureSpriteSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
+ break;
+ case TextureImporterType.Cursor:
+ output = TextureGeneratorHelper.GenerateTextureCursor(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureWrapSettings);
+ break;
+ case TextureImporterType.Cookie:
+ output = TextureGeneratorHelper.GenerateCookie(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
+ break;
+ case TextureImporterType.Lightmap:
+ output = TextureGeneratorHelper.GenerateLightmap(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureMipmapSettings, textureWrapSettings);
+ break;
+ case TextureImporterType.SingleChannel:
+ output = TextureGeneratorHelper.GenerateTextureSingleChannel(imageData, textureWidth, textureHeight, textureSettings, platformSettings, textureAlphaSettings, textureMipmapSettings, textureCubemapSettings, textureWrapSettings);
+ break;
+ default:
+ Debug.LogAssertion("Unknown texture type for import");
+ output = default(TextureGenerationOutput);
+ break;
+ }
+ UnityEngine.Profiling.Profiler.EndSample();
+ return output;
+ }
+
+ void AutoGenerateSpriteSkinData(SpriteMetaData metaData)
+ {
+ //If bone data exist but skinning data doesn't exist, auto generate them
+ if (metaData.spriteBone != null && metaData.spriteBone.Count > 0 &&
+ (metaData.vertices == null || metaData.vertices.Count == 0))
+ {
+ var spriteMeshDataController = new SpriteMeshDataController();
+ var smd = new SpriteMeshData();
+ smd.spriteID = metaData.spriteID;
+ smd.frame = metaData.rect;
+ smd.pivot = metaData.pivot;
+ smd.bones = ModuleUtility.CreateSpriteBoneData(metaData.spriteBone.ToArray(), Matrix4x4.TRS(metaData.rect.position, Quaternion.identity, Vector3.one));
+ spriteMeshDataController.spriteMeshData = smd;
+ spriteMeshDataController.OutlineFromAlpha(new OutlineGenerator(), GetDataProvider(), 0.05f, 200);
+ spriteMeshDataController.Triangulate(new Triangulator());
+ spriteMeshDataController.Subdivide(new Triangulator(), 0.25f);
+ spriteMeshDataController.CalculateWeights(new BoundedBiharmonicWeightsGenerator(), null, 0.01f);
+ spriteMeshDataController.SortTrianglesByDepth();
+
+ List vmd = new List(smd.vertices.Count);
+ foreach (var v in smd.vertices)
+ vmd.Add(new Vertex2DMetaData() { position = v.position - smd.frame.position, boneWeight = v.editableBoneWeight.ToBoneWeight(true) });
+ List emd = new List(smd.edges.Count);
+ foreach (var e in smd.edges)
+ emd.Add(new Vector2Int(e.index1, e.index2));
+
+ metaData.vertices = vmd;
+ metaData.indices = smd.indices.ToArray();
+ metaData.edges = emd.ToArray();
+ }
+ }
+
+ string GetUniqueSpriteName(string name, List namehash)
+ {
+ if (m_KeepDupilcateSpriteName)
+ return name;
+ return GetUniqueName(name, namehash);
+ }
+
+ void ImportFromLayers(AssetImportContext ctx, Document doc)
+ {
+ NativeArray output = default(NativeArray);
+
+ List layerIndex = new List();
+ List spriteNameHash = new List();
+ var oldPsdLayers = GetPSDLayers();
+ try
+ {
+ var psdLayers = new List();
+ ExtractLayerTask.Execute(psdLayers, doc.Layers, m_ImportHiddenLayers);
+ var removedLayersSprite = oldPsdLayers.Where(x => psdLayers.FirstOrDefault(y => y.layerID == x.layerID) == null).Select(z => z.spriteID).ToArray();
+ for (int i = 0; i < psdLayers.Count; ++i)
+ {
+ int j = 0;
+ var psdLayer = psdLayers[i];
+ for (; j < oldPsdLayers.Count; ++j)
+ {
+ if (psdLayer.layerID == oldPsdLayers[j].layerID)
+ {
+ psdLayer.spriteID = oldPsdLayers[j].spriteID;
+ psdLayer.spriteName = oldPsdLayers[j].spriteName;
+ psdLayer.mosaicPosition = oldPsdLayers[j].mosaicPosition;
+ break;
+ }
+ }
+ }
+
+ int expectedBufferLength = doc.width * doc.height;
+ var layerBuffers = new List>();
+ for (int i = 0; i < psdLayers.Count; ++i)
+ {
+ var l = psdLayers[i];
+ if (l.texture.IsCreated && l.texture.Length == expectedBufferLength)
+ {
+ layerBuffers.Add(l.texture);
+ layerIndex.Add(i);
+ }
+ }
+
+ RectInt[] spritedata;
+ int width, height;
+ int padding = 4;
+ Vector2Int[] uvTransform;
+ ImagePacker.Pack(layerBuffers.ToArray(), doc.width, doc.height, padding, out output, out width, out height, out spritedata, out uvTransform);
+ var spriteImportData = GetSpriteImportData();
+ if (spriteImportData.Count <= 0 || shouldResliceFromLayer)
+ {
+ var newSpriteMeta = new List();
+
+ for (int i = 0; i < spritedata.Length && i < layerIndex.Count; ++i)
+ {
+ var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[layerIndex[i]].spriteID);
+ if (spriteSheet == null)
+ {
+ spriteSheet = new SpriteMetaData();
+ spriteSheet.border = Vector4.zero;
+ spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
+ spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
+ }
+
+ psdLayers[layerIndex[i]].spriteName = GetUniqueSpriteName(psdLayers[layerIndex[i]].name, spriteNameHash);
+ spriteSheet.name = psdLayers[layerIndex[i]].spriteName;
+ spriteSheet.rect = new Rect(spritedata[i].x, spritedata[i].y, spritedata[i].width, spritedata[i].height);
+ spriteSheet.uvTransform = uvTransform[i];
+
+ psdLayers[layerIndex[i]].spriteID = spriteSheet.spriteID;
+ psdLayers[layerIndex[i]].mosaicPosition = spritedata[i].position;
+ newSpriteMeta.Add(spriteSheet);
+ }
+ spriteImportData.Clear();
+ spriteImportData.AddRange(newSpriteMeta);
+ }
+ else
+ {
+ spriteImportData.RemoveAll(x => removedLayersSprite.Contains(x.spriteID));
+
+ // First look for any user created SpriteRect and add those into the name hash
+ foreach (var spriteData in spriteImportData)
+ {
+ var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == spriteData.spriteID);
+ if (psdLayer == null)
+ spriteNameHash.Add(spriteData.name.GetHashCode());
+ }
+
+ foreach (var spriteData in spriteImportData)
+ {
+ var psdLayer = psdLayers.FirstOrDefault(x => x.spriteID == spriteData.spriteID);
+ if (psdLayer == null)
+ spriteData.uvTransform = new Vector2Int((int)spriteData.rect.position.x, (int)spriteData.rect.position.y);
+ // If it is user created rect or the name has been changed before
+ // add it into the spriteNameHash and we don't copy it over from the layer
+ if (psdLayer == null || psdLayer.spriteName != spriteData.name)
+ spriteNameHash.Add(spriteData.name.GetHashCode());
+
+ // If the sprite name has not been changed, we ensure the new
+ // layer name is still unique and use it as the sprite name
+ if (psdLayer != null && psdLayer.spriteName == spriteData.name)
+ {
+ psdLayer.spriteName = GetUniqueSpriteName(psdLayer.name, spriteNameHash);
+ spriteData.name = psdLayer.spriteName;
+ }
+ }
+
+ //Update names for those user has not changed and add new sprite rect based on PSD file.
+ for (int k = 0; k < layerIndex.Count; ++k)
+ {
+ int i = layerIndex[k];
+ var spriteSheet = spriteImportData.FirstOrDefault(x => x.spriteID == psdLayers[i].spriteID);
+ var inOldLayer = oldPsdLayers.FindIndex(x => x.layerID == psdLayers[i].layerID) != -1;
+ if (spriteSheet == null && !inOldLayer)
+ {
+ spriteSheet = new SpriteMetaData();
+ spriteImportData.Add(spriteSheet);
+ spriteSheet.rect = new Rect(spritedata[k].x, spritedata[k].y, spritedata[k].width, spritedata[k].height);
+ spriteSheet.border = Vector4.zero;
+ spriteSheet.alignment = (SpriteAlignment)m_TextureImporterSettings.spriteAlignment;
+ spriteSheet.pivot = m_TextureImporterSettings.spritePivot;
+ psdLayers[i].spriteName = GetUniqueSpriteName(psdLayers[i].name, spriteNameHash);
+ spriteSheet.name = psdLayers[i].spriteName;
+ }
+ else if (spriteSheet != null)
+ {
+ var r = spriteSheet.rect;
+ r.position = spriteSheet.rect.position - psdLayers[i].mosaicPosition + spritedata[k].position;
+ spriteSheet.rect = r;
+ }
+
+ if (spriteSheet != null)
+ {
+ spriteSheet.uvTransform = uvTransform[k];
+ psdLayers[i].spriteID = spriteSheet.spriteID;
+ psdLayers[i].mosaicPosition = spritedata[k].position;
+ }
+ }
+ }
+
+ foreach (var l in oldPsdLayers)
+ l.Dispose();
+ oldPsdLayers.Clear();
+
+ oldPsdLayers.AddRange(psdLayers);
+ m_ImportedTextureHeight = textureActualHeight = height;
+ m_ImportedTextureWidth = textureActualWidth = width;
+ var generatedTexture = ImportTexture(ctx, output, width, height, 0, spriteImportData.Count);
+
+ if (generatedTexture.texture)
+ {
+ m_ImportedTextureHeight = generatedTexture.texture.height;
+ m_ImportedTextureWidth = generatedTexture.texture.width;
+ }
+
+ RegisterAssets(ctx, generatedTexture);
+ }
+ finally
+ {
+ if (output.IsCreated)
+ output.Dispose();
+ foreach (var l in oldPsdLayers)
+ l.Dispose();
+ }
+
+ }
+
+ void MemorySnapshotFinish(string path, bool done)
+ {
+
+ }
+
+ void EnsureSingleSpriteExist()
+ {
+ if (m_SpriteImportData.Count <= 0)
+ m_SpriteImportData.Add(new SpriteMetaData()); // insert default for single sprite mode
+ }
+
+ internal TextureImporterPlatformSettings GetPlatformTextureSettings(BuildTarget buildTarget)
+ {
+ var buildTargetName = TexturePlatformSettingsHelper.GetBuildTargetName(buildTarget);
+ TextureImporterPlatformSettings platformSettings = null;
+ platformSettings = m_PlatformSettings.SingleOrDefault(x => x.name == buildTargetName && x.overridden == true);
+ platformSettings = platformSettings ?? m_PlatformSettings.SingleOrDefault(x => x.name == TexturePlatformSettingsHelper.defaultPlatformName);
+
+ if (platformSettings == null)
+ {
+ platformSettings = new TextureImporterPlatformSettings();
+ platformSettings.name = buildTargetName;
+ platformSettings.overridden = false;
+ }
+ return platformSettings;
+ }
+
+ void RegisterAssets(AssetImportContext ctx, TextureGenerationOutput output)
+ {
+ List assetNameHash = new List();
+ if (!string.IsNullOrEmpty(output.importInspectorWarnings))
+ {
+ Debug.LogWarning(output.importInspectorWarnings);
+ }
+ if (output.importWarnings != null && output.importWarnings.Length != 0)
+ {
+ foreach (var warning in output.importWarnings)
+ Debug.LogWarning(warning);
+ }
+ if (output.thumbNail == null)
+ Debug.LogWarning("Thumbnail generation fail");
+ if (output.texture == null)
+ {
+ 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(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;
+
+
+ if (output.sprites != null)
+ {
+ var slAsset = ProduceSpriteLibAsset(output.sprites);
+
+ if (shouldProduceGameObject)
+ {
+ GameObject prefab = null;
+ if (m_PaperDollMode)
+ prefab = OnProducePaperDollPrefab(m_TextureAssetName, output.sprites, slAsset);
+ else
+ prefab = OnProducePrefab(m_TextureAssetName, output.sprites, slAsset);
+ if (prefab != null)
+ {
+ ctx.AddObjectToAsset(m_PrefabAssetName, prefab);
+ mainAsset = prefab;
+ }
+ }
+
+ foreach (var s in output.sprites)
+ {
+ var spriteAssetName = GetUniqueName(s.GetSpriteID().ToString(), assetNameHash, false, s);
+ ctx.AddObjectToAsset(spriteAssetName, s);
+ }
+
+ if (slAsset != null)
+ {
+ slAsset.name = assetName;
+ ctx.AddObjectToAsset(m_SpriteLibAssetName, slAsset);
+ }
+ }
+ ctx.SetMainObject(mainAsset);
+ }
+
+ bool SpriteIsMainFromSpriteLib(string spriteId, out string categoryName)
+ {
+ categoryName = "";
+ if (m_SpriteCategoryList.categories != null)
+ {
+ foreach (var category in m_SpriteCategoryList.categories)
+ {
+ var index = category.labels.FindIndex(x => x.spriteId == spriteId);
+ if (index == 0)
+ {
+ categoryName = category.name;
+ return true;
+ }
+ if (index > 0)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void BuildGroupGameObject(List 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].isGroup == false))
+ {
+ // 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);
+ root = psdGroup[psdGroup[index].parentIndex].gameObject.transform;
+ }
+
+ if (psdGroup[index].gameObject != null)
+ psdGroup[index].gameObject.transform.SetParent(root);
+ }
+ }
+
+ bool shouldProduceGameObject
+ {
+ get { return m_CharacterMode && m_MosaicLayers && spriteImportMode == SpriteImportMode.Multiple; }
+ }
+
+ bool shouldResliceFromLayer
+ {
+ get { return m_ResliceFromLayer && m_MosaicLayers && spriteImportMode == SpriteImportMode.Multiple; }
+ }
+
+ bool characterMode
+ {
+ get { return mosaicMode && m_CharacterMode == true; }
+ }
+
+ float definitionScale
+ {
+ get
+ {
+ float definitionScaleW = m_ImportedTextureWidth / (float)textureActualWidth;
+ float definitionScaleH = m_ImportedTextureHeight / (float)textureActualHeight;
+ return Mathf.Min(definitionScaleW, definitionScaleH);
+ }
+ }
+
+ private Vector2 GetPivotPoint(Rect rect, SpriteAlignment alignment)
+ {
+ switch (alignment)
+ {
+ case SpriteAlignment.TopLeft:
+ return new Vector2(rect.xMin, rect.yMax);
+
+ case SpriteAlignment.TopCenter:
+ return new Vector2(rect.center.x, rect.yMax);
+
+ case SpriteAlignment.TopRight:
+ return new Vector2(rect.xMax, rect.yMax);
+
+ case SpriteAlignment.LeftCenter:
+ return new Vector2(rect.xMin, rect.center.y);
+
+ case SpriteAlignment.Center:
+ return new Vector2(rect.center.x, rect.center.y);
+
+ case SpriteAlignment.RightCenter:
+ return new Vector2(rect.xMax, rect.center.y);
+
+ case SpriteAlignment.BottomLeft:
+ return new Vector2(rect.xMin, rect.yMin);
+
+ case SpriteAlignment.BottomCenter:
+ return new Vector2(rect.center.x, rect.yMin);
+
+ case SpriteAlignment.BottomRight:
+ return new Vector2(rect.xMax, rect.yMin);
+
+ case SpriteAlignment.Custom:
+ return new Vector2(m_DocumentPivot.x * rect.width, m_DocumentPivot.y * rect.height);
+ }
+ return Vector2.zero;
+ }
+
+ void CreateBoneGO(int index, SpriteBone[] bones, BoneGO[] bonesGO, Transform defaultRoot)
+ {
+ if (bonesGO[index].go != null)
+ return;
+ var bone = bones[index];
+ if (bone.parentId != -1 && bonesGO[bone.parentId].go == null)
+ CreateBoneGO(bone.parentId, bones, bonesGO, defaultRoot);
+
+ var go = m_GameObjectFactory.CreateGameObject(bone.name);
+ if (bone.parentId == -1)
+ go.transform.SetParent(defaultRoot);
+ else
+ go.transform.SetParent(bonesGO[bone.parentId].go.transform);
+ go.transform.localPosition = bone.position * 1 / pixelsPerUnit;
+ go.transform.localRotation = bone.rotation;
+ bonesGO[index] = new BoneGO()
+ {
+ go = go,
+ index = index
+ };
+ }
+
+ BoneGO[] CreateBonesGO(Transform root)
+ {
+ if (characterMode)
+ {
+ var characterSkeleton = GetDataProvider().GetCharacterData();
+ var bones = characterSkeleton.bones;
+ if (bones != null)
+ {
+ var boneGOs = new BoneGO[bones.Length];
+ for (int i = 0; i < bones.Length; ++i)
+ {
+ CreateBoneGO(i, bones, boneGOs, root);
+ }
+ return boneGOs;
+ }
+ }
+ return new BoneGO[0];
+ }
+
+ void GetSpriteLiblabel(string spriteId, out string category, out string label)
+ {
+ category = "";
+ label = "";
+ var index = -1;
+ foreach (var cat in m_SpriteCategoryList.categories)
+ {
+ index = cat.labels.FindIndex(x => x.spriteId == spriteId);
+ if (index != -1)
+ {
+ category = cat.name;
+ label = cat.labels[index].name;
+ break;
+ }
+ }
+ }
+
+ GameObject OnProducePaperDollPrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
+ {
+ GameObject root = null;
+ CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider().GetCharacterData()) : null;
+ if (sprites != null && sprites.Length > 0)
+ {
+ root = new GameObject();
+ root.name = assetname + "_GO";
+ var spriteImportData = GetSpriteImportData();
+ var psdLayers = GetPSDLayers();
+ var boneGOs = CreateBonesGO(root.transform);
+ if (spriteLib != null)
+ root.AddComponent().spriteLibraryAsset = 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 < boneGOs.Length).Select(x => 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();
+ 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 labelName = "";
+ GetSpriteLiblabel(sprites[i].GetSpriteID().ToString(), out category, out labelName);
+ if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
+ {
+ var sresolver = srGameObject.AddComponent();
+ sresolver.SetCategoryAndLabel(category, labelName);
+ sresolver.ResolveSpriteToSpriteRenderer();
+ }
+ }
+ }
+ }
+ return root;
+ }
+
+ internal void SetPlatformTextureSettings(TextureImporterPlatformSettings platformSettings)
+ {
+ var index = m_PlatformSettings.FindIndex(x => x.name == platformSettings.name);
+ if(index < 0)
+ m_PlatformSettings.Add(platformSettings);
+ else
+ m_PlatformSettings[index] = platformSettings;
+ }
+
+ internal TextureImporterPlatformSettings[] GetAllPlatformSettings()
+ {
+ return m_PlatformSettings.ToArray();
+ }
+
+ GameObject OnProducePrefab(string assetname, Sprite[] sprites, SpriteLibraryAsset spriteLib)
+ {
+ GameObject root = null;
+ CharacterData? characterSkeleton = characterMode ? new CharacterData ? (GetDataProvider().GetCharacterData()) : null;
+ if (sprites != null && sprites.Length > 0)
+ {
+ var spriteImportData = GetSpriteImportData();
+ root = new GameObject();
+ root.name = assetname + "_GO";
+ if (spriteLib != null)
+ root.AddComponent().spriteLibraryAsset = spriteLib;
+
+ var psdLayers = GetPSDLayers();
+ for (int i = 0; i < psdLayers.Count; ++i)
+ {
+ BuildGroupGameObject(psdLayers, i, root.transform);
+ }
+ var boneGOs = CreateBonesGO(root.transform);
+ for (int i = 0; i < psdLayers.Count; ++i)
+ {
+ var l = psdLayers[i];
+ 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 && l.gameObject != null)
+ {
+ var spriteRenderer = l.gameObject.AddComponent();
+ spriteRenderer.sprite = sprite;
+ 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;
+ l.gameObject.transform.position = new Vector3(outlineOffset.x, outlineOffset.y, 0);
+
+ if (characterSkeleton != null)
+ {
+ var part = characterSkeleton.Value.parts.FirstOrDefault(x => x.spriteId == spriteMetaData.spriteID.ToString());
+ if (part.bones != null && part.bones.Length > 0)
+ {
+ var spriteSkin = l.gameObject.AddComponent();
+ 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]);
+ if (spriteBones.Any())
+ {
+ spriteSkin.rootBone = spriteBones.OrderBy(x => x.index).First().go.transform;
+ spriteSkin.boneTransforms = spriteBones.Select(x => x.go.transform).ToArray();
+ if (spriteSkin.isValid)
+ spriteSkin.CalculateBounds();
+ }
+ }
+ }
+ }
+
+ var category = "";
+ var labelName = "";
+ GetSpriteLiblabel(layerSpriteID.ToString(), out category, out labelName);
+ if (!string.IsNullOrEmpty(category) && !string.IsNullOrEmpty(labelName))
+ {
+ var sresolver = l.gameObject.AddComponent();
+ sresolver.SetCategoryAndLabel(category, labelName);
+ sresolver.ResolveSpriteToSpriteRenderer();
+ }
+ }
+ }
+
+ var prefabBounds = new Rect(0 , 0, m_DocumentSize.x / pixelsPerUnit, m_DocumentSize.y / pixelsPerUnit);
+ var documentPivot = (Vector3)GetPivotPoint(prefabBounds, m_DocumentAlignment);
+ for (int i = 0; i < psdLayers.Count; ++i)
+ {
+ var l = psdLayers[i];
+ if (l.gameObject == null || l.gameObject.GetComponent() == null)
+ continue;
+ var p = l.gameObject.transform.localPosition;
+ p -= documentPivot;
+ l.gameObject.transform.localPosition = p;
+ }
+ for (int i = 0; i < boneGOs.Length; ++i)
+ {
+ if (boneGOs[i].go.transform.parent != root.transform)
+ continue;
+ var p = boneGOs[i].go.transform.position;
+ p -= documentPivot;
+ boneGOs[i].go.transform.position = p;
+ }
+ }
+
+ return root;
+ }
+
+ Bounds? GetBoundingBox(GameObject root)
+ {
+ Bounds? prefabBounds1 = null;
+ var sr = root.GetComponent();
+ if (sr != null)
+ {
+ prefabBounds1 = sr.bounds;
+ }
+ for (int i = 0; i < root.transform.childCount; ++i)
+ {
+ var b = GetBoundingBox(root.transform.GetChild(i).gameObject);
+ if (prefabBounds1 == null)
+ prefabBounds1 = b;
+ else
+ {
+ if (b.HasValue)
+ {
+ var bb = prefabBounds1.Value;
+ bb.Encapsulate(b.Value);
+ prefabBounds1 = bb;
+ }
+ }
+ }
+ return prefabBounds1;
+ }
+
+ bool CleanUpGameobjectsWithOutRig(GameObject root)
+ {
+ var sr = root.GetComponent();
+ var canDelete = true;
+ if (sr != null && sr.sprite != null)
+ {
+ try
+ {
+ var bones = GetDataProvider().GetBones(sr.sprite.GetSpriteID());
+ canDelete = bones == null || bones.Count == 0;
+ }
+ catch (Exception e)
+ {
+ Debug.LogError(e);
+ }
+ }
+
+
+ List cleanup = new List();
+ for (int i = 0; i < root.transform.childCount; ++i)
+ {
+ var go = root.transform.GetChild(i);
+ if (CleanUpGameobjectsWithOutRig(go.gameObject))
+ cleanup.Add(go.gameObject);
+ }
+
+ for (int i = 0; i < cleanup.Count; ++i)
+ GameObject.DestroyImmediate(cleanup[i]);
+ cleanup.Clear();
+
+ if (root.transform.childCount == 0 && canDelete)
+ return true;
+
+ return false;
+ }
+
+ static string SanitizeName(string name)
+ {
+ string newName = null;
+ // We can't create asset name with these name.
+ if ((name.Length == 2 && name[0] == '.' && name[1] == '.')
+ || (name.Length == 1 && name[0] == '.')
+ || (name.Length == 1 && name[0] == '/'))
+ newName += name + "_";
+
+ if (!string.IsNullOrEmpty(newName))
+ {
+ Debug.LogWarning(string.Format("File contains layer with invalid name for generating asset. {0} is renamed to {1}", name, newName));
+ return newName;
+ }
+ return name;
+ }
+
+ static string GetUniqueName(string name, List stringHash, bool logNewNameGenerated = false, UnityEngine.Object context = null)
+ {
+ string uniqueName = string.Copy(SanitizeName(name));
+ int index = 1;
+ while (true)
+ {
+ int hash = uniqueName.GetHashCode();
+ var p = stringHash.Where(x => x == hash);
+ if (!p.Any())
+ {
+ stringHash.Add(hash);
+ if (logNewNameGenerated && name != uniqueName)
+ Debug.Log(string.Format("Asset name {0} is changed to {1} to ensure uniqueness", name, uniqueName), context);
+ return uniqueName;
+ }
+ uniqueName = string.Format("{0}_{1}", name, index);
+ ++index;
+ }
+ }
+
+ // ISpriteEditorDataProvider interface
+ internal SpriteImportMode spriteImportMode
+ {
+ get
+ {
+ return m_TextureImporterSettings.textureType != TextureImporterType.Sprite ?
+ SpriteImportMode.None :
+ (SpriteImportMode)m_TextureImporterSettings.spriteMode;
+ }
+ }
+
+ SpriteImportMode ISpriteEditorDataProvider.spriteImportMode => spriteImportMode;
+
+ internal int spriteDataCount
+ {
+ get
+ {
+ var spriteImportData = GetSpriteImportData();
+ if (mosaicMode)
+ return spriteImportData.Count;
+ if (spriteImportMode != SpriteImportMode.Multiple)
+ return 1;
+ return spriteImportData.Count - 1;
+ }
+ }
+
+ internal UnityEngine.Object targetObject
+ {
+ get { return this; }
+ }
+ UnityEngine.Object ISpriteEditorDataProvider.targetObject => targetObject;
+
+ internal float pixelsPerUnit
+ {
+ get { return m_TextureImporterSettings.spritePixelsPerUnit; }
+ }
+
+ float ISpriteEditorDataProvider.pixelsPerUnit =>pixelsPerUnit;
+
+ internal T GetDataProvider() where T : class
+ {
+ if (typeof(T) == typeof(ISpriteBoneDataProvider))
+ {
+ return new SpriteBoneDataProvider { dataProvider = this } as T;
+ }
+ if (typeof(T) == typeof(ISpriteMeshDataProvider))
+ {
+ return new SpriteMeshDataProvider { dataProvider = this } as T;
+ }
+ if (typeof(T) == typeof(ISpriteOutlineDataProvider))
+ {
+ return new SpriteOutlineDataProvider { dataProvider = this } as T;
+ }
+ if (typeof(T) == typeof(ISpritePhysicsOutlineDataProvider))
+ {
+ return new SpritePhysicsOutlineProvider { dataProvider = this } as T;
+ }
+ if (typeof(T) == typeof(ITextureDataProvider))
+ {
+ return new TextureDataProvider { dataProvider = this } as T;
+ }
+ if (typeof(T) == typeof(ICharacterDataProvider))
+ {
+ 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;
+ }
+ else
+ return this as T;
+ }
+
+ T ISpriteEditorDataProvider.GetDataProvider()
+ {
+ return GetDataProvider();
+ }
+
+ internal bool HasDataProvider(Type type)
+ {
+ if (characterMode && type == typeof(ICharacterDataProvider))
+ return true;
+ if (type == typeof(ISpriteBoneDataProvider) ||
+ type == typeof(ISpriteMeshDataProvider) ||
+ type == typeof(ISpriteOutlineDataProvider) ||
+ type == typeof(ISpritePhysicsOutlineDataProvider) ||
+ type == typeof(ITextureDataProvider) ||
+ type == typeof(ISpriteLibDataProvider) ||
+ type == typeof(ISecondaryTextureDataProvider))
+ {
+ return true;
+ }
+ else
+ return type.IsAssignableFrom(GetType());
+ }
+
+ bool ISpriteEditorDataProvider.HasDataProvider(Type type)
+ {
+ return HasDataProvider(type);
+ }
+
+ internal void AddSpriteData(SpriteRect spriteRect)
+ {
+ if (spriteImportMode != SpriteImportMode.Multiple)
+ Debug.LogWarning("Can only add sprite data when import mode is multiple");
+ else
+ {
+ GetSpriteImportData().Add(new SpriteMetaData(spriteRect));
+ }
+ }
+
+ internal void DeleteSpriteData(SpriteRect spriteRect)
+ {
+ if (spriteImportMode != SpriteImportMode.Multiple)
+ Debug.LogWarning("Can only add sprite data when import mode is multiple");
+ else
+ {
+ var spriteImportData = GetSpriteImportData();
+ int index = spriteImportData.FindIndex(x => x.spriteID == spriteRect.spriteID);
+ Assert.AreEqual(0, index, "Cannot delete Sprite from single sprite mode");
+ spriteImportData.RemoveAt(index);
+ }
+ }
+
+ internal int GetSpriteDataIndex(GUID guid)
+ {
+ switch (spriteImportMode)
+ {
+ case SpriteImportMode.Single:
+ case SpriteImportMode.Polygon:
+ return 0;
+ case SpriteImportMode.Multiple:
+ {
+ var spriteImportData = GetSpriteImportData();
+ return spriteImportData.FindIndex(x => x.spriteID == guid);
+ }
+ default:
+ throw new InvalidOperationException("GUID not found");
+ }
+ }
+
+ internal void Apply()
+ {
+ // Do this so that asset change save dialog will not show
+ var originalValue = EditorPrefs.GetBool("VerifySavingAssets", false);
+ EditorPrefs.SetBool("VerifySavingAssets", false);
+ AssetDatabase.ForceReserializeAssets(new string[] { assetPath }, ForceReserializeAssetsOptions.ReserializeMetadata);
+ EditorPrefs.SetBool("VerifySavingAssets", originalValue);
+ }
+
+ void ISpriteEditorDataProvider.Apply()
+ {
+ Apply();
+ }
+
+ internal void InitSpriteEditorDataProvider() {}
+ void ISpriteEditorDataProvider.InitSpriteEditorDataProvider()
+ {
+ InitSpriteEditorDataProvider();
+ }
+
+ internal SpriteRect[] GetSpriteRects()
+ {
+ var spriteImportData = GetSpriteImportData();
+ var skip = mosaicMode ? 0 : 1;
+ return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).Select(x => new SpriteMetaData(x) as SpriteRect).ToArray() : new[] {new SpriteMetaData(spriteImportData[0]) };
+ }
+
+ SpriteRect[] ISpriteEditorDataProvider.GetSpriteRects()
+ {
+ return GetSpriteRects();
+ }
+
+ List GetSpriteImportData()
+ {
+ return mosaicMode ? (characterMode ? m_RigSpriteImportData : m_MosaicSpriteImportData) : m_SpriteImportData;
+ }
+
+ internal List GetPSDLayers()
+ {
+ return mosaicMode ? (characterMode ? m_RigPSDLayers : m_MosaicPSDLayers) : null;
+ }
+
+ internal SpriteMetaData[] GetSpriteMetaData()
+ {
+ var spriteImportData = GetSpriteImportData();
+ var skip = mosaicMode ? 0 : 1;
+ return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).ToArray() : new[] { new SpriteMetaData(spriteImportData[0]) };
+ }
+
+ internal SpriteRect GetSpriteDataFromAllMode(GUID guid)
+ {
+ var spriteMetaData = m_RigSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
+ if(spriteMetaData == null)
+ spriteMetaData = m_MosaicSpriteImportData.FirstOrDefault(x => x.spriteID == guid);
+ if(spriteMetaData == null)
+ spriteMetaData = m_SpriteImportData.FirstOrDefault(x => x.spriteID == guid);
+ return spriteMetaData;
+ }
+
+ internal SpriteRect GetSpriteData(GUID guid)
+ {
+ var spriteImportData = GetSpriteImportData();
+ var skip = mosaicMode ? 0 : 1;
+ return spriteImportMode == SpriteImportMode.Multiple ? spriteImportData.Skip(skip).FirstOrDefault(x => x.spriteID == guid) : spriteImportData[0];
+ }
+
+ internal void SetSpriteRects(SpriteRect[] spriteRects)
+ {
+ var spriteImportData = GetSpriteImportData();
+ if (spriteImportMode == SpriteImportMode.Multiple)
+ {
+ var singleSpriteID = mosaicMode ? new GUID() : spriteImportData[0].spriteID;
+ spriteImportData.RemoveAll(data => data.spriteID != singleSpriteID && spriteRects.FirstOrDefault(x => x.spriteID == data.spriteID) == null);
+ foreach (var sr in spriteRects)
+ {
+ var importData = spriteImportData.FirstOrDefault(x => x.spriteID == sr.spriteID);
+ if (importData == null)
+ spriteImportData.Add(new SpriteMetaData(sr));
+ else
+ {
+ importData.name = sr.name;
+ importData.alignment = sr.alignment;
+ importData.border = sr.border;
+ importData.pivot = sr.pivot;
+ importData.rect = sr.rect;
+ }
+ }
+ }
+ else if (spriteRects.Length == 1 && (spriteImportMode == SpriteImportMode.Single || spriteImportMode == SpriteImportMode.Polygon))
+ {
+ if (spriteImportData[0].spriteID == spriteRects[0].spriteID)
+ {
+ spriteImportData[0].name = spriteRects[0].name;
+ spriteImportData[0].alignment = spriteRects[0].alignment;
+ m_TextureImporterSettings.spriteAlignment = (int)spriteRects[0].alignment;
+ m_TextureImporterSettings.spriteBorder = spriteImportData[0].border = spriteRects[0].border;
+ m_TextureImporterSettings.spritePivot = spriteImportData[0].pivot = spriteRects[0].pivot;
+ spriteImportData[0].rect = spriteRects[0].rect;
+ }
+ else
+ {
+ spriteImportData[0] = new SpriteMetaData(spriteRects[0]);
+ }
+ }
+ }
+
+ void ISpriteEditorDataProvider.SetSpriteRects(SpriteRect[] spriteRects)
+ {
+ SetSpriteRects(spriteRects);
+ }
+
+ bool mosaicMode
+ {
+ get { return spriteImportMode == SpriteImportMode.Multiple && m_MosaicLayers; }
+ }
+
+ internal CharacterData characterData
+ {
+ get { return m_CharacterData; }
+ set { m_CharacterData = value; }
+ }
+
+ internal Vector2Int documentSize
+ {
+ get { return m_DocumentSize; }
+ }
+
+ SpriteLibraryAsset ProduceSpriteLibAsset(Sprite[] sprites)
+ {
+ if (!characterMode || m_SpriteCategoryList.categories == null)
+ return null;
+ var sla = ScriptableObject.CreateInstance();
+ sla.name = "Sprite Lib";
+ sla.categories = m_SpriteCategoryList.categories.Select(x =>
+ new SpriteLibCategory()
+ {
+ name = x.name,
+ categoryList = x.labels.Select(y =>
+ {
+ 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; }
+ }
+
+ internal void ReadTextureSettings(TextureImporterSettings dest)
+ {
+ m_TextureImporterSettings.CopyTo(dest);
+ }
+ }
+}
diff --git a/Editor/PSDImporter.cs.meta b/Editor/PSDImporter.cs.meta
index d44cb68..c4c99ed 100644
--- a/Editor/PSDImporter.cs.meta
+++ b/Editor/PSDImporter.cs.meta
@@ -1,11 +1,11 @@
-fileFormatVersion: 2
-guid: b2a9591990af98743ba3ff7cf1000886
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: b2a9591990af98743ba3ff7cf1000886
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDImporterDataProvider.cs b/Editor/PSDImporterDataProvider.cs
index 5fe0515..7792287 100644
--- a/Editor/PSDImporterDataProvider.cs
+++ b/Editor/PSDImporterDataProvider.cs
@@ -1,299 +1,299 @@
-using System.Collections.Generic;
-using System.Linq;
-using UnityEngine;
-using UnityEngine.Assertions;
-using UnityEditor.U2D.Common;
-using UnityEditor.U2D.Animation;
-using System;
-using UnityEditor.U2D.Sprites;
-using UnityEngine.U2D;
-
-namespace UnityEditor.U2D.PSD
-{
- internal abstract class PSDDataProvider
- {
- public PSDImporter dataProvider;
- }
-
- internal class SpriteBoneDataProvider : PSDDataProvider, ISpriteBoneDataProvider
- {
- public List GetBones(GUID guid)
- {
- var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
- Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
- return sprite.spriteBone != null ? sprite.spriteBone.ToList() : new List();
- }
-
- public void SetBones(GUID guid, List bones)
- {
- var sprite = dataProvider.GetSpriteData(guid);
- if (sprite != null)
- ((SpriteMetaData)sprite).spriteBone = bones;
- }
- }
-
- internal class TextureDataProvider : PSDDataProvider, ITextureDataProvider
- {
- Texture2D m_ReadableTexture;
- Texture2D m_OriginalTexture;
-
- PSDImporter textureImporter { get { return (PSDImporter)dataProvider.targetObject; } }
-
- public Texture2D texture
- {
- get
- {
- if (m_OriginalTexture == null)
- m_OriginalTexture = AssetDatabase.LoadAssetAtPath(textureImporter.assetPath);
- return m_OriginalTexture;
- }
- }
-
- public Texture2D previewTexture
- {
- get { return texture; }
- }
-
- public Texture2D GetReadableTexture2D()
- {
- if (m_ReadableTexture == null)
- {
- m_ReadableTexture = InternalEditorBridge.CreateTemporaryDuplicate(texture, texture.width, texture.height);
- if (m_ReadableTexture != null)
- m_ReadableTexture.filterMode = texture.filterMode;
- }
- return m_ReadableTexture;
- }
-
- public void GetTextureActualWidthAndHeight(out int width, out int height)
- {
- width = dataProvider.textureActualWidth;
- height = dataProvider.textureActualHeight;
- }
- }
-
- internal class SecondaryTextureDataProvider : PSDDataProvider, ISecondaryTextureDataProvider
- {
- public SecondarySpriteTexture[] textures
- {
- get { return dataProvider.secondaryTextures; }
- set { dataProvider.secondaryTextures = value; }
- }
- }
-
- internal class SpriteOutlineDataProvider : PSDDataProvider, ISpriteOutlineDataProvider
- {
- public List GetOutlines(GUID guid)
- {
- var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
- Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
-
- var outline = sprite.spriteOutline;
- if (outline != null)
- return outline.Select(x => x.outline).ToList();
- return new List();
- }
-
- public void SetOutlines(GUID guid, List data)
- {
- var sprite = dataProvider.GetSpriteData(guid);
- if (sprite != null)
- ((SpriteMetaData)sprite).spriteOutline = data.Select(x => new SpriteOutline() {outline = x}).ToList();
- }
-
- public float GetTessellationDetail(GUID guid)
- {
- return ((SpriteMetaData)dataProvider.GetSpriteData(guid)).tessellationDetail;
- }
-
- public void SetTessellationDetail(GUID guid, float value)
- {
- var sprite = dataProvider.GetSpriteData(guid);
- if (sprite != null)
- ((SpriteMetaData)sprite).tessellationDetail = value;
- }
- }
-
- internal class SpritePhysicsOutlineProvider : PSDDataProvider, ISpritePhysicsOutlineDataProvider
- {
- public List GetOutlines(GUID guid)
- {
- var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
- Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
- var outline = sprite.spritePhysicsOutline;
- if (outline != null)
- return outline.Select(x => x.outline).ToList();
-
- return new List();
- }
-
- public void SetOutlines(GUID guid, List data)
- {
- var sprite = dataProvider.GetSpriteData(guid);
- if (sprite != null)
- ((SpriteMetaData)sprite).spritePhysicsOutline = data.Select(x => new SpriteOutline() { outline = x }).ToList();
- }
-
- public float GetTessellationDetail(GUID guid)
- {
- return ((SpriteMetaData)dataProvider.GetSpriteData(guid)).tessellationDetail;
- }
-
- public void SetTessellationDetail(GUID guid, float value)
- {
- var sprite = dataProvider.GetSpriteData(guid);
- if (sprite != null)
- ((SpriteMetaData)sprite).tessellationDetail = value;
- }
- }
-
- internal class SpriteMeshDataProvider : PSDDataProvider, ISpriteMeshDataProvider
- {
- public Vertex2DMetaData[] GetVertices(GUID guid)
- {
- var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
- Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
- var v = sprite.vertices;
- if (v != null)
- return v.ToArray();
-
- return new Vertex2DMetaData[0];
- }
-
- public void SetVertices(GUID guid, Vertex2DMetaData[] vertices)
- {
- var sprite = dataProvider.GetSpriteData(guid);
- if (sprite != null)
- ((SpriteMetaData)sprite).vertices = vertices.ToList();
- }
-
- public int[] GetIndices(GUID guid)
- {
- var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
- Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
- var v = sprite.indices;
- if (v != null)
- return v;
-
- return new int[0];
- }
-
- public void SetIndices(GUID guid, int[] indices)
- {
- var sprite = dataProvider.GetSpriteData(guid);
- if (sprite != null)
- ((SpriteMetaData)sprite).indices = indices;
- }
-
- public Vector2Int[] GetEdges(GUID guid)
- {
- var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
- Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
- var v = sprite.edges;
- if (v != null)
- return v;
-
- return new Vector2Int[0];
- }
-
- public void SetEdges(GUID guid, Vector2Int[] edges)
- {
- var sprite = dataProvider.GetSpriteData(guid);
- if (sprite != null)
- ((SpriteMetaData)sprite).edges = edges;
- }
- }
-
-
- internal class CharacterDataProvider : PSDDataProvider, ICharacterDataProvider
- {
- int ParentGroupInFlatten(int parentIndex, List 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 = new List();
- for (int i = 0; i < psdLayers.Count; ++i)
- {
- if (psdLayers[i].isGroup)
- {
- groups.Add(new CharacterGroup()
- {
- name = psdLayers[i].name,
- parentGroup = ParentGroupInFlatten(psdLayers[i].parentIndex, psdLayers),
- order = i
- });
- }
- }
-
- var cd = dataProvider.characterData;
- var parts = cd.parts == null ? new List() : cd.parts.ToList();
- var spriteRects = dataProvider.GetSpriteMetaData();
- parts.RemoveAll(x => Array.FindIndex(spriteRects, y => y.spriteID == new GUID(x.spriteId)) == -1);
- foreach (var spriteMetaData in spriteRects)
- {
- var srIndex = parts.FindIndex(x => new GUID(x.spriteId) == spriteMetaData.spriteID);
- CharacterPart cp = srIndex == -1 ? new CharacterPart() : parts[srIndex];
- cp.spriteId = spriteMetaData.spriteID.ToString();
- cp.order = psdLayers.FindIndex(l => l.spriteID == spriteMetaData.spriteID);
- cp.spritePosition = new RectInt();
- var uvTransform = spriteMetaData.uvTransform;
- 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
- parts[srIndex] = cp;
- }
-
- var layers = dataProvider.GetPSDLayers();
- parts.Sort((x, y) =>
- {
- return x.order.CompareTo(y.order);
- });
-
- parts.Reverse();
- cd.parts = parts.ToArray();
- cd.dimension = dataProvider.documentSize;
- cd.characterGroups = groups.ToArray();
- return cd;
- }
-
- public void SetCharacterData(CharacterData characterData)
- {
- characterData.parts = characterData.parts.Reverse().ToArray();
- dataProvider.characterData = characterData;
- }
- }
-
- internal class SpriteLibraryDataProvider : PSDDataProvider, ISpriteLibDataProvider
- {
- public SpriteCategoryList GetSpriteCategoryList()
- {
- return dataProvider.spriteCategoryList;
- }
-
- public void SetSpriteCategoryList(SpriteCategoryList spriteCategoryList)
- {
- dataProvider.spriteCategoryList = spriteCategoryList;
- }
- }
-}
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using UnityEngine.Assertions;
+using UnityEditor.U2D.Common;
+using UnityEditor.U2D.Animation;
+using System;
+using UnityEditor.U2D.Sprites;
+using UnityEngine.U2D;
+
+namespace UnityEditor.U2D.PSD
+{
+ internal abstract class PSDDataProvider
+ {
+ public PSDImporter dataProvider;
+ }
+
+ internal class SpriteBoneDataProvider : PSDDataProvider, ISpriteBoneDataProvider
+ {
+ public List GetBones(GUID guid)
+ {
+ var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
+ Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
+ return sprite.spriteBone != null ? sprite.spriteBone.ToList() : new List();
+ }
+
+ public void SetBones(GUID guid, List bones)
+ {
+ var sprite = dataProvider.GetSpriteDataFromAllMode(guid);
+ if (sprite != null)
+ ((SpriteMetaData)sprite).spriteBone = bones;
+ }
+ }
+
+ internal class TextureDataProvider : PSDDataProvider, ITextureDataProvider
+ {
+ Texture2D m_ReadableTexture;
+ Texture2D m_OriginalTexture;
+
+ PSDImporter textureImporter { get { return (PSDImporter)dataProvider.targetObject; } }
+
+ public Texture2D texture
+ {
+ get
+ {
+ if (m_OriginalTexture == null)
+ m_OriginalTexture = AssetDatabase.LoadAssetAtPath(textureImporter.assetPath);
+ return m_OriginalTexture;
+ }
+ }
+
+ public Texture2D previewTexture
+ {
+ get { return texture; }
+ }
+
+ public Texture2D GetReadableTexture2D()
+ {
+ if (m_ReadableTexture == null)
+ {
+ m_ReadableTexture = InternalEditorBridge.CreateTemporaryDuplicate(texture, texture.width, texture.height);
+ if (m_ReadableTexture != null)
+ m_ReadableTexture.filterMode = texture.filterMode;
+ }
+ return m_ReadableTexture;
+ }
+
+ public void GetTextureActualWidthAndHeight(out int width, out int height)
+ {
+ width = dataProvider.textureActualWidth;
+ height = dataProvider.textureActualHeight;
+ }
+ }
+
+ internal class SecondaryTextureDataProvider : PSDDataProvider, ISecondaryTextureDataProvider
+ {
+ public SecondarySpriteTexture[] textures
+ {
+ get { return dataProvider.secondaryTextures; }
+ set { dataProvider.secondaryTextures = value; }
+ }
+ }
+
+ internal class SpriteOutlineDataProvider : PSDDataProvider, ISpriteOutlineDataProvider
+ {
+ public List GetOutlines(GUID guid)
+ {
+ var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
+ Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
+
+ var outline = sprite.spriteOutline;
+ if (outline != null)
+ return outline.Select(x => x.outline).ToList();
+ return new List();
+ }
+
+ public void SetOutlines(GUID guid, List data)
+ {
+ var sprite = dataProvider.GetSpriteDataFromAllMode(guid);
+ if (sprite != null)
+ ((SpriteMetaData)sprite).spriteOutline = data.Select(x => new SpriteOutline() {outline = x}).ToList();
+ }
+
+ public float GetTessellationDetail(GUID guid)
+ {
+ return ((SpriteMetaData)dataProvider.GetSpriteData(guid)).tessellationDetail;
+ }
+
+ public void SetTessellationDetail(GUID guid, float value)
+ {
+ var sprite = dataProvider.GetSpriteDataFromAllMode(guid);
+ if (sprite != null)
+ ((SpriteMetaData)sprite).tessellationDetail = value;
+ }
+ }
+
+ internal class SpritePhysicsOutlineProvider : PSDDataProvider, ISpritePhysicsOutlineDataProvider
+ {
+ public List GetOutlines(GUID guid)
+ {
+ var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
+ Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
+ var outline = sprite.spritePhysicsOutline;
+ if (outline != null)
+ return outline.Select(x => x.outline).ToList();
+
+ return new List();
+ }
+
+ public void SetOutlines(GUID guid, List data)
+ {
+ var sprite = dataProvider.GetSpriteDataFromAllMode(guid);
+ if (sprite != null)
+ ((SpriteMetaData)sprite).spritePhysicsOutline = data.Select(x => new SpriteOutline() { outline = x }).ToList();
+ }
+
+ public float GetTessellationDetail(GUID guid)
+ {
+ return ((SpriteMetaData)dataProvider.GetSpriteData(guid)).tessellationDetail;
+ }
+
+ public void SetTessellationDetail(GUID guid, float value)
+ {
+ var sprite = dataProvider.GetSpriteDataFromAllMode(guid);
+ if (sprite != null)
+ ((SpriteMetaData)sprite).tessellationDetail = value;
+ }
+ }
+
+ internal class SpriteMeshDataProvider : PSDDataProvider, ISpriteMeshDataProvider
+ {
+ public Vertex2DMetaData[] GetVertices(GUID guid)
+ {
+ var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
+ Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
+ var v = sprite.vertices;
+ if (v != null)
+ return v.ToArray();
+
+ return new Vertex2DMetaData[0];
+ }
+
+ public void SetVertices(GUID guid, Vertex2DMetaData[] vertices)
+ {
+ var sprite = dataProvider.GetSpriteDataFromAllMode(guid);
+ if (sprite != null)
+ ((SpriteMetaData)sprite).vertices = vertices.ToList();
+ }
+
+ public int[] GetIndices(GUID guid)
+ {
+ var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
+ Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
+ var v = sprite.indices;
+ if (v != null)
+ return v;
+
+ return new int[0];
+ }
+
+ public void SetIndices(GUID guid, int[] indices)
+ {
+ var sprite = dataProvider.GetSpriteDataFromAllMode(guid);
+ if (sprite != null)
+ ((SpriteMetaData)sprite).indices = indices;
+ }
+
+ public Vector2Int[] GetEdges(GUID guid)
+ {
+ var sprite = ((SpriteMetaData)dataProvider.GetSpriteData(guid));
+ Assert.IsNotNull(sprite, string.Format("Sprite not found for GUID:{0}", guid.ToString()));
+ var v = sprite.edges;
+ if (v != null)
+ return v;
+
+ return new Vector2Int[0];
+ }
+
+ public void SetEdges(GUID guid, Vector2Int[] edges)
+ {
+ var sprite = dataProvider.GetSpriteDataFromAllMode(guid);
+ if (sprite != null)
+ ((SpriteMetaData)sprite).edges = edges;
+ }
+ }
+
+
+ internal class CharacterDataProvider : PSDDataProvider, ICharacterDataProvider
+ {
+ int ParentGroupInFlatten(int parentIndex, List 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 = new List();
+ for (int i = 0; i < psdLayers.Count; ++i)
+ {
+ if (psdLayers[i].isGroup)
+ {
+ groups.Add(new CharacterGroup()
+ {
+ name = psdLayers[i].name,
+ parentGroup = ParentGroupInFlatten(psdLayers[i].parentIndex, psdLayers),
+ order = i
+ });
+ }
+ }
+
+ var cd = dataProvider.characterData;
+ var parts = cd.parts == null ? new List() : cd.parts.ToList();
+ var spriteRects = dataProvider.GetSpriteMetaData();
+ parts.RemoveAll(x => Array.FindIndex(spriteRects, y => y.spriteID == new GUID(x.spriteId)) == -1);
+ foreach (var spriteMetaData in spriteRects)
+ {
+ var srIndex = parts.FindIndex(x => new GUID(x.spriteId) == spriteMetaData.spriteID);
+ CharacterPart cp = srIndex == -1 ? new CharacterPart() : parts[srIndex];
+ cp.spriteId = spriteMetaData.spriteID.ToString();
+ cp.order = psdLayers.FindIndex(l => l.spriteID == spriteMetaData.spriteID);
+ cp.spritePosition = new RectInt();
+ var uvTransform = spriteMetaData.uvTransform;
+ 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
+ parts[srIndex] = cp;
+ }
+
+ var layers = dataProvider.GetPSDLayers();
+ parts.Sort((x, y) =>
+ {
+ return x.order.CompareTo(y.order);
+ });
+
+ parts.Reverse();
+ cd.parts = parts.ToArray();
+ cd.dimension = dataProvider.documentSize;
+ cd.characterGroups = groups.ToArray();
+ return cd;
+ }
+
+ public void SetCharacterData(CharacterData characterData)
+ {
+ characterData.parts = characterData.parts.Reverse().ToArray();
+ dataProvider.characterData = characterData;
+ }
+ }
+
+ internal class SpriteLibraryDataProvider : PSDDataProvider, ISpriteLibDataProvider
+ {
+ public SpriteCategoryList GetSpriteCategoryList()
+ {
+ return dataProvider.spriteCategoryList;
+ }
+
+ public void SetSpriteCategoryList(SpriteCategoryList spriteCategoryList)
+ {
+ dataProvider.spriteCategoryList = spriteCategoryList;
+ }
+ }
+}
diff --git a/Editor/PSDImporterDataProvider.cs.meta b/Editor/PSDImporterDataProvider.cs.meta
index 6a6d8bd..2aa6f07 100644
--- a/Editor/PSDImporterDataProvider.cs.meta
+++ b/Editor/PSDImporterDataProvider.cs.meta
@@ -1,11 +1,11 @@
-fileFormatVersion: 2
-guid: d38b7c3f9a7064947a8e162797ea2fa8
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: d38b7c3f9a7064947a8e162797ea2fa8
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDImporterEditor.cs b/Editor/PSDImporterEditor.cs
index 61d9d71..a0d1151 100644
--- a/Editor/PSDImporterEditor.cs
+++ b/Editor/PSDImporterEditor.cs
@@ -1,991 +1,1124 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using PhotoshopFile;
-using UnityEditor.Experimental.AssetImporters;
-using UnityEditor.U2D.Animation;
-using UnityEditor.U2D.Common;
-using UnityEditor.U2D.Sprites;
-using UnityEngine;
-
-namespace UnityEditor.U2D.PSD
-{
- ///
- /// Inspector for PSDImporter
- ///
- [CustomEditor(typeof(PSDImporter))]
- public class PSDImporterEditor : ScriptedImporterEditor
- {
- SerializedProperty m_TextureType;
- SerializedProperty m_TextureShape;
- SerializedProperty m_SpriteMode;
- SerializedProperty m_SpritePixelsToUnits;
- SerializedProperty m_SpriteMeshType;
- SerializedProperty m_SpriteExtrude;
- SerializedProperty m_Alignment;
- SerializedProperty m_SpritePivot;
- SerializedProperty m_NPOTScale;
- SerializedProperty m_IsReadable;
- SerializedProperty m_sRGBTexture;
- SerializedProperty m_AlphaSource;
- SerializedProperty m_MipMapMode;
- SerializedProperty m_EnableMipMap;
- SerializedProperty m_FadeOut;
- SerializedProperty m_BorderMipMap;
- SerializedProperty m_MipMapsPreserveCoverage;
- SerializedProperty m_AlphaTestReferenceValue;
- SerializedProperty m_MipMapFadeDistanceStart;
- SerializedProperty m_MipMapFadeDistanceEnd;
- SerializedProperty m_AlphaIsTransparency;
- SerializedProperty m_FilterMode;
- SerializedProperty m_Aniso;
-
- SerializedProperty m_WrapU;
- SerializedProperty m_WrapV;
- SerializedProperty m_WrapW;
- SerializedProperty m_ConvertToNormalMap;
- SerializedProperty m_MosaicLayers;
- SerializedProperty m_ImportHiddenLayers;
- SerializedProperty m_ResliceFromLayer;
- SerializedProperty m_CharacterMode;
- SerializedProperty m_DocumentPivot;
- SerializedProperty m_DocumentAlignment;
- SerializedProperty m_GenerateGOHierarchy;
- SerializedProperty m_PaperDollMode;
- SerializedProperty m_KeepDupilcateSpriteName;
-
- readonly int[] m_FilterModeOptions = (int[])(Enum.GetValues(typeof(FilterMode)));
-
- bool m_IsPOT = false;
- bool m_ShowAdvanced = false;
- bool m_ShowExperimental = false;
- Dictionary m_AdvanceInspectorGUI = new Dictionary();
- int m_PlatformSettingsIndex;
- bool m_ShowPerAxisWrapModes = false;
-
- TexturePlatformSettingsView m_TexturePlatformSettingsView = new TexturePlatformSettingsView();
- TexturePlatformSettingsController m_TexturePlatformSettingsController = new TexturePlatformSettingsController();
-
- ///
- /// Implementation of AssetImporterEditor.OnEnable
- ///
- public override void OnEnable()
- {
- base.OnEnable();
- m_MosaicLayers = serializedObject.FindProperty("m_MosaicLayers");
- m_ImportHiddenLayers = serializedObject.FindProperty("m_ImportHiddenLayers");
- m_ResliceFromLayer = serializedObject.FindProperty("m_ResliceFromLayer");
- m_CharacterMode = serializedObject.FindProperty("m_CharacterMode");
- m_DocumentPivot = serializedObject.FindProperty("m_DocumentPivot");
- m_DocumentAlignment = serializedObject.FindProperty("m_DocumentAlignment");
- m_GenerateGOHierarchy = serializedObject.FindProperty("m_GenerateGOHierarchy");
- m_PaperDollMode = serializedObject.FindProperty("m_PaperDollMode");
- m_KeepDupilcateSpriteName = serializedObject.FindProperty("m_KeepDupilcateSpriteName");
-
- var textureImporterSettingsSP = serializedObject.FindProperty("m_TextureImporterSettings");
- m_TextureType = textureImporterSettingsSP.FindPropertyRelative("m_TextureType");
- m_TextureShape = textureImporterSettingsSP.FindPropertyRelative("m_TextureShape");
- m_ConvertToNormalMap = textureImporterSettingsSP.FindPropertyRelative("m_ConvertToNormalMap");
- m_SpriteMode = textureImporterSettingsSP.FindPropertyRelative("m_SpriteMode");
- m_SpritePixelsToUnits = textureImporterSettingsSP.FindPropertyRelative("m_SpritePixelsToUnits");
- m_SpriteMeshType = textureImporterSettingsSP.FindPropertyRelative("m_SpriteMeshType");
- m_SpriteExtrude = textureImporterSettingsSP.FindPropertyRelative("m_SpriteExtrude");
- m_Alignment = textureImporterSettingsSP.FindPropertyRelative("m_Alignment");
- m_SpritePivot = textureImporterSettingsSP.FindPropertyRelative("m_SpritePivot");
- m_NPOTScale = textureImporterSettingsSP.FindPropertyRelative("m_NPOTScale");
- m_IsReadable = textureImporterSettingsSP.FindPropertyRelative("m_IsReadable");
- m_sRGBTexture = textureImporterSettingsSP.FindPropertyRelative("m_sRGBTexture");
- m_AlphaSource = textureImporterSettingsSP.FindPropertyRelative("m_AlphaSource");
- m_MipMapMode = textureImporterSettingsSP.FindPropertyRelative("m_MipMapMode");
- m_EnableMipMap = textureImporterSettingsSP.FindPropertyRelative("m_EnableMipMap");
- m_FadeOut = textureImporterSettingsSP.FindPropertyRelative("m_FadeOut");
- m_BorderMipMap = textureImporterSettingsSP.FindPropertyRelative("m_BorderMipMap");
- m_MipMapsPreserveCoverage = textureImporterSettingsSP.FindPropertyRelative("m_MipMapsPreserveCoverage");
- m_AlphaTestReferenceValue = textureImporterSettingsSP.FindPropertyRelative("m_AlphaTestReferenceValue");
- m_MipMapFadeDistanceStart = textureImporterSettingsSP.FindPropertyRelative("m_MipMapFadeDistanceStart");
- m_MipMapFadeDistanceEnd = textureImporterSettingsSP.FindPropertyRelative("m_MipMapFadeDistanceEnd");
- m_AlphaIsTransparency = textureImporterSettingsSP.FindPropertyRelative("m_AlphaIsTransparency");
- m_FilterMode = textureImporterSettingsSP.FindPropertyRelative("m_FilterMode");
- m_Aniso = textureImporterSettingsSP.FindPropertyRelative("m_Aniso");
- m_WrapU = textureImporterSettingsSP.FindPropertyRelative("m_WrapU");
- m_WrapV = textureImporterSettingsSP.FindPropertyRelative("m_WrapV");
- m_WrapW = textureImporterSettingsSP.FindPropertyRelative("m_WrapW");
-
- var textureWidth = serializedObject.FindProperty("m_TextureActualWidth");
- var textureHeight = serializedObject.FindProperty("m_TextureActualHeight");
- m_IsPOT = Mathf.IsPowerOfTwo(textureWidth.intValue) && Mathf.IsPowerOfTwo(textureHeight.intValue);
-
-
- var advanceGUIAction = new Action[]
- {
- ColorSpaceGUI,
- AlphaHandlingGUI,
- POTScaleGUI,
- ReadableGUI,
- MipMapGUI
- };
- m_AdvanceInspectorGUI.Add(TextureImporterType.Sprite, advanceGUIAction);
-
- advanceGUIAction = new Action[]
- {
- POTScaleGUI,
- ReadableGUI,
- MipMapGUI
- };
- m_AdvanceInspectorGUI.Add(TextureImporterType.Default, advanceGUIAction);
-
- LoadPlatformSettings();
- }
-
- ///
- /// Implementation of AssetImporterEditor.OnInspectorGUI
- ///
- public override void OnInspectorGUI()
- {
- serializedObject.Update();
- if (s_Styles == null)
- s_Styles = new Styles();
-
- EditorGUI.showMixedValue = m_TextureType.hasMultipleDifferentValues;
- m_TextureType.intValue = EditorGUILayout.IntPopup(s_Styles.textureTypeTitle, m_TextureType.intValue, s_Styles.textureTypeOptions, s_Styles.textureTypeValues);
- EditorGUI.showMixedValue = false;
-
- switch ((TextureImporterType)m_TextureType.intValue)
- {
- case TextureImporterType.Sprite:
- DoSpriteInspector();
- break;
- case TextureImporterType.Default:
- DoTextureDefaultInspector();
- break;
- default:
- Debug.LogWarning("We only support Default or Sprite texture type for now. Texture type is set to default.");
- m_TextureType.intValue = (int)TextureImporterType.Default;
- break;
- }
-
- DoAdvanceInspector();
- CommonTextureSettingsGUI();
- GUILayout.Space(10);
- DoPlatformSettings();
- serializedObject.ApplyModifiedProperties();
- ApplyRevertGUI();
- }
-
- ///
- /// Implementation of AssetImporterEditor.Apply
- ///
- protected override void Apply()
- {
- FileStream fileStream = new FileStream(((AssetImporter)target).assetPath, FileMode.Open, FileAccess.Read);
- var doc = PaintDotNet.Data.PhotoshopFileType.PsdLoad.Load(fileStream, ELoadFlag.Header | ELoadFlag.ColorMode);
-
- PSDApplyEvent evt = new PSDApplyEvent()
- {
- instance_id = target.GetInstanceID(),
- texture_type = m_TextureType.intValue,
- sprite_mode = m_SpriteMode.intValue,
- mosaic_layer = m_MosaicLayers.boolValue,
- import_hidden_layer = m_ImportHiddenLayers.boolValue,
- character_mode = m_CharacterMode.boolValue,
- generate_go_hierarchy = m_GenerateGOHierarchy.boolValue,
- reslice_from_layer = m_ResliceFromLayer.boolValue,
- is_character_rigged = IsCharacterRigged(),
- is_psd = IsPSD(doc),
- color_mode = FileColorMode(doc)
- };
- doc.Cleanup();
- AnalyticFactory.analytics.SendApplyEvent(evt);
- base.Apply();
- }
-
- static bool IsPSD(PsdFile doc)
- {
- return !doc.IsLargeDocument;
- }
-
- static PsdColorMode FileColorMode(PsdFile doc)
- {
- return doc.ColorMode;
- }
-
- bool IsCharacterRigged()
- {
- var importer = target as PSDImporter;
- if (importer != null)
- {
- var characterProvider = importer.GetDataProvider();
- var meshDataProvider = importer.GetDataProvider();
- if (characterProvider != null && meshDataProvider != null)
- {
- var character = characterProvider.GetCharacterData();
- foreach (var parts in character.parts)
- {
- var vert = meshDataProvider.GetVertices(new GUID(parts.spriteId));
- var indices = meshDataProvider.GetIndices(new GUID(parts.spriteId));
- if (parts.bones != null && parts.bones.Length > 0 &&
- vert != null && vert.Length > 0 &&
- indices != null && indices.Length > 0)
- return true;
- }
- }
- }
- return false;
- }
-
- Dictionary> m_PlatfromSettings = new Dictionary>();
- void LoadPlatformSettings()
- {
- foreach (var t in targets)
- {
- var so = new SerializedObject(t);
- var platformSettingsSP = so.FindProperty("m_PlatformSettings");
- for (int i = 0; i < platformSettingsSP.arraySize; ++i)
- {
- var tip = new TextureImporterPlatformSettings();
- var sp = platformSettingsSP.GetArrayElementAtIndex(i);
- tip.name = sp.FindPropertyRelative("m_Name").stringValue;
- tip.overridden = sp.FindPropertyRelative("m_Overridden").intValue == 1;
- tip.maxTextureSize = sp.FindPropertyRelative("m_MaxTextureSize").intValue;
- tip.resizeAlgorithm = (TextureResizeAlgorithm)sp.FindPropertyRelative("m_ResizeAlgorithm").intValue;
- tip.format = (TextureImporterFormat)sp.FindPropertyRelative("m_TextureFormat").intValue;
- tip.textureCompression = (TextureImporterCompression)sp.FindPropertyRelative("m_TextureCompression").intValue;
- tip.compressionQuality = sp.FindPropertyRelative("m_CompressionQuality").intValue;
- tip.crunchedCompression = sp.FindPropertyRelative("m_CrunchedCompression").intValue == 1;
- tip.allowsAlphaSplitting = sp.FindPropertyRelative("m_AllowsAlphaSplitting").intValue == 1;
-
- List platformSettings = null;
- m_PlatfromSettings.TryGetValue(tip.name, out platformSettings);
- if (platformSettings == null)
- {
- platformSettings = new List();
- m_PlatfromSettings.Add(tip.name, platformSettings);
- }
- platformSettings.Add(tip);
- }
- }
- }
-
- void StorePlatformSettings()
- {
- var platformSettingsSP = serializedObject.FindProperty("m_PlatformSettings");
- platformSettingsSP.ClearArray();
- foreach (var keyValue in m_PlatfromSettings)
- {
- if (!keyValue.Value[0].overridden)
- continue;
-
- SerializedProperty platformSettingSP = null;
- for (int i = 0; i < platformSettingsSP.arraySize; ++i)
- {
- var sp = platformSettingsSP.GetArrayElementAtIndex(i);
- if (sp.FindPropertyRelative("m_Name").stringValue == keyValue.Key)
- platformSettingSP = sp;
- }
- if (platformSettingSP == null)
- {
- platformSettingsSP.InsertArrayElementAtIndex(platformSettingsSP.arraySize);
- platformSettingSP = platformSettingsSP.GetArrayElementAtIndex(platformSettingsSP.arraySize - 1);
- }
-
- var tip = keyValue.Value[0];
- platformSettingSP.FindPropertyRelative("m_Name").stringValue = tip.name;
- platformSettingSP.FindPropertyRelative("m_Overridden").intValue = tip.overridden ? 1 : 0;
- platformSettingSP.FindPropertyRelative("m_MaxTextureSize").intValue = tip.maxTextureSize;
- platformSettingSP.FindPropertyRelative("m_ResizeAlgorithm").intValue = (int)tip.resizeAlgorithm;
- platformSettingSP.FindPropertyRelative("m_TextureFormat").intValue = (int)tip.format;
- platformSettingSP.FindPropertyRelative("m_TextureCompression").intValue = (int)tip.textureCompression;
- platformSettingSP.FindPropertyRelative("m_CompressionQuality").intValue = tip.compressionQuality;
- platformSettingSP.FindPropertyRelative("m_CrunchedCompression").intValue = tip.crunchedCompression ? 1 : 0;
- platformSettingSP.FindPropertyRelative("m_AllowsAlphaSplitting").intValue = tip.allowsAlphaSplitting ? 1 : 0;
- }
- }
-
- void DoPlatformSettings()
- {
- m_PlatformSettingsIndex = EditorGUILayout.Popup(s_Styles.platformSettingsLabel, m_PlatformSettingsIndex, s_Styles.platformSettingsSelection);
-
- List settings = null;
- m_PlatfromSettings.TryGetValue(TexturePlatformSettingsModal.kValidBuildPlatform[m_PlatformSettingsIndex].buildTargetName, out settings);
- if (settings == null)
- {
- settings = new List(targets.Length);
- for (int i = 0; i < targets.Length; ++i)
- {
- var tip = new TextureImporterPlatformSettings();
- tip.name = TexturePlatformSettingsModal.kValidBuildPlatform[m_PlatformSettingsIndex].buildTargetName;
- tip.format = TexturePlatformSettingsModal.kValidBuildPlatform[m_PlatformSettingsIndex].defaultTextureFormat;
- if (TexturePlatformSettingsModal.kValidBuildPlatform[m_PlatformSettingsIndex].buildTarget[0] == BuildTarget.NoTarget)
- {
- tip.overridden = true;
- }
- settings.Add(tip);
- }
- m_PlatfromSettings.Add(TexturePlatformSettingsModal.kValidBuildPlatform[m_PlatformSettingsIndex].buildTargetName, settings);
- }
-
-
- if (m_TexturePlatformSettingsController.HandlePlatformSettings(TexturePlatformSettingsModal.kValidBuildPlatform[m_PlatformSettingsIndex].buildTarget[0], settings, m_TexturePlatformSettingsView))
- {
- StorePlatformSettings();
- }
- }
-
- void DoAdvanceInspector()
- {
- if (!m_TextureType.hasMultipleDifferentValues)
- {
- if (m_AdvanceInspectorGUI.ContainsKey((TextureImporterType)m_TextureType.intValue))
- {
- EditorGUILayout.Space();
-
- m_ShowAdvanced = EditorGUILayout.Foldout(m_ShowAdvanced, s_Styles.showAdvanced, true);
- if (m_ShowAdvanced)
- {
- foreach (var action in m_AdvanceInspectorGUI[(TextureImporterType)m_TextureType.intValue])
- {
- action();
- }
- }
- }
- }
- EditorGUILayout.Space();
- }
-
- void CommonTextureSettingsGUI()
- {
- EditorGUI.BeginChangeCheck();
-
- // Wrap mode
- bool isVolume = false;
- WrapModePopup(m_WrapU, m_WrapV, m_WrapW, isVolume, ref m_ShowPerAxisWrapModes);
-
-
- // Display warning about repeat wrap mode on restricted npot emulation
- if (m_NPOTScale.intValue == (int)TextureImporterNPOTScale.None &&
- (m_WrapU.intValue == (int)TextureWrapMode.Repeat || m_WrapV.intValue == (int)TextureWrapMode.Repeat) &&
- !InternalEditorBridge.DoesHardwareSupportsFullNPOT())
- {
- bool displayWarning = false;
- foreach (var target in targets)
- {
- var imp = (PSDImporter)target;
- int w = imp.textureActualWidth;
- int h = imp.textureActualHeight;
- if (!Mathf.IsPowerOfTwo(w) || !Mathf.IsPowerOfTwo(h))
- {
- displayWarning = true;
- break;
- }
- }
-
- if (displayWarning)
- {
- EditorGUILayout.HelpBox(s_Styles.warpNotSupportWarning.text, MessageType.Warning, true);
- }
- }
-
- // Filter mode
- EditorGUI.showMixedValue = m_FilterMode.hasMultipleDifferentValues;
- FilterMode filter = (FilterMode)m_FilterMode.intValue;
- if ((int)filter == -1)
- {
- if (m_FadeOut.intValue > 0 || m_ConvertToNormalMap.intValue > 0)
- filter = FilterMode.Trilinear;
- else
- filter = FilterMode.Bilinear;
- }
- filter = (FilterMode)EditorGUILayout.IntPopup(s_Styles.filterMode, (int)filter, s_Styles.filterModeOptions, m_FilterModeOptions);
- EditorGUI.showMixedValue = false;
- if (EditorGUI.EndChangeCheck())
- m_FilterMode.intValue = (int)filter;
-
- // Aniso
- bool showAniso = (FilterMode)m_FilterMode.intValue != FilterMode.Point
- && m_EnableMipMap.intValue > 0
- && (TextureImporterShape)m_TextureShape.intValue != TextureImporterShape.TextureCube;
- using (new EditorGUI.DisabledScope(!showAniso))
- {
- EditorGUI.BeginChangeCheck();
- EditorGUI.showMixedValue = m_Aniso.hasMultipleDifferentValues;
- int aniso = m_Aniso.intValue;
- if (aniso == -1)
- aniso = 1;
- aniso = EditorGUILayout.IntSlider(s_Styles.anisoLevelLabel, aniso, 0, 16);
- EditorGUI.showMixedValue = false;
- if (EditorGUI.EndChangeCheck())
- m_Aniso.intValue = aniso;
-
- if (aniso > 1)
- {
- if (QualitySettings.anisotropicFiltering == AnisotropicFiltering.Disable)
- EditorGUILayout.HelpBox(s_Styles.anisotropicDisableInfo.text, MessageType.Info);
- else if (QualitySettings.anisotropicFiltering == AnisotropicFiltering.ForceEnable)
- EditorGUILayout.HelpBox(s_Styles.anisotropicForceEnableInfo.text, MessageType.Info);
- }
- }
- }
-
- private static bool IsAnyTextureObjectUsingPerAxisWrapMode(UnityEngine.Object[] objects, bool isVolumeTexture)
- {
- foreach (var o in objects)
- {
- int u = 0, v = 0, w = 0;
- // the objects can be Textures themselves, or texture-related importers
- if (o is Texture)
- {
- var ti = (Texture)o;
- u = (int)ti.wrapModeU;
- v = (int)ti.wrapModeV;
- w = (int)ti.wrapModeW;
- }
- if (o is TextureImporter)
- {
- var ti = (TextureImporter)o;
- u = (int)ti.wrapModeU;
- v = (int)ti.wrapModeV;
- w = (int)ti.wrapModeW;
- }
- if (o is IHVImageFormatImporter)
- {
- var ti = (IHVImageFormatImporter)o;
- u = (int)ti.wrapModeU;
- v = (int)ti.wrapModeV;
- w = (int)ti.wrapModeW;
- }
- u = Mathf.Max(0, u);
- v = Mathf.Max(0, v);
- w = Mathf.Max(0, w);
- if (u != v)
- {
- return true;
- }
- if (isVolumeTexture)
- {
- if (u != w || v != w)
- {
- return true;
- }
- }
- }
- return false;
- }
-
- // showPerAxisWrapModes is state of whether "Per-Axis" mode should be active in the main dropdown.
- // It is set automatically if wrap modes in UVW are different, or if user explicitly picks "Per-Axis" option -- when that one is picked,
- // then it should stay true even if UVW wrap modes will initially be the same.
- //
- // Note: W wrapping mode is only shown when isVolumeTexture is true.
- internal static void WrapModePopup(SerializedProperty wrapU, SerializedProperty wrapV, SerializedProperty wrapW, bool isVolumeTexture, ref bool showPerAxisWrapModes)
- {
- if (s_Styles == null)
- s_Styles = new Styles();
-
- // In texture importer settings, serialized properties for things like wrap modes can contain -1;
- // that seems to indicate "use defaults, user has not changed them to anything" but not totally sure.
- // Show them as Repeat wrap modes in the popups.
- var wu = (TextureWrapMode)Mathf.Max(wrapU.intValue, 0);
- var wv = (TextureWrapMode)Mathf.Max(wrapV.intValue, 0);
- var ww = (TextureWrapMode)Mathf.Max(wrapW.intValue, 0);
-
- // automatically go into per-axis mode if values are already different
- if (wu != wv)
- showPerAxisWrapModes = true;
- if (isVolumeTexture)
- {
- if (wu != ww || wv != ww)
- showPerAxisWrapModes = true;
- }
-
- // It's not possible to determine whether any single texture in the whole selection is using per-axis wrap modes
- // just from SerializedProperty values. They can only tell if "some values in whole selection are different" (e.g.
- // wrap value on U axis is not the same among all textures), and can return value of "some" object in the selection
- // (typically based on object loading order). So in order for more intuitive behavior with multi-selection,
- // we go over the actual objects when there's >1 object selected and some wrap modes are different.
- if (!showPerAxisWrapModes)
- {
- if (wrapU.hasMultipleDifferentValues || wrapV.hasMultipleDifferentValues || (isVolumeTexture && wrapW.hasMultipleDifferentValues))
- {
- if (IsAnyTextureObjectUsingPerAxisWrapMode(wrapU.serializedObject.targetObjects, isVolumeTexture))
- {
- showPerAxisWrapModes = true;
- }
- }
- }
-
- int value = showPerAxisWrapModes ? -1 : (int)wu;
-
- // main wrap mode popup
- EditorGUI.BeginChangeCheck();
- EditorGUI.showMixedValue = !showPerAxisWrapModes && (wrapU.hasMultipleDifferentValues || wrapV.hasMultipleDifferentValues || (isVolumeTexture && wrapW.hasMultipleDifferentValues));
- value = EditorGUILayout.IntPopup(s_Styles.wrapModeLabel, value, s_Styles.wrapModeContents, s_Styles.wrapModeValues);
- if (EditorGUI.EndChangeCheck() && value != -1)
- {
- // assign the same wrap mode to all axes, and hide per-axis popups
- wrapU.intValue = value;
- wrapV.intValue = value;
- wrapW.intValue = value;
- showPerAxisWrapModes = false;
- }
-
- // show per-axis popups if needed
- if (value == -1)
- {
- showPerAxisWrapModes = true;
- EditorGUI.indentLevel++;
- WrapModeAxisPopup(s_Styles.wrapU, wrapU);
- WrapModeAxisPopup(s_Styles.wrapV, wrapV);
- if (isVolumeTexture)
- {
- WrapModeAxisPopup(s_Styles.wrapW, wrapW);
- }
- EditorGUI.indentLevel--;
- }
- EditorGUI.showMixedValue = false;
- }
-
- static void WrapModeAxisPopup(GUIContent label, SerializedProperty wrapProperty)
- {
- // In texture importer settings, serialized properties for wrap modes can contain -1, which means "use default".
- var wrap = (TextureWrapMode)Mathf.Max(wrapProperty.intValue, 0);
- Rect rect = EditorGUILayout.GetControlRect();
- EditorGUI.BeginChangeCheck();
- EditorGUI.BeginProperty(rect, label, wrapProperty);
- wrap = (TextureWrapMode)EditorGUI.EnumPopup(rect, label, wrap);
- EditorGUI.EndProperty();
- if (EditorGUI.EndChangeCheck())
- {
- wrapProperty.intValue = (int)wrap;
- }
- }
-
- void DoWrapModePopup()
- {
- WrapModePopup(m_WrapU, m_WrapV, m_WrapW, IsVolume(), ref m_ShowPerAxisWrapModes);
- }
-
- bool IsVolume()
- {
- var t = target as Texture;
- return t != null && t.dimension == UnityEngine.Rendering.TextureDimension.Tex3D;
- }
-
- void DoSpriteInspector()
- {
- EditorGUI.BeginChangeCheck();
- EditorGUILayout.IntPopup(m_SpriteMode, s_Styles.spriteModeOptions, new[] { 1, 2, 3 }, s_Styles.spriteMode);
-
- // Ensure that PropertyField focus will be cleared when we change spriteMode.
- if (EditorGUI.EndChangeCheck())
- {
- GUIUtility.keyboardControl = 0;
- }
-
- EditorGUI.indentLevel++;
-
- // Show generic attributes
- if (m_SpriteMode.intValue != 0)
- {
- EditorGUILayout.PropertyField(m_SpritePixelsToUnits, s_Styles.spritePixelsPerUnit);
-
- if (m_SpriteMode.intValue != (int)SpriteImportMode.Polygon && !m_SpriteMode.hasMultipleDifferentValues)
- {
- EditorGUILayout.IntPopup(m_SpriteMeshType, s_Styles.spriteMeshTypeOptions, new[] { 0, 1 }, s_Styles.spriteMeshType);
- }
-
- EditorGUILayout.IntSlider(m_SpriteExtrude, 0, 32, s_Styles.spriteExtrude);
-
- if (m_SpriteMode.intValue == 1)
- {
- EditorGUILayout.IntPopup(m_Alignment, s_Styles.spriteAlignmentOptions, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s_Styles.spriteAlignment);
-
- if (m_Alignment.intValue == (int)SpriteAlignment.Custom)
- {
- GUILayout.BeginHorizontal();
- EditorGUILayout.PropertyField(m_SpritePivot, new GUIContent());
- GUILayout.EndHorizontal();
- }
- }
- }
-
- EditorGUILayout.PropertyField(m_ImportHiddenLayers, s_Styles.importHiddenLayer);
- if (m_SpriteMode.intValue == (int)SpriteImportMode.Multiple && !m_SpriteMode.hasMultipleDifferentValues)
- {
- EditorGUILayout.PropertyField(m_MosaicLayers, s_Styles.mosaicLayers);
- using (new EditorGUI.DisabledScope(!m_MosaicLayers.boolValue))
- {
- EditorGUILayout.PropertyField(m_CharacterMode, s_Styles.characterMode);
- using (new EditorGUI.DisabledScope(!m_CharacterMode.boolValue))
- {
- EditorGUILayout.PropertyField(m_GenerateGOHierarchy, s_Styles.generateGOHierarchy);
- EditorGUILayout.IntPopup(m_DocumentAlignment, s_Styles.spriteAlignmentOptions, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s_Styles.characterAlignment);
- if (m_DocumentAlignment.intValue == (int)SpriteAlignment.Custom)
- {
- GUILayout.BeginHorizontal();
- GUILayout.Space(EditorGUIUtility.labelWidth);
- EditorGUILayout.PropertyField(m_DocumentPivot, new GUIContent());
- GUILayout.EndHorizontal();
- }
- //EditorGUILayout.PropertyField(m_PaperDollMode, s_Styles.paperDollMode);
- }
-
-
- EditorGUILayout.PropertyField(m_ResliceFromLayer, s_Styles.resliceFromLayer);
- if (m_ResliceFromLayer.boolValue)
- {
- EditorGUILayout.HelpBox(s_Styles.resliceFromLayerWarning.text, MessageType.Info, true);
- }
- }
- m_ShowExperimental = EditorGUILayout.Foldout(m_ShowExperimental, s_Styles.experimental, true);
- if (m_ShowExperimental)
- {
- EditorGUI.indentLevel++;
- EditorGUILayout.PropertyField(m_KeepDupilcateSpriteName, s_Styles.keepDuplicateSpriteName);
- EditorGUI.indentLevel--;
- }
- }
-
- using (new EditorGUI.DisabledScope(targets.Length != 1))
- {
- GUILayout.BeginHorizontal();
-
- GUILayout.FlexibleSpace();
- if (GUILayout.Button(s_Styles.spriteEditorButtonLabel))
- {
- if (HasModified())
- {
- // To ensure Sprite Editor Window to have the latest texture import setting,
- // We must applied those modified values first.
- string dialogText = string.Format(s_Styles.unappliedSettingsDialogContent.text, ((AssetImporter)target).assetPath);
- if (EditorUtility.DisplayDialog(s_Styles.unappliedSettingsDialogTitle.text,
- dialogText, s_Styles.applyButtonLabel.text, s_Styles.revertButtonLabel.text))
- {
- ApplyAndImport();
- InternalEditorBridge.ShowSpriteEditorWindow();
-
- // We reimported the asset which destroyed the editor, so we can't keep running the UI here.
- GUIUtility.ExitGUI();
- }
- }
- else
- {
- InternalEditorBridge.ShowSpriteEditorWindow();
- }
- }
- GUILayout.EndHorizontal();
- }
- EditorGUI.indentLevel--;
- }
-
- void DoTextureDefaultInspector()
- {
- ColorSpaceGUI();
- AlphaHandlingGUI();
- }
-
- void ColorSpaceGUI()
- {
- ToggleFromInt(m_sRGBTexture, s_Styles.sRGBTexture);
- }
-
- void POTScaleGUI()
- {
- using (new EditorGUI.DisabledScope(m_IsPOT || m_TextureType.intValue == (int)TextureImporterType.Sprite))
- {
- EnumPopup(m_NPOTScale, typeof(TextureImporterNPOTScale), s_Styles.npot);
- }
- }
-
- void ReadableGUI()
- {
- ToggleFromInt(m_IsReadable, s_Styles.readWrite);
- }
-
- void AlphaHandlingGUI()
- {
- EditorGUI.showMixedValue = m_AlphaSource.hasMultipleDifferentValues;
- EditorGUI.BeginChangeCheck();
- int newAlphaUsage = EditorGUILayout.IntPopup(s_Styles.alphaSource, m_AlphaSource.intValue, s_Styles.alphaSourceOptions, s_Styles.alphaSourceValues);
-
- EditorGUI.showMixedValue = false;
- if (EditorGUI.EndChangeCheck())
- {
- m_AlphaSource.intValue = newAlphaUsage;
- }
-
- bool showAlphaIsTransparency = (TextureImporterAlphaSource)m_AlphaSource.intValue != TextureImporterAlphaSource.None;
- using (new EditorGUI.DisabledScope(!showAlphaIsTransparency))
- {
- ToggleFromInt(m_AlphaIsTransparency, s_Styles.alphaIsTransparency);
- }
- }
-
- void MipMapGUI()
- {
- ToggleFromInt(m_EnableMipMap, s_Styles.generateMipMaps);
-
- if (m_EnableMipMap.boolValue && !m_EnableMipMap.hasMultipleDifferentValues)
- {
- EditorGUI.indentLevel++;
- ToggleFromInt(m_BorderMipMap, s_Styles.borderMipMaps);
- EditorGUILayout.Popup(s_Styles.mipMapFilter, m_MipMapMode.intValue, s_Styles.mipMapFilterOptions);
-
- ToggleFromInt(m_MipMapsPreserveCoverage, s_Styles.mipMapsPreserveCoverage);
- if (m_MipMapsPreserveCoverage.intValue != 0 && !m_MipMapsPreserveCoverage.hasMultipleDifferentValues)
- {
- EditorGUI.indentLevel++;
- EditorGUILayout.PropertyField(m_AlphaTestReferenceValue, s_Styles.alphaTestReferenceValue);
- EditorGUI.indentLevel--;
- }
-
- // Mipmap fadeout
- ToggleFromInt(m_FadeOut, s_Styles.mipmapFadeOutToggle);
- if (m_FadeOut.intValue > 0)
- {
- EditorGUI.indentLevel++;
- EditorGUI.BeginChangeCheck();
- float min = m_MipMapFadeDistanceStart.intValue;
- float max = m_MipMapFadeDistanceEnd.intValue;
- EditorGUILayout.MinMaxSlider(s_Styles.mipmapFadeOut, ref min, ref max, 0, 10);
- if (EditorGUI.EndChangeCheck())
- {
- m_MipMapFadeDistanceStart.intValue = Mathf.RoundToInt(min);
- m_MipMapFadeDistanceEnd.intValue = Mathf.RoundToInt(max);
- }
- EditorGUI.indentLevel--;
- }
- EditorGUI.indentLevel--;
- }
- }
-
- void ToggleFromInt(SerializedProperty property, GUIContent label)
- {
- EditorGUI.BeginChangeCheck();
- EditorGUI.showMixedValue = property.hasMultipleDifferentValues;
- int value = EditorGUILayout.Toggle(label, property.intValue > 0) ? 1 : 0;
- EditorGUI.showMixedValue = false;
- if (EditorGUI.EndChangeCheck())
- property.intValue = value;
- }
-
- void EnumPopup(SerializedProperty property, System.Type type, GUIContent label)
- {
- EditorGUILayout.IntPopup(label.text, property.intValue,
- System.Enum.GetNames(type),
- System.Enum.GetValues(type) as int[]);
- }
-
- void ExportMosaicTexture()
- {
- var assetPath = ((AssetImporter)target).assetPath;
- var texture2D = AssetDatabase.LoadAssetAtPath(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();
- }
-
- ///
- /// Override of AssetImporterEditor.showImportedObject
- /// The property always returns false so that imported objects does not show up in the Inspector.
- ///
- /// false
- public override bool showImportedObject { get => false; }
-
- internal class Styles
- {
- public readonly GUIContent textureTypeTitle = new GUIContent("Texture Type", "What will this texture be used for?");
- public readonly GUIContent[] textureTypeOptions =
- {
- new GUIContent("Default", "Texture is a normal image such as a diffuse texture or other."),
- new GUIContent("Sprite (2D and UI)", "Texture is used for a sprite."),
- };
- public readonly int[] textureTypeValues =
- {
- (int)TextureImporterType.Default,
- (int)TextureImporterType.Sprite,
- };
-
- public readonly GUIContent textureShape = new GUIContent("Texture Shape", "What shape is this texture?");
- private readonly GUIContent textureShape2D = new GUIContent("2D, Texture is 2D.");
- private readonly GUIContent textureShapeCube = new GUIContent("Cube", "Texture is a Cubemap.");
- public readonly Dictionary textureShapeOptionsDictionnary = new Dictionary();
- public readonly Dictionary textureShapeValuesDictionnary = new Dictionary();
-
-
- public readonly GUIContent filterMode = new GUIContent("Filter Mode");
- public readonly GUIContent[] filterModeOptions =
- {
- new GUIContent("Point (no filter)"),
- new GUIContent("Bilinear"),
- new GUIContent("Trilinear")
- };
-
- public readonly GUIContent textureFormat = new GUIContent("Format");
-
- public readonly GUIContent defaultPlatform = new GUIContent("Default");
- public readonly GUIContent mipmapFadeOutToggle = new GUIContent("Fadeout Mip Maps");
- public readonly GUIContent mipmapFadeOut = new GUIContent("Fade Range");
- public readonly GUIContent readWrite = new GUIContent("Read/Write Enabled", "Enable to be able to access the raw pixel data from code.");
-
- public readonly GUIContent alphaSource = new GUIContent("Alpha Source", "How is the alpha generated for the imported texture.");
- public readonly GUIContent[] alphaSourceOptions =
- {
- new GUIContent("None", "No Alpha will be used."),
- new GUIContent("Input Texture Alpha", "Use Alpha from the input texture if one is provided."),
- new GUIContent("From Gray Scale", "Generate Alpha from image gray scale."),
- };
- public readonly int[] alphaSourceValues =
- {
- (int)TextureImporterAlphaSource.None,
- (int)TextureImporterAlphaSource.FromInput,
- (int)TextureImporterAlphaSource.FromGrayScale,
- };
-
- public readonly GUIContent generateMipMaps = new GUIContent("Generate Mip Maps");
- public readonly GUIContent sRGBTexture = new GUIContent("sRGB (Color Texture)", "Texture content is stored in gamma space. Non-HDR color textures should enable this flag (except if used for IMGUI).");
- public readonly GUIContent borderMipMaps = new GUIContent("Border Mip Maps");
- public readonly GUIContent mipMapsPreserveCoverage = new GUIContent("Mip Maps Preserve Coverage", "The alpha channel of generated Mip Maps will preserve coverage during the alpha test.");
- public readonly GUIContent alphaTestReferenceValue = new GUIContent("Alpha Cutoff Value", "The reference value used during the alpha test. Controls Mip Map coverage.");
- public readonly GUIContent mipMapFilter = new GUIContent("Mip Map Filtering");
- public readonly GUIContent[] mipMapFilterOptions =
- {
- new GUIContent("Box"),
- new GUIContent("Kaiser"),
- };
- public readonly GUIContent npot = new GUIContent("Non Power of 2", "How non-power-of-two textures are scaled on import.");
-
- public readonly GUIContent compressionQuality = new GUIContent("Compressor Quality");
- public readonly GUIContent compressionQualitySlider = new GUIContent("Compressor Quality", "Use the slider to adjust compression quality from 0 (Fastest) to 100 (Best)");
- public readonly GUIContent[] mobileCompressionQualityOptions =
- {
- new GUIContent("Fast"),
- new GUIContent("Normal"),
- new GUIContent("Best")
- };
-
- public readonly GUIContent spriteMode = new GUIContent("Sprite Mode");
- public readonly GUIContent[] spriteModeOptions =
- {
- new GUIContent("Single"),
- new GUIContent("Multiple"),
- new GUIContent("Polygon"),
- };
- public readonly GUIContent[] spriteMeshTypeOptions =
- {
- new GUIContent("Full Rect"),
- new GUIContent("Tight"),
- };
-
- public readonly GUIContent spritePackingTag = new GUIContent("Packing Tag", "Tag for the Sprite Packing system.");
- public readonly GUIContent spritePixelsPerUnit = new GUIContent("Pixels Per Unit", "How many pixels in the sprite correspond to one unit in the world.");
- public readonly GUIContent spriteExtrude = new GUIContent("Extrude Edges", "How much empty area to leave around the sprite in the generated mesh.");
- public readonly GUIContent spriteMeshType = new GUIContent("Mesh Type", "Type of sprite mesh to generate.");
- public readonly GUIContent spriteAlignment = new GUIContent("Pivot", "Sprite pivot point in its local space. May be used for syncing animation frames of different sizes.");
- public readonly GUIContent characterAlignment = new GUIContent("Pivot", "Character pivot point in its local space using normalized value i.e. 0 - 1");
-
- public readonly GUIContent[] spriteAlignmentOptions =
- {
- new GUIContent("Center"),
- new GUIContent("Top Left"),
- new GUIContent("Top"),
- new GUIContent("Top Right"),
- new GUIContent("Left"),
- new GUIContent("Right"),
- new GUIContent("Bottom Left"),
- new GUIContent("Bottom"),
- new GUIContent("Bottom Right"),
- new GUIContent("Custom"),
- };
-
- public readonly GUIContent warpNotSupportWarning = new GUIContent("Graphics device doesn't support Repeat wrap mode on NPOT textures. Falling back to Clamp.");
- public readonly GUIContent anisoLevelLabel = new GUIContent("Aniso Level");
- public readonly GUIContent anisotropicDisableInfo = new GUIContent("Anisotropic filtering is disabled for all textures in Quality Settings.");
- public readonly GUIContent anisotropicForceEnableInfo = new GUIContent("Anisotropic filtering is enabled for all textures in Quality Settings.");
- public readonly GUIContent unappliedSettingsDialogTitle = new GUIContent("Unapplied import settings");
- public readonly GUIContent unappliedSettingsDialogContent = new GUIContent("Unapplied import settings for \'{0}\'.\nApply and continue to sprite editor or cancel.");
- public readonly GUIContent applyButtonLabel = new GUIContent("Apply");
- public readonly GUIContent revertButtonLabel = new GUIContent("Revert");
- public readonly GUIContent spriteEditorButtonLabel = new GUIContent("Sprite Editor");
- public readonly GUIContent resliceFromLayerWarning = new GUIContent("This will reinitialize and recreate all Sprites based on the file’s layer data. Existing Sprite metadata from previously generated Sprites are copied over.");
- public readonly GUIContent alphaIsTransparency = new GUIContent("Alpha Is Transparency", "If the provided alpha channel is transparency, enable this to pre-filter the color to avoid texture filtering artifacts. This is not supported for HDR textures.");
- public readonly GUIContent etc1Compression = new GUIContent("Compress using ETC1 (split alpha channel)|Alpha for this texture will be preserved by splitting the alpha channel to another texture, and both resulting textures will be compressed using ETC1.");
- public readonly GUIContent crunchedCompression = new GUIContent("Use Crunch Compression", "Texture is crunch-compressed to save space on disk when applicable.");
-
- public readonly GUIContent showAdvanced = new GUIContent("Advanced", "Show advanced settings.");
-
- public readonly GUIContent platformSettingsLabel = new GUIContent("Platform Setttings");
-
- public readonly GUIContent[] platformSettingsSelection;
-
- public readonly GUIContent wrapModeLabel = new GUIContent("Wrap Mode");
- public readonly GUIContent wrapU = new GUIContent("U axis");
- public readonly GUIContent wrapV = new GUIContent("V axis");
- public readonly GUIContent wrapW = new GUIContent("W axis");
-
-
- public readonly GUIContent[] wrapModeContents =
- {
- new GUIContent("Repeat"),
- new GUIContent("Clamp"),
- new GUIContent("Mirror"),
- new GUIContent("Mirror Once"),
- new GUIContent("Per-axis")
- };
- public readonly int[] wrapModeValues =
- {
- (int)TextureWrapMode.Repeat,
- (int)TextureWrapMode.Clamp,
- (int)TextureWrapMode.Mirror,
- (int)TextureWrapMode.MirrorOnce,
- -1
- };
-
- public readonly GUIContent importHiddenLayer = new GUIContent(L10n.Tr("Import Hidden"), L10n.Tr("Import hidden layers"));
- public readonly GUIContent mosaicLayers = new GUIContent(L10n.Tr("Mosaic"), L10n.Tr("Layers will be imported as individual Sprites"));
- public readonly GUIContent characterMode = new GUIContent(L10n.Tr("Character Rig"), L10n.Tr("Enable to support 2D Animation character rigging"));
- public readonly GUIContent generateGOHierarchy = new GUIContent(L10n.Tr("Use Layer Grouping"), L10n.Tr("GameObjects are grouped according to source file layer grouping"));
- public readonly GUIContent resliceFromLayer = new GUIContent(L10n.Tr("Reslice"), L10n.Tr("Recreate Sprite rects from file"));
- public readonly GUIContent paperDollMode = new GUIContent(L10n.Tr("Paper Doll Mode"), L10n.Tr("Special mode to generate a Prefab for Paper Doll use case"));
- public readonly GUIContent experimental = new GUIContent(L10n.Tr("Experimental"));
- public readonly GUIContent keepDuplicateSpriteName = new GUIContent(L10n.Tr("Keep Duplicate Name"), L10n.Tr("Keep Sprite name same as Layer Name even if there are duplicated Layer Name"));
-
- public Styles()
- {
- // This is far from ideal, but it's better than having tons of logic in the GUI code itself.
- // The combination should not grow too much anyway since only Texture3D will be added later.
- GUIContent[] s2D_Options = { textureShape2D };
- GUIContent[] sCube_Options = { textureShapeCube };
- GUIContent[] s2D_Cube_Options = { textureShape2D, textureShapeCube };
- textureShapeOptionsDictionnary.Add(TextureImporterShape.Texture2D, s2D_Options);
- textureShapeOptionsDictionnary.Add(TextureImporterShape.TextureCube, sCube_Options);
- textureShapeOptionsDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube, s2D_Cube_Options);
-
- int[] s2D_Values = { (int)TextureImporterShape.Texture2D };
- int[] sCube_Values = { (int)TextureImporterShape.TextureCube };
- int[] s2D_Cube_Values = { (int)TextureImporterShape.Texture2D, (int)TextureImporterShape.TextureCube };
- textureShapeValuesDictionnary.Add(TextureImporterShape.Texture2D, s2D_Values);
- textureShapeValuesDictionnary.Add(TextureImporterShape.TextureCube, sCube_Values);
- textureShapeValuesDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube, s2D_Cube_Values);
-
- platformSettingsSelection = new GUIContent[TexturePlatformSettingsModal.kValidBuildPlatform.Length];
- for (int i = 0; i < TexturePlatformSettingsModal.kValidBuildPlatform.Length; ++i)
- {
- platformSettingsSelection[i] = new GUIContent(TexturePlatformSettingsModal.kValidBuildPlatform[i].buildTargetName);
- }
- }
- }
-
- internal static Styles s_Styles;
- }
-}
+using System;
+using System.Collections.Generic;
+using System.IO;
+using PhotoshopFile;
+using UnityEditor.Experimental.AssetImporters;
+using UnityEditor.U2D.Animation;
+using UnityEditor.U2D.Common;
+using UnityEditor.U2D.Sprites;
+using UnityEngine;
+
+namespace UnityEditor.U2D.PSD
+{
+ ///
+ /// Inspector for PSDImporter
+ ///
+ [CustomEditor(typeof(PSDImporter))]
+ public class PSDImporterEditor : ScriptedImporterEditor, ITexturePlatformSettingsDataProvider
+ {
+ SerializedProperty m_TextureType;
+ SerializedProperty m_TextureShape;
+ SerializedProperty m_SpriteMode;
+ SerializedProperty m_SpritePixelsToUnits;
+ SerializedProperty m_SpriteMeshType;
+ SerializedProperty m_SpriteExtrude;
+ SerializedProperty m_Alignment;
+ SerializedProperty m_SpritePivot;
+ SerializedProperty m_NPOTScale;
+ SerializedProperty m_IsReadable;
+ SerializedProperty m_sRGBTexture;
+ SerializedProperty m_AlphaSource;
+ SerializedProperty m_MipMapMode;
+ SerializedProperty m_EnableMipMap;
+ SerializedProperty m_FadeOut;
+ SerializedProperty m_BorderMipMap;
+ SerializedProperty m_MipMapsPreserveCoverage;
+ SerializedProperty m_AlphaTestReferenceValue;
+ SerializedProperty m_MipMapFadeDistanceStart;
+ SerializedProperty m_MipMapFadeDistanceEnd;
+ SerializedProperty m_AlphaIsTransparency;
+ SerializedProperty m_FilterMode;
+ SerializedProperty m_Aniso;
+
+ SerializedProperty m_WrapU;
+ SerializedProperty m_WrapV;
+ SerializedProperty m_WrapW;
+ SerializedProperty m_ConvertToNormalMap;
+ SerializedProperty m_MosaicLayers;
+ SerializedProperty m_ImportHiddenLayers;
+ SerializedProperty m_ResliceFromLayer;
+ SerializedProperty m_CharacterMode;
+ SerializedProperty m_DocumentPivot;
+ SerializedProperty m_DocumentAlignment;
+ SerializedProperty m_GenerateGOHierarchy;
+ SerializedProperty m_PaperDollMode;
+ SerializedProperty m_KeepDupilcateSpriteName;
+
+ readonly int[] m_FilterModeOptions = (int[])(Enum.GetValues(typeof(FilterMode)));
+
+ bool m_IsPOT = false;
+ bool m_ShowAdvanced = false;
+ bool m_ShowExperimental = false;
+ Dictionary m_AdvanceInspectorGUI = new Dictionary();
+ int m_PlatformSettingsIndex;
+ bool m_ShowPerAxisWrapModes = false;
+
+ TexturePlatformSettingsHelper m_TexturePlatformSettingsHelper;
+
+ TexturePlatformSettingsView m_TexturePlatformSettingsView = new TexturePlatformSettingsView();
+ TexturePlatformSettingsController m_TexturePlatformSettingsController = new TexturePlatformSettingsController();
+
+ ///
+ /// Implementation of AssetImporterEditor.OnEnable
+ ///
+ public override void OnEnable()
+ {
+ base.OnEnable();
+ m_MosaicLayers = serializedObject.FindProperty("m_MosaicLayers");
+ m_ImportHiddenLayers = serializedObject.FindProperty("m_ImportHiddenLayers");
+ m_ResliceFromLayer = serializedObject.FindProperty("m_ResliceFromLayer");
+ m_CharacterMode = serializedObject.FindProperty("m_CharacterMode");
+ m_DocumentPivot = serializedObject.FindProperty("m_DocumentPivot");
+ m_DocumentAlignment = serializedObject.FindProperty("m_DocumentAlignment");
+ m_GenerateGOHierarchy = serializedObject.FindProperty("m_GenerateGOHierarchy");
+ m_PaperDollMode = serializedObject.FindProperty("m_PaperDollMode");
+ m_KeepDupilcateSpriteName = serializedObject.FindProperty("m_KeepDupilcateSpriteName");
+
+ var textureImporterSettingsSP = serializedObject.FindProperty("m_TextureImporterSettings");
+ m_TextureType = textureImporterSettingsSP.FindPropertyRelative("m_TextureType");
+ m_TextureShape = textureImporterSettingsSP.FindPropertyRelative("m_TextureShape");
+ m_ConvertToNormalMap = textureImporterSettingsSP.FindPropertyRelative("m_ConvertToNormalMap");
+ m_SpriteMode = textureImporterSettingsSP.FindPropertyRelative("m_SpriteMode");
+ m_SpritePixelsToUnits = textureImporterSettingsSP.FindPropertyRelative("m_SpritePixelsToUnits");
+ m_SpriteMeshType = textureImporterSettingsSP.FindPropertyRelative("m_SpriteMeshType");
+ m_SpriteExtrude = textureImporterSettingsSP.FindPropertyRelative("m_SpriteExtrude");
+ m_Alignment = textureImporterSettingsSP.FindPropertyRelative("m_Alignment");
+ m_SpritePivot = textureImporterSettingsSP.FindPropertyRelative("m_SpritePivot");
+ m_NPOTScale = textureImporterSettingsSP.FindPropertyRelative("m_NPOTScale");
+ m_IsReadable = textureImporterSettingsSP.FindPropertyRelative("m_IsReadable");
+ m_sRGBTexture = textureImporterSettingsSP.FindPropertyRelative("m_sRGBTexture");
+ m_AlphaSource = textureImporterSettingsSP.FindPropertyRelative("m_AlphaSource");
+ m_MipMapMode = textureImporterSettingsSP.FindPropertyRelative("m_MipMapMode");
+ m_EnableMipMap = textureImporterSettingsSP.FindPropertyRelative("m_EnableMipMap");
+ m_FadeOut = textureImporterSettingsSP.FindPropertyRelative("m_FadeOut");
+ m_BorderMipMap = textureImporterSettingsSP.FindPropertyRelative("m_BorderMipMap");
+ m_MipMapsPreserveCoverage = textureImporterSettingsSP.FindPropertyRelative("m_MipMapsPreserveCoverage");
+ m_AlphaTestReferenceValue = textureImporterSettingsSP.FindPropertyRelative("m_AlphaTestReferenceValue");
+ m_MipMapFadeDistanceStart = textureImporterSettingsSP.FindPropertyRelative("m_MipMapFadeDistanceStart");
+ m_MipMapFadeDistanceEnd = textureImporterSettingsSP.FindPropertyRelative("m_MipMapFadeDistanceEnd");
+ m_AlphaIsTransparency = textureImporterSettingsSP.FindPropertyRelative("m_AlphaIsTransparency");
+ m_FilterMode = textureImporterSettingsSP.FindPropertyRelative("m_FilterMode");
+ m_Aniso = textureImporterSettingsSP.FindPropertyRelative("m_Aniso");
+ m_WrapU = textureImporterSettingsSP.FindPropertyRelative("m_WrapU");
+ m_WrapV = textureImporterSettingsSP.FindPropertyRelative("m_WrapV");
+ m_WrapW = textureImporterSettingsSP.FindPropertyRelative("m_WrapW");
+
+ var textureWidth = serializedObject.FindProperty("m_TextureActualWidth");
+ var textureHeight = serializedObject.FindProperty("m_TextureActualHeight");
+ m_IsPOT = Mathf.IsPowerOfTwo(textureWidth.intValue) && Mathf.IsPowerOfTwo(textureHeight.intValue);
+
+
+ var advanceGUIAction = new Action[]
+ {
+ ColorSpaceGUI,
+ AlphaHandlingGUI,
+ POTScaleGUI,
+ ReadableGUI,
+ MipMapGUI
+ };
+ m_AdvanceInspectorGUI.Add(TextureImporterType.Sprite, advanceGUIAction);
+
+ advanceGUIAction = new Action[]
+ {
+ POTScaleGUI,
+ ReadableGUI,
+ MipMapGUI
+ };
+ m_AdvanceInspectorGUI.Add(TextureImporterType.Default, advanceGUIAction);
+ LoadPlatformSettings();
+ m_TexturePlatformSettingsHelper = new TexturePlatformSettingsHelper(this);
+ }
+
+ ///
+ /// Implementation of AssetImporterEditor.OnInspectorGUI
+ ///
+ public override void OnInspectorGUI()
+ {
+ serializedObject.Update();
+ if (s_Styles == null)
+ s_Styles = new Styles();
+
+ EditorGUI.showMixedValue = m_TextureType.hasMultipleDifferentValues;
+ m_TextureType.intValue = EditorGUILayout.IntPopup(s_Styles.textureTypeTitle, m_TextureType.intValue, s_Styles.textureTypeOptions, s_Styles.textureTypeValues);
+ EditorGUI.showMixedValue = false;
+
+ switch ((TextureImporterType)m_TextureType.intValue)
+ {
+ case TextureImporterType.Sprite:
+ DoSpriteInspector();
+ break;
+ case TextureImporterType.Default:
+ DoTextureDefaultInspector();
+ break;
+ default:
+ Debug.LogWarning("We only support Default or Sprite texture type for now. Texture type is set to default.");
+ m_TextureType.intValue = (int)TextureImporterType.Default;
+ break;
+ }
+
+ DoAdvanceInspector();
+ CommonTextureSettingsGUI();
+ GUILayout.Space(10);
+ DoPlatformSettings();
+ serializedObject.ApplyModifiedProperties();
+ ApplyRevertGUI();
+ }
+
+ ///
+ /// Implementation of AssetImporterEditor.Apply
+ ///
+ protected override void Apply()
+ {
+ FileStream fileStream = new FileStream(((AssetImporter)target).assetPath, FileMode.Open, FileAccess.Read);
+ var doc = PaintDotNet.Data.PhotoshopFileType.PsdLoad.Load(fileStream, ELoadFlag.Header | ELoadFlag.ColorMode);
+
+ PSDApplyEvent evt = new PSDApplyEvent()
+ {
+ instance_id = target.GetInstanceID(),
+ texture_type = m_TextureType.intValue,
+ sprite_mode = m_SpriteMode.intValue,
+ mosaic_layer = m_MosaicLayers.boolValue,
+ import_hidden_layer = m_ImportHiddenLayers.boolValue,
+ character_mode = m_CharacterMode.boolValue,
+ generate_go_hierarchy = m_GenerateGOHierarchy.boolValue,
+ reslice_from_layer = m_ResliceFromLayer.boolValue,
+ is_character_rigged = IsCharacterRigged(),
+ is_psd = IsPSD(doc),
+ color_mode = FileColorMode(doc)
+ };
+ doc.Cleanup();
+ AnalyticFactory.analytics.SendApplyEvent(evt);
+ m_TexturePlatformSettingsHelper.Apply();
+ base.Apply();
+ Selection.activeObject = null;
+ Unsupported.SceneTrackerFlushDirty();
+ PSDImportPostProcessor.currentApplyAssetPath = ((PSDImporter) target).assetPath;
+ }
+
+ static bool IsPSD(PsdFile doc)
+ {
+ return !doc.IsLargeDocument;
+ }
+
+ static PsdColorMode FileColorMode(PsdFile doc)
+ {
+ return doc.ColorMode;
+ }
+
+ bool IsCharacterRigged()
+ {
+ var importer = target as PSDImporter;
+ if (importer != null)
+ {
+ var characterProvider = importer.GetDataProvider();
+ var meshDataProvider = importer.GetDataProvider();
+ if (characterProvider != null && meshDataProvider != null)
+ {
+ var character = characterProvider.GetCharacterData();
+ foreach (var parts in character.parts)
+ {
+ var vert = meshDataProvider.GetVertices(new GUID(parts.spriteId));
+ var indices = meshDataProvider.GetIndices(new GUID(parts.spriteId));
+ if (parts.bones != null && parts.bones.Length > 0 &&
+ vert != null && vert.Length > 0 &&
+ indices != null && indices.Length > 0)
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ Dictionary> m_PlatfromSettings = new Dictionary>();
+ void LoadPlatformSettings()
+ {
+ foreach (var t in targets)
+ {
+ var importer = ((PSDImporter)t);
+ var importerPlatformSettings = importer.GetAllPlatformSettings();
+ for (int i = 0; i < importerPlatformSettings.Length; ++i)
+ {
+ var tip = importerPlatformSettings[i];
+ List platformSettings = null;
+ m_PlatfromSettings.TryGetValue(tip.name, out platformSettings);
+ if (platformSettings == null)
+ {
+ platformSettings = new List();
+ m_PlatfromSettings.Add(tip.name, platformSettings);
+ }
+ platformSettings.Add(tip);
+ }
+ }
+ }
+
+ void StorePlatformSettings()
+ {
+ var platformSettingsSP = serializedObject.FindProperty("m_PlatformSettings");
+ platformSettingsSP.ClearArray();
+ foreach (var keyValue in m_PlatfromSettings)
+ {
+ if (!keyValue.Value[0].overridden)
+ continue;
+
+ SerializedProperty platformSettingSP = null;
+ for (int i = 0; i < platformSettingsSP.arraySize; ++i)
+ {
+ var sp = platformSettingsSP.GetArrayElementAtIndex(i);
+ if (sp.FindPropertyRelative("m_Name").stringValue == keyValue.Key)
+ platformSettingSP = sp;
+ }
+ if (platformSettingSP == null)
+ {
+ platformSettingsSP.InsertArrayElementAtIndex(platformSettingsSP.arraySize);
+ platformSettingSP = platformSettingsSP.GetArrayElementAtIndex(platformSettingsSP.arraySize - 1);
+ }
+
+ var tip = keyValue.Value[0];
+ platformSettingSP.FindPropertyRelative("m_Name").stringValue = tip.name;
+ platformSettingSP.FindPropertyRelative("m_Overridden").intValue = tip.overridden ? 1 : 0;
+ platformSettingSP.FindPropertyRelative("m_MaxTextureSize").intValue = tip.maxTextureSize;
+ platformSettingSP.FindPropertyRelative("m_ResizeAlgorithm").intValue = (int)tip.resizeAlgorithm;
+ platformSettingSP.FindPropertyRelative("m_TextureFormat").intValue = (int)tip.format;
+ platformSettingSP.FindPropertyRelative("m_TextureCompression").intValue = (int)tip.textureCompression;
+ platformSettingSP.FindPropertyRelative("m_CompressionQuality").intValue = tip.compressionQuality;
+ platformSettingSP.FindPropertyRelative("m_CrunchedCompression").intValue = tip.crunchedCompression ? 1 : 0;
+ platformSettingSP.FindPropertyRelative("m_AllowsAlphaSplitting").intValue = tip.allowsAlphaSplitting ? 1 : 0;
+ }
+ }
+
+ void DoPlatformSettings()
+ {
+ m_TexturePlatformSettingsHelper.ShowPlatformSpecificSettings();
+ }
+
+ void DoAdvanceInspector()
+ {
+ if (!m_TextureType.hasMultipleDifferentValues)
+ {
+ if (m_AdvanceInspectorGUI.ContainsKey((TextureImporterType)m_TextureType.intValue))
+ {
+ EditorGUILayout.Space();
+
+ m_ShowAdvanced = EditorGUILayout.Foldout(m_ShowAdvanced, s_Styles.showAdvanced, true);
+ if (m_ShowAdvanced)
+ {
+ foreach (var action in m_AdvanceInspectorGUI[(TextureImporterType)m_TextureType.intValue])
+ {
+ action();
+ }
+ }
+ }
+ }
+ EditorGUILayout.Space();
+ }
+
+ void CommonTextureSettingsGUI()
+ {
+ EditorGUI.BeginChangeCheck();
+
+ // Wrap mode
+ bool isVolume = false;
+ WrapModePopup(m_WrapU, m_WrapV, m_WrapW, isVolume, ref m_ShowPerAxisWrapModes);
+
+
+ // Display warning about repeat wrap mode on restricted npot emulation
+ if (m_NPOTScale.intValue == (int)TextureImporterNPOTScale.None &&
+ (m_WrapU.intValue == (int)TextureWrapMode.Repeat || m_WrapV.intValue == (int)TextureWrapMode.Repeat) &&
+ !InternalEditorBridge.DoesHardwareSupportsFullNPOT())
+ {
+ bool displayWarning = false;
+ foreach (var target in targets)
+ {
+ var imp = (PSDImporter)target;
+ int w = imp.textureActualWidth;
+ int h = imp.textureActualHeight;
+ if (!Mathf.IsPowerOfTwo(w) || !Mathf.IsPowerOfTwo(h))
+ {
+ displayWarning = true;
+ break;
+ }
+ }
+
+ if (displayWarning)
+ {
+ EditorGUILayout.HelpBox(s_Styles.warpNotSupportWarning.text, MessageType.Warning, true);
+ }
+ }
+
+ // Filter mode
+ EditorGUI.showMixedValue = m_FilterMode.hasMultipleDifferentValues;
+ FilterMode filter = (FilterMode)m_FilterMode.intValue;
+ if ((int)filter == -1)
+ {
+ if (m_FadeOut.intValue > 0 || m_ConvertToNormalMap.intValue > 0)
+ filter = FilterMode.Trilinear;
+ else
+ filter = FilterMode.Bilinear;
+ }
+ filter = (FilterMode)EditorGUILayout.IntPopup(s_Styles.filterMode, (int)filter, s_Styles.filterModeOptions, m_FilterModeOptions);
+ EditorGUI.showMixedValue = false;
+ if (EditorGUI.EndChangeCheck())
+ m_FilterMode.intValue = (int)filter;
+
+ // Aniso
+ bool showAniso = (FilterMode)m_FilterMode.intValue != FilterMode.Point
+ && m_EnableMipMap.intValue > 0
+ && (TextureImporterShape)m_TextureShape.intValue != TextureImporterShape.TextureCube;
+ using (new EditorGUI.DisabledScope(!showAniso))
+ {
+ EditorGUI.BeginChangeCheck();
+ EditorGUI.showMixedValue = m_Aniso.hasMultipleDifferentValues;
+ int aniso = m_Aniso.intValue;
+ if (aniso == -1)
+ aniso = 1;
+ aniso = EditorGUILayout.IntSlider(s_Styles.anisoLevelLabel, aniso, 0, 16);
+ EditorGUI.showMixedValue = false;
+ if (EditorGUI.EndChangeCheck())
+ m_Aniso.intValue = aniso;
+
+ if (aniso > 1)
+ {
+ if (QualitySettings.anisotropicFiltering == AnisotropicFiltering.Disable)
+ EditorGUILayout.HelpBox(s_Styles.anisotropicDisableInfo.text, MessageType.Info);
+ else if (QualitySettings.anisotropicFiltering == AnisotropicFiltering.ForceEnable)
+ EditorGUILayout.HelpBox(s_Styles.anisotropicForceEnableInfo.text, MessageType.Info);
+ }
+ }
+ }
+
+ private static bool IsAnyTextureObjectUsingPerAxisWrapMode(UnityEngine.Object[] objects, bool isVolumeTexture)
+ {
+ foreach (var o in objects)
+ {
+ int u = 0, v = 0, w = 0;
+ // the objects can be Textures themselves, or texture-related importers
+ if (o is Texture)
+ {
+ var ti = (Texture)o;
+ u = (int)ti.wrapModeU;
+ v = (int)ti.wrapModeV;
+ w = (int)ti.wrapModeW;
+ }
+ if (o is TextureImporter)
+ {
+ var ti = (TextureImporter)o;
+ u = (int)ti.wrapModeU;
+ v = (int)ti.wrapModeV;
+ w = (int)ti.wrapModeW;
+ }
+ if (o is IHVImageFormatImporter)
+ {
+ var ti = (IHVImageFormatImporter)o;
+ u = (int)ti.wrapModeU;
+ v = (int)ti.wrapModeV;
+ w = (int)ti.wrapModeW;
+ }
+ u = Mathf.Max(0, u);
+ v = Mathf.Max(0, v);
+ w = Mathf.Max(0, w);
+ if (u != v)
+ {
+ return true;
+ }
+ if (isVolumeTexture)
+ {
+ if (u != w || v != w)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // showPerAxisWrapModes is state of whether "Per-Axis" mode should be active in the main dropdown.
+ // It is set automatically if wrap modes in UVW are different, or if user explicitly picks "Per-Axis" option -- when that one is picked,
+ // then it should stay true even if UVW wrap modes will initially be the same.
+ //
+ // Note: W wrapping mode is only shown when isVolumeTexture is true.
+ internal static void WrapModePopup(SerializedProperty wrapU, SerializedProperty wrapV, SerializedProperty wrapW, bool isVolumeTexture, ref bool showPerAxisWrapModes)
+ {
+ if (s_Styles == null)
+ s_Styles = new Styles();
+
+ // In texture importer settings, serialized properties for things like wrap modes can contain -1;
+ // that seems to indicate "use defaults, user has not changed them to anything" but not totally sure.
+ // Show them as Repeat wrap modes in the popups.
+ var wu = (TextureWrapMode)Mathf.Max(wrapU.intValue, 0);
+ var wv = (TextureWrapMode)Mathf.Max(wrapV.intValue, 0);
+ var ww = (TextureWrapMode)Mathf.Max(wrapW.intValue, 0);
+
+ // automatically go into per-axis mode if values are already different
+ if (wu != wv)
+ showPerAxisWrapModes = true;
+ if (isVolumeTexture)
+ {
+ if (wu != ww || wv != ww)
+ showPerAxisWrapModes = true;
+ }
+
+ // It's not possible to determine whether any single texture in the whole selection is using per-axis wrap modes
+ // just from SerializedProperty values. They can only tell if "some values in whole selection are different" (e.g.
+ // wrap value on U axis is not the same among all textures), and can return value of "some" object in the selection
+ // (typically based on object loading order). So in order for more intuitive behavior with multi-selection,
+ // we go over the actual objects when there's >1 object selected and some wrap modes are different.
+ if (!showPerAxisWrapModes)
+ {
+ if (wrapU.hasMultipleDifferentValues || wrapV.hasMultipleDifferentValues || (isVolumeTexture && wrapW.hasMultipleDifferentValues))
+ {
+ if (IsAnyTextureObjectUsingPerAxisWrapMode(wrapU.serializedObject.targetObjects, isVolumeTexture))
+ {
+ showPerAxisWrapModes = true;
+ }
+ }
+ }
+
+ int value = showPerAxisWrapModes ? -1 : (int)wu;
+
+ // main wrap mode popup
+ EditorGUI.BeginChangeCheck();
+ EditorGUI.showMixedValue = !showPerAxisWrapModes && (wrapU.hasMultipleDifferentValues || wrapV.hasMultipleDifferentValues || (isVolumeTexture && wrapW.hasMultipleDifferentValues));
+ value = EditorGUILayout.IntPopup(s_Styles.wrapModeLabel, value, s_Styles.wrapModeContents, s_Styles.wrapModeValues);
+ if (EditorGUI.EndChangeCheck() && value != -1)
+ {
+ // assign the same wrap mode to all axes, and hide per-axis popups
+ wrapU.intValue = value;
+ wrapV.intValue = value;
+ wrapW.intValue = value;
+ showPerAxisWrapModes = false;
+ }
+
+ // show per-axis popups if needed
+ if (value == -1)
+ {
+ showPerAxisWrapModes = true;
+ EditorGUI.indentLevel++;
+ WrapModeAxisPopup(s_Styles.wrapU, wrapU);
+ WrapModeAxisPopup(s_Styles.wrapV, wrapV);
+ if (isVolumeTexture)
+ {
+ WrapModeAxisPopup(s_Styles.wrapW, wrapW);
+ }
+ EditorGUI.indentLevel--;
+ }
+ EditorGUI.showMixedValue = false;
+ }
+
+ static void WrapModeAxisPopup(GUIContent label, SerializedProperty wrapProperty)
+ {
+ // In texture importer settings, serialized properties for wrap modes can contain -1, which means "use default".
+ var wrap = (TextureWrapMode)Mathf.Max(wrapProperty.intValue, 0);
+ Rect rect = EditorGUILayout.GetControlRect();
+ EditorGUI.BeginChangeCheck();
+ EditorGUI.BeginProperty(rect, label, wrapProperty);
+ wrap = (TextureWrapMode)EditorGUI.EnumPopup(rect, label, wrap);
+ EditorGUI.EndProperty();
+ if (EditorGUI.EndChangeCheck())
+ {
+ wrapProperty.intValue = (int)wrap;
+ }
+ }
+
+ void DoWrapModePopup()
+ {
+ WrapModePopup(m_WrapU, m_WrapV, m_WrapW, IsVolume(), ref m_ShowPerAxisWrapModes);
+ }
+
+ bool IsVolume()
+ {
+ var t = target as Texture;
+ return t != null && t.dimension == UnityEngine.Rendering.TextureDimension.Tex3D;
+ }
+
+ void DoSpriteInspector()
+ {
+ EditorGUI.BeginChangeCheck();
+ EditorGUILayout.IntPopup(m_SpriteMode, s_Styles.spriteModeOptions, new[] { 1, 2, 3 }, s_Styles.spriteMode);
+
+ // Ensure that PropertyField focus will be cleared when we change spriteMode.
+ if (EditorGUI.EndChangeCheck())
+ {
+ GUIUtility.keyboardControl = 0;
+ }
+
+ EditorGUI.indentLevel++;
+
+ // Show generic attributes
+ if (m_SpriteMode.intValue != 0)
+ {
+ EditorGUILayout.PropertyField(m_SpritePixelsToUnits, s_Styles.spritePixelsPerUnit);
+
+ if (m_SpriteMode.intValue != (int)SpriteImportMode.Polygon && !m_SpriteMode.hasMultipleDifferentValues)
+ {
+ EditorGUILayout.IntPopup(m_SpriteMeshType, s_Styles.spriteMeshTypeOptions, new[] { 0, 1 }, s_Styles.spriteMeshType);
+ }
+
+ EditorGUILayout.IntSlider(m_SpriteExtrude, 0, 32, s_Styles.spriteExtrude);
+
+ if (m_SpriteMode.intValue == 1)
+ {
+ EditorGUILayout.IntPopup(m_Alignment, s_Styles.spriteAlignmentOptions, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s_Styles.spriteAlignment);
+
+ if (m_Alignment.intValue == (int)SpriteAlignment.Custom)
+ {
+ GUILayout.BeginHorizontal();
+ EditorGUILayout.PropertyField(m_SpritePivot, new GUIContent());
+ GUILayout.EndHorizontal();
+ }
+ }
+ }
+
+ EditorGUILayout.PropertyField(m_ImportHiddenLayers, s_Styles.importHiddenLayer);
+ if (m_SpriteMode.intValue == (int)SpriteImportMode.Multiple && !m_SpriteMode.hasMultipleDifferentValues)
+ {
+ EditorGUILayout.PropertyField(m_MosaicLayers, s_Styles.mosaicLayers);
+ using (new EditorGUI.DisabledScope(!m_MosaicLayers.boolValue))
+ {
+ EditorGUILayout.PropertyField(m_CharacterMode, s_Styles.characterMode);
+ using (new EditorGUI.DisabledScope(!m_CharacterMode.boolValue))
+ {
+ EditorGUILayout.PropertyField(m_GenerateGOHierarchy, s_Styles.generateGOHierarchy);
+ EditorGUILayout.IntPopup(m_DocumentAlignment, s_Styles.spriteAlignmentOptions, new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s_Styles.characterAlignment);
+ if (m_DocumentAlignment.intValue == (int)SpriteAlignment.Custom)
+ {
+ GUILayout.BeginHorizontal();
+ GUILayout.Space(EditorGUIUtility.labelWidth);
+ EditorGUILayout.PropertyField(m_DocumentPivot, new GUIContent());
+ GUILayout.EndHorizontal();
+ }
+ //EditorGUILayout.PropertyField(m_PaperDollMode, s_Styles.paperDollMode);
+ }
+
+
+ EditorGUILayout.PropertyField(m_ResliceFromLayer, s_Styles.resliceFromLayer);
+ if (m_ResliceFromLayer.boolValue)
+ {
+ EditorGUILayout.HelpBox(s_Styles.resliceFromLayerWarning.text, MessageType.Info, true);
+ }
+ }
+ m_ShowExperimental = EditorGUILayout.Foldout(m_ShowExperimental, s_Styles.experimental, true);
+ if (m_ShowExperimental)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_KeepDupilcateSpriteName, s_Styles.keepDuplicateSpriteName);
+ EditorGUI.indentLevel--;
+ }
+ }
+
+ using (new EditorGUI.DisabledScope(targets.Length != 1))
+ {
+ GUILayout.BeginHorizontal();
+
+ GUILayout.FlexibleSpace();
+ if (GUILayout.Button(s_Styles.spriteEditorButtonLabel))
+ {
+ if (HasModified())
+ {
+ // To ensure Sprite Editor Window to have the latest texture import setting,
+ // We must applied those modified values first.
+ string dialogText = string.Format(s_Styles.unappliedSettingsDialogContent.text, ((AssetImporter)target).assetPath);
+ if (EditorUtility.DisplayDialog(s_Styles.unappliedSettingsDialogTitle.text,
+ dialogText, s_Styles.applyButtonLabel.text, s_Styles.revertButtonLabel.text))
+ {
+ ApplyAndImport();
+ InternalEditorBridge.ShowSpriteEditorWindow();
+
+ // We reimported the asset which destroyed the editor, so we can't keep running the UI here.
+ GUIUtility.ExitGUI();
+ }
+ }
+ else
+ {
+ InternalEditorBridge.ShowSpriteEditorWindow();
+ }
+ }
+ GUILayout.EndHorizontal();
+ }
+ EditorGUI.indentLevel--;
+ }
+
+ void DoTextureDefaultInspector()
+ {
+ ColorSpaceGUI();
+ AlphaHandlingGUI();
+ }
+
+ void ColorSpaceGUI()
+ {
+ ToggleFromInt(m_sRGBTexture, s_Styles.sRGBTexture);
+ }
+
+ void POTScaleGUI()
+ {
+ using (new EditorGUI.DisabledScope(m_IsPOT || m_TextureType.intValue == (int)TextureImporterType.Sprite))
+ {
+ EnumPopup(m_NPOTScale, typeof(TextureImporterNPOTScale), s_Styles.npot);
+ }
+ }
+
+ void ReadableGUI()
+ {
+ ToggleFromInt(m_IsReadable, s_Styles.readWrite);
+ }
+
+ void AlphaHandlingGUI()
+ {
+ EditorGUI.showMixedValue = m_AlphaSource.hasMultipleDifferentValues;
+ EditorGUI.BeginChangeCheck();
+ int newAlphaUsage = EditorGUILayout.IntPopup(s_Styles.alphaSource, m_AlphaSource.intValue, s_Styles.alphaSourceOptions, s_Styles.alphaSourceValues);
+
+ EditorGUI.showMixedValue = false;
+ if (EditorGUI.EndChangeCheck())
+ {
+ m_AlphaSource.intValue = newAlphaUsage;
+ }
+
+ bool showAlphaIsTransparency = (TextureImporterAlphaSource)m_AlphaSource.intValue != TextureImporterAlphaSource.None;
+ using (new EditorGUI.DisabledScope(!showAlphaIsTransparency))
+ {
+ ToggleFromInt(m_AlphaIsTransparency, s_Styles.alphaIsTransparency);
+ }
+ }
+
+ void MipMapGUI()
+ {
+ ToggleFromInt(m_EnableMipMap, s_Styles.generateMipMaps);
+
+ if (m_EnableMipMap.boolValue && !m_EnableMipMap.hasMultipleDifferentValues)
+ {
+ EditorGUI.indentLevel++;
+ ToggleFromInt(m_BorderMipMap, s_Styles.borderMipMaps);
+ EditorGUILayout.Popup(s_Styles.mipMapFilter, m_MipMapMode.intValue, s_Styles.mipMapFilterOptions);
+
+ ToggleFromInt(m_MipMapsPreserveCoverage, s_Styles.mipMapsPreserveCoverage);
+ if (m_MipMapsPreserveCoverage.intValue != 0 && !m_MipMapsPreserveCoverage.hasMultipleDifferentValues)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUILayout.PropertyField(m_AlphaTestReferenceValue, s_Styles.alphaTestReferenceValue);
+ EditorGUI.indentLevel--;
+ }
+
+ // Mipmap fadeout
+ ToggleFromInt(m_FadeOut, s_Styles.mipmapFadeOutToggle);
+ if (m_FadeOut.intValue > 0)
+ {
+ EditorGUI.indentLevel++;
+ EditorGUI.BeginChangeCheck();
+ float min = m_MipMapFadeDistanceStart.intValue;
+ float max = m_MipMapFadeDistanceEnd.intValue;
+ EditorGUILayout.MinMaxSlider(s_Styles.mipmapFadeOut, ref min, ref max, 0, 10);
+ if (EditorGUI.EndChangeCheck())
+ {
+ m_MipMapFadeDistanceStart.intValue = Mathf.RoundToInt(min);
+ m_MipMapFadeDistanceEnd.intValue = Mathf.RoundToInt(max);
+ }
+ EditorGUI.indentLevel--;
+ }
+ EditorGUI.indentLevel--;
+ }
+ }
+
+ void ToggleFromInt(SerializedProperty property, GUIContent label)
+ {
+ EditorGUI.BeginChangeCheck();
+ EditorGUI.showMixedValue = property.hasMultipleDifferentValues;
+ int value = EditorGUILayout.Toggle(label, property.intValue > 0) ? 1 : 0;
+ EditorGUI.showMixedValue = false;
+ if (EditorGUI.EndChangeCheck())
+ property.intValue = value;
+ }
+
+ void EnumPopup(SerializedProperty property, System.Type type, GUIContent label)
+ {
+ EditorGUILayout.IntPopup(label.text, property.intValue,
+ System.Enum.GetNames(type),
+ System.Enum.GetValues(type) as int[]);
+ }
+
+ void ExportMosaicTexture()
+ {
+ var assetPath = ((AssetImporter)target).assetPath;
+ var texture2D = AssetDatabase.LoadAssetAtPath(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();
+ }
+
+ protected override void ResetValues()
+ {
+ base.ResetValues();
+ LoadPlatformSettings();
+ m_TexturePlatformSettingsHelper = new TexturePlatformSettingsHelper(this);
+ }
+
+ public int GetTargetCount()
+ {
+ return targets.Length;
+ }
+
+ public TextureImporterPlatformSettings GetPlatformTextureSettings(int i, string name)
+ {
+ if(m_PlatfromSettings.ContainsKey(name))
+ if(m_PlatfromSettings[name].Count > i)
+ return m_PlatfromSettings[name][i];
+ return new TextureImporterPlatformSettings()
+ {
+ name = name,
+ overridden = false
+ };
+ }
+
+ public bool ShowPresetSettings()
+ {
+ return assetTarget == null;
+ }
+
+ public bool DoesSourceTextureHaveAlpha(int v)
+ {
+ return true;
+ }
+
+ public bool IsSourceTextureHDR(int v)
+ {
+ return false;
+ }
+
+ public void SetPlatformTextureSettings(int i, TextureImporterPlatformSettings platformSettings)
+ {
+ var psdImporter = ((PSDImporter)targets[i]);
+ psdImporter.SetPlatformTextureSettings(platformSettings);
+ psdImporter.Apply();
+ }
+
+ public void GetImporterSettings(int i, TextureImporterSettings settings)
+ {
+ ((PSDImporter)targets[i]).ReadTextureSettings(settings);
+ // Get settings that have been changed in the inspector
+ GetSerializedPropertySettings(settings);
+ }
+
+ internal TextureImporterSettings GetSerializedPropertySettings(TextureImporterSettings settings)
+ {
+ if (!m_AlphaSource.hasMultipleDifferentValues)
+ settings.alphaSource = (TextureImporterAlphaSource)m_AlphaSource.intValue;
+
+ if (!m_ConvertToNormalMap.hasMultipleDifferentValues)
+ settings.convertToNormalMap = m_ConvertToNormalMap.intValue > 0;
+
+ if (!m_BorderMipMap.hasMultipleDifferentValues)
+ settings.borderMipmap = m_BorderMipMap.intValue > 0;
+
+ if (!m_MipMapsPreserveCoverage.hasMultipleDifferentValues)
+ settings.mipMapsPreserveCoverage = m_MipMapsPreserveCoverage.intValue > 0;
+
+ if (!m_AlphaTestReferenceValue.hasMultipleDifferentValues)
+ settings.alphaTestReferenceValue = m_AlphaTestReferenceValue.floatValue;
+
+ if (!m_NPOTScale.hasMultipleDifferentValues)
+ settings.npotScale = (TextureImporterNPOTScale)m_NPOTScale.intValue;
+
+ if (!m_IsReadable.hasMultipleDifferentValues)
+ settings.readable = m_IsReadable.intValue > 0;
+
+ if (!m_sRGBTexture.hasMultipleDifferentValues)
+ settings.sRGBTexture = m_sRGBTexture.intValue > 0;
+
+ if (!m_EnableMipMap.hasMultipleDifferentValues)
+ settings.mipmapEnabled = m_EnableMipMap.intValue > 0;
+
+ if (!m_MipMapMode.hasMultipleDifferentValues)
+ settings.mipmapFilter = (TextureImporterMipFilter)m_MipMapMode.intValue;
+
+ if (!m_FadeOut.hasMultipleDifferentValues)
+ settings.fadeOut = m_FadeOut.intValue > 0;
+
+ if (!m_MipMapFadeDistanceStart.hasMultipleDifferentValues)
+ settings.mipmapFadeDistanceStart = m_MipMapFadeDistanceStart.intValue;
+
+ if (!m_MipMapFadeDistanceEnd.hasMultipleDifferentValues)
+ settings.mipmapFadeDistanceEnd = m_MipMapFadeDistanceEnd.intValue;
+
+ if (!m_SpriteMode.hasMultipleDifferentValues)
+ settings.spriteMode = m_SpriteMode.intValue;
+
+ if (!m_SpritePixelsToUnits.hasMultipleDifferentValues)
+ settings.spritePixelsPerUnit = m_SpritePixelsToUnits.floatValue;
+
+ if (!m_SpriteExtrude.hasMultipleDifferentValues)
+ settings.spriteExtrude = (uint)m_SpriteExtrude.intValue;
+
+ if (!m_SpriteMeshType.hasMultipleDifferentValues)
+ settings.spriteMeshType = (SpriteMeshType)m_SpriteMeshType.intValue;
+
+ if (!m_Alignment.hasMultipleDifferentValues)
+ settings.spriteAlignment = m_Alignment.intValue;
+
+ if (!m_SpritePivot.hasMultipleDifferentValues)
+ settings.spritePivot = m_SpritePivot.vector2Value;
+
+ if (!m_WrapU.hasMultipleDifferentValues)
+ settings.wrapModeU = (TextureWrapMode)m_WrapU.intValue;
+ if (!m_WrapV.hasMultipleDifferentValues)
+ settings.wrapModeU = (TextureWrapMode)m_WrapV.intValue;
+ if (!m_WrapW.hasMultipleDifferentValues)
+ settings.wrapModeU = (TextureWrapMode)m_WrapW.intValue;
+
+ if (!m_FilterMode.hasMultipleDifferentValues)
+ settings.filterMode = (FilterMode)m_FilterMode.intValue;
+
+ if (!m_Aniso.hasMultipleDifferentValues)
+ settings.aniso = m_Aniso.intValue;
+
+
+ if (!m_AlphaIsTransparency.hasMultipleDifferentValues)
+ settings.alphaIsTransparency = m_AlphaIsTransparency.intValue > 0;
+
+ if (!m_TextureType.hasMultipleDifferentValues)
+ settings.textureType = (TextureImporterType)m_TextureType.intValue;
+
+ if (!m_TextureShape.hasMultipleDifferentValues)
+ settings.textureShape = (TextureImporterShape)m_TextureShape.intValue;
+
+ return settings;
+ }
+ ///
+ /// Override of AssetImporterEditor.showImportedObject
+ /// The property always returns false so that imported objects does not show up in the Inspector.
+ ///
+ /// false
+ public override bool showImportedObject
+ {
+ get { return false; }
+ }
+
+ public bool textureTypeHasMultipleDifferentValues
+ {
+ get { return m_TextureType.hasMultipleDifferentValues; }
+ }
+
+ public TextureImporterType textureType
+ {
+ get { return (TextureImporterType)m_TextureType.intValue; }
+ }
+
+ public SpriteImportMode spriteImportMode
+ {
+ get { return (SpriteImportMode)m_SpriteMode.intValue; }
+ }
+
+ public override bool HasModified()
+ {
+ if (base.HasModified())
+ return true;
+
+ return m_TexturePlatformSettingsHelper.HasModified();
+ }
+
+ internal class Styles
+ {
+ public readonly GUIContent textureTypeTitle = new GUIContent("Texture Type", "What will this texture be used for?");
+ public readonly GUIContent[] textureTypeOptions =
+ {
+ new GUIContent("Default", "Texture is a normal image such as a diffuse texture or other."),
+ new GUIContent("Sprite (2D and UI)", "Texture is used for a sprite."),
+ };
+ public readonly int[] textureTypeValues =
+ {
+ (int)TextureImporterType.Default,
+ (int)TextureImporterType.Sprite,
+ };
+
+ public readonly GUIContent textureShape = new GUIContent("Texture Shape", "What shape is this texture?");
+ private readonly GUIContent textureShape2D = new GUIContent("2D, Texture is 2D.");
+ private readonly GUIContent textureShapeCube = new GUIContent("Cube", "Texture is a Cubemap.");
+ public readonly Dictionary textureShapeOptionsDictionnary = new Dictionary();
+ public readonly Dictionary textureShapeValuesDictionnary = new Dictionary();
+
+
+ public readonly GUIContent filterMode = new GUIContent("Filter Mode");
+ public readonly GUIContent[] filterModeOptions =
+ {
+ new GUIContent("Point (no filter)"),
+ new GUIContent("Bilinear"),
+ new GUIContent("Trilinear")
+ };
+
+ public readonly GUIContent textureFormat = new GUIContent("Format");
+
+ public readonly GUIContent defaultPlatform = new GUIContent("Default");
+ public readonly GUIContent mipmapFadeOutToggle = new GUIContent("Fadeout Mip Maps");
+ public readonly GUIContent mipmapFadeOut = new GUIContent("Fade Range");
+ public readonly GUIContent readWrite = new GUIContent("Read/Write Enabled", "Enable to be able to access the raw pixel data from code.");
+
+ public readonly GUIContent alphaSource = new GUIContent("Alpha Source", "How is the alpha generated for the imported texture.");
+ public readonly GUIContent[] alphaSourceOptions =
+ {
+ new GUIContent("None", "No Alpha will be used."),
+ new GUIContent("Input Texture Alpha", "Use Alpha from the input texture if one is provided."),
+ new GUIContent("From Gray Scale", "Generate Alpha from image gray scale."),
+ };
+ public readonly int[] alphaSourceValues =
+ {
+ (int)TextureImporterAlphaSource.None,
+ (int)TextureImporterAlphaSource.FromInput,
+ (int)TextureImporterAlphaSource.FromGrayScale,
+ };
+
+ public readonly GUIContent generateMipMaps = new GUIContent("Generate Mip Maps");
+ public readonly GUIContent sRGBTexture = new GUIContent("sRGB (Color Texture)", "Texture content is stored in gamma space. Non-HDR color textures should enable this flag (except if used for IMGUI).");
+ public readonly GUIContent borderMipMaps = new GUIContent("Border Mip Maps");
+ public readonly GUIContent mipMapsPreserveCoverage = new GUIContent("Mip Maps Preserve Coverage", "The alpha channel of generated Mip Maps will preserve coverage during the alpha test.");
+ public readonly GUIContent alphaTestReferenceValue = new GUIContent("Alpha Cutoff Value", "The reference value used during the alpha test. Controls Mip Map coverage.");
+ public readonly GUIContent mipMapFilter = new GUIContent("Mip Map Filtering");
+ public readonly GUIContent[] mipMapFilterOptions =
+ {
+ new GUIContent("Box"),
+ new GUIContent("Kaiser"),
+ };
+ public readonly GUIContent npot = new GUIContent("Non Power of 2", "How non-power-of-two textures are scaled on import.");
+
+ public readonly GUIContent compressionQuality = new GUIContent("Compressor Quality");
+ public readonly GUIContent compressionQualitySlider = new GUIContent("Compressor Quality", "Use the slider to adjust compression quality from 0 (Fastest) to 100 (Best)");
+ public readonly GUIContent[] mobileCompressionQualityOptions =
+ {
+ new GUIContent("Fast"),
+ new GUIContent("Normal"),
+ new GUIContent("Best")
+ };
+
+ public readonly GUIContent spriteMode = new GUIContent("Sprite Mode");
+ public readonly GUIContent[] spriteModeOptions =
+ {
+ new GUIContent("Single"),
+ new GUIContent("Multiple"),
+ new GUIContent("Polygon"),
+ };
+ public readonly GUIContent[] spriteMeshTypeOptions =
+ {
+ new GUIContent("Full Rect"),
+ new GUIContent("Tight"),
+ };
+
+ public readonly GUIContent spritePackingTag = new GUIContent("Packing Tag", "Tag for the Sprite Packing system.");
+ public readonly GUIContent spritePixelsPerUnit = new GUIContent("Pixels Per Unit", "How many pixels in the sprite correspond to one unit in the world.");
+ public readonly GUIContent spriteExtrude = new GUIContent("Extrude Edges", "How much empty area to leave around the sprite in the generated mesh.");
+ public readonly GUIContent spriteMeshType = new GUIContent("Mesh Type", "Type of sprite mesh to generate.");
+ public readonly GUIContent spriteAlignment = new GUIContent("Pivot", "Sprite pivot point in its local space. May be used for syncing animation frames of different sizes.");
+ public readonly GUIContent characterAlignment = new GUIContent("Pivot", "Character pivot point in its local space using normalized value i.e. 0 - 1");
+
+ public readonly GUIContent[] spriteAlignmentOptions =
+ {
+ new GUIContent("Center"),
+ new GUIContent("Top Left"),
+ new GUIContent("Top"),
+ new GUIContent("Top Right"),
+ new GUIContent("Left"),
+ new GUIContent("Right"),
+ new GUIContent("Bottom Left"),
+ new GUIContent("Bottom"),
+ new GUIContent("Bottom Right"),
+ new GUIContent("Custom"),
+ };
+
+ public readonly GUIContent warpNotSupportWarning = new GUIContent("Graphics device doesn't support Repeat wrap mode on NPOT textures. Falling back to Clamp.");
+ public readonly GUIContent anisoLevelLabel = new GUIContent("Aniso Level");
+ public readonly GUIContent anisotropicDisableInfo = new GUIContent("Anisotropic filtering is disabled for all textures in Quality Settings.");
+ public readonly GUIContent anisotropicForceEnableInfo = new GUIContent("Anisotropic filtering is enabled for all textures in Quality Settings.");
+ public readonly GUIContent unappliedSettingsDialogTitle = new GUIContent("Unapplied import settings");
+ public readonly GUIContent unappliedSettingsDialogContent = new GUIContent("Unapplied import settings for \'{0}\'.\nApply and continue to sprite editor or cancel.");
+ public readonly GUIContent applyButtonLabel = new GUIContent("Apply");
+ public readonly GUIContent revertButtonLabel = new GUIContent("Revert");
+ public readonly GUIContent spriteEditorButtonLabel = new GUIContent("Sprite Editor");
+ public readonly GUIContent resliceFromLayerWarning = new GUIContent("This will reinitialize and recreate all Sprites based on the file’s layer data. Existing Sprite metadata from previously generated Sprites are copied over.");
+ public readonly GUIContent alphaIsTransparency = new GUIContent("Alpha Is Transparency", "If the provided alpha channel is transparency, enable this to pre-filter the color to avoid texture filtering artifacts. This is not supported for HDR textures.");
+ public readonly GUIContent etc1Compression = new GUIContent("Compress using ETC1 (split alpha channel)|Alpha for this texture will be preserved by splitting the alpha channel to another texture, and both resulting textures will be compressed using ETC1.");
+ public readonly GUIContent crunchedCompression = new GUIContent("Use Crunch Compression", "Texture is crunch-compressed to save space on disk when applicable.");
+
+ public readonly GUIContent showAdvanced = new GUIContent("Advanced", "Show advanced settings.");
+
+ public readonly GUIContent platformSettingsLabel = new GUIContent("Platform Setttings");
+
+ public readonly GUIContent[] platformSettingsSelection;
+
+ public readonly GUIContent wrapModeLabel = new GUIContent("Wrap Mode");
+ public readonly GUIContent wrapU = new GUIContent("U axis");
+ public readonly GUIContent wrapV = new GUIContent("V axis");
+ public readonly GUIContent wrapW = new GUIContent("W axis");
+
+
+ public readonly GUIContent[] wrapModeContents =
+ {
+ new GUIContent("Repeat"),
+ new GUIContent("Clamp"),
+ new GUIContent("Mirror"),
+ new GUIContent("Mirror Once"),
+ new GUIContent("Per-axis")
+ };
+ public readonly int[] wrapModeValues =
+ {
+ (int)TextureWrapMode.Repeat,
+ (int)TextureWrapMode.Clamp,
+ (int)TextureWrapMode.Mirror,
+ (int)TextureWrapMode.MirrorOnce,
+ -1
+ };
+
+ public readonly GUIContent importHiddenLayer = new GUIContent(L10n.Tr("Import Hidden"), L10n.Tr("Import hidden layers"));
+ public readonly GUIContent mosaicLayers = new GUIContent(L10n.Tr("Mosaic"), L10n.Tr("Layers will be imported as individual Sprites"));
+ public readonly GUIContent characterMode = new GUIContent(L10n.Tr("Character Rig"), L10n.Tr("Enable to support 2D Animation character rigging"));
+ public readonly GUIContent generateGOHierarchy = new GUIContent(L10n.Tr("Use Layer Grouping"), L10n.Tr("GameObjects are grouped according to source file layer grouping"));
+ public readonly GUIContent resliceFromLayer = new GUIContent(L10n.Tr("Reslice"), L10n.Tr("Recreate Sprite rects from file"));
+ public readonly GUIContent paperDollMode = new GUIContent(L10n.Tr("Paper Doll Mode"), L10n.Tr("Special mode to generate a Prefab for Paper Doll use case"));
+ public readonly GUIContent experimental = new GUIContent(L10n.Tr("Experimental"));
+ public readonly GUIContent keepDuplicateSpriteName = new GUIContent(L10n.Tr("Keep Duplicate Name"), L10n.Tr("Keep Sprite name same as Layer Name even if there are duplicated Layer Name"));
+
+ public Styles()
+ {
+ // This is far from ideal, but it's better than having tons of logic in the GUI code itself.
+ // The combination should not grow too much anyway since only Texture3D will be added later.
+ GUIContent[] s2D_Options = { textureShape2D };
+ GUIContent[] sCube_Options = { textureShapeCube };
+ GUIContent[] s2D_Cube_Options = { textureShape2D, textureShapeCube };
+ textureShapeOptionsDictionnary.Add(TextureImporterShape.Texture2D, s2D_Options);
+ textureShapeOptionsDictionnary.Add(TextureImporterShape.TextureCube, sCube_Options);
+ textureShapeOptionsDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube, s2D_Cube_Options);
+
+ int[] s2D_Values = { (int)TextureImporterShape.Texture2D };
+ int[] sCube_Values = { (int)TextureImporterShape.TextureCube };
+ int[] s2D_Cube_Values = { (int)TextureImporterShape.Texture2D, (int)TextureImporterShape.TextureCube };
+ textureShapeValuesDictionnary.Add(TextureImporterShape.Texture2D, s2D_Values);
+ textureShapeValuesDictionnary.Add(TextureImporterShape.TextureCube, sCube_Values);
+ textureShapeValuesDictionnary.Add(TextureImporterShape.Texture2D | TextureImporterShape.TextureCube, s2D_Cube_Values);
+
+ platformSettingsSelection = new GUIContent[TexturePlatformSettingsModal.kValidBuildPlatform.Length];
+ for (int i = 0; i < TexturePlatformSettingsModal.kValidBuildPlatform.Length; ++i)
+ {
+ platformSettingsSelection[i] = new GUIContent(TexturePlatformSettingsModal.kValidBuildPlatform[i].buildTargetName);
+ }
+ }
+ }
+
+ internal static Styles s_Styles;
+ }
+}
diff --git a/Editor/PSDImporterEditor.cs.meta b/Editor/PSDImporterEditor.cs.meta
index b9895fe..eb174d7 100644
--- a/Editor/PSDImporterEditor.cs.meta
+++ b/Editor/PSDImporterEditor.cs.meta
@@ -1,11 +1,11 @@
-fileFormatVersion: 2
-guid: 18bf2b24e4cf52b4db1d73f71d4bd76b
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 18bf2b24e4cf52b4db1d73f71d4bd76b
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDLayer.cs b/Editor/PSDLayer.cs
index 185a75c..57f6cc5 100644
--- a/Editor/PSDLayer.cs
+++ b/Editor/PSDLayer.cs
@@ -1,59 +1,59 @@
-using System;
-using Unity.Collections;
-using UnityEngine;
-
-namespace UnityEditor.U2D.PSD
-{
- [Serializable]
- class PSDLayer
- {
- [SerializeField]
- string m_Name;
- [SerializeField]
- string m_SpriteName;
- [SerializeField]
- bool m_IsGroup;
- [SerializeField]
- int m_ParentIndex;
- [SerializeField]
- string m_SpriteID;
- [SerializeField]
- int m_LayerID;
- [SerializeField]
- Vector2Int m_MosaicPosition;
-
- [NonSerialized]
- GameObject m_GameObject;
-
- public PSDLayer(NativeArray tex, int parent, bool group, string layerName, int width, int height, int id)
- {
- isGroup = group;
- parentIndex = parent;
- texture = tex;
- name = layerName;
- this.width = width;
- this.height = height;
- layerID = id;
- }
-
- public int layerID { get { return m_LayerID; } private set { m_LayerID = value; } }
-
- public string name { get { return m_Name; } private set { m_Name = value; } }
- public string spriteName { get { return m_SpriteName; } set { m_SpriteName = value; } }
- public bool isGroup { get { return m_IsGroup; } private set { m_IsGroup = value; } }
- public int parentIndex { get { return m_ParentIndex; } private set { m_ParentIndex = value; } }
- public Vector2Int mosaicPosition { get { return m_MosaicPosition; } set { m_MosaicPosition = value; } }
- public GUID spriteID { get { return new GUID(m_SpriteID); } set { m_SpriteID = value.ToString(); } }
- public GameObject gameObject { get { return m_GameObject; } set { m_GameObject = value; } }
-
- public NativeArray texture { get; set; }
- public int width { get; private set; }
- public int height { get; private set; }
-
- public void Dispose()
- {
- if (texture.IsCreated)
- texture.Dispose();
- }
- }
-}
+using System;
+using Unity.Collections;
+using UnityEngine;
+
+namespace UnityEditor.U2D.PSD
+{
+ [Serializable]
+ class PSDLayer
+ {
+ [SerializeField]
+ string m_Name;
+ [SerializeField]
+ string m_SpriteName;
+ [SerializeField]
+ bool m_IsGroup;
+ [SerializeField]
+ int m_ParentIndex;
+ [SerializeField]
+ string m_SpriteID;
+ [SerializeField]
+ int m_LayerID;
+ [SerializeField]
+ Vector2Int m_MosaicPosition;
+
+ [NonSerialized]
+ GameObject m_GameObject;
+
+ public PSDLayer(NativeArray tex, int parent, bool group, string layerName, int width, int height, int id)
+ {
+ isGroup = group;
+ parentIndex = parent;
+ texture = tex;
+ name = layerName;
+ this.width = width;
+ this.height = height;
+ layerID = id;
+ }
+
+ public int layerID { get { return m_LayerID; } private set { m_LayerID = value; } }
+
+ public string name { get { return m_Name; } private set { m_Name = value; } }
+ public string spriteName { get { return m_SpriteName; } set { m_SpriteName = value; } }
+ public bool isGroup { get { return m_IsGroup; } private set { m_IsGroup = value; } }
+ public int parentIndex { get { return m_ParentIndex; } private set { m_ParentIndex = value; } }
+ public Vector2Int mosaicPosition { get { return m_MosaicPosition; } set { m_MosaicPosition = value; } }
+ public GUID spriteID { get { return new GUID(m_SpriteID); } set { m_SpriteID = value.ToString(); } }
+ public GameObject gameObject { get { return m_GameObject; } set { m_GameObject = value; } }
+
+ public NativeArray texture { get; set; }
+ public int width { get; private set; }
+ public int height { get; private set; }
+
+ public void Dispose()
+ {
+ if (texture.IsCreated)
+ texture.Dispose();
+ }
+ }
+}
diff --git a/Editor/PSDLayer.cs.meta b/Editor/PSDLayer.cs.meta
index b602270..4d8cf68 100644
--- a/Editor/PSDLayer.cs.meta
+++ b/Editor/PSDLayer.cs.meta
@@ -1,11 +1,11 @@
-fileFormatVersion: 2
-guid: a775ce65fe4b55c46a628fa416f319d3
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: a775ce65fe4b55c46a628fa416f319d3
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDPlugin.meta b/Editor/PSDPlugin.meta
index b78ae1c..ad5c91f 100644
--- a/Editor/PSDPlugin.meta
+++ b/Editor/PSDPlugin.meta
@@ -1,10 +1,10 @@
-fileFormatVersion: 2
-guid: c21e2663cf9e69a40b8ac0838a3f9ae1
-folderAsset: yes
-timeCreated: 1502356798
-licenseType: Pro
-DefaultImporter:
- externalObjects: {}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: c21e2663cf9e69a40b8ac0838a3f9ae1
+folderAsset: yes
+timeCreated: 1502356798
+licenseType: Pro
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDPlugin/AssemblyInfo.cs b/Editor/PSDPlugin/AssemblyInfo.cs
index 8ebf792..320536a 100644
--- a/Editor/PSDPlugin/AssemblyInfo.cs
+++ b/Editor/PSDPlugin/AssemblyInfo.cs
@@ -1,3 +1,3 @@
-using System.Runtime.CompilerServices;
-
+using System.Runtime.CompilerServices;
+
[assembly: InternalsVisibleTo("Unity.2D.PsdImporter.Editor")]
\ No newline at end of file
diff --git a/Editor/PSDPlugin/AssemblyInfo.cs.meta b/Editor/PSDPlugin/AssemblyInfo.cs.meta
index ce1ab1d..48fc37f 100644
--- a/Editor/PSDPlugin/AssemblyInfo.cs.meta
+++ b/Editor/PSDPlugin/AssemblyInfo.cs.meta
@@ -1,11 +1,11 @@
-fileFormatVersion: 2
-guid: 86edfd93afbfbfd4a9dd8afefbb6ba14
-MonoImporter:
- externalObjects: {}
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 86edfd93afbfbfd4a9dd8afefbb6ba14
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDPlugin/PDNWrapper.meta b/Editor/PSDPlugin/PDNWrapper.meta
index 62a7895..9bac7a1 100644
--- a/Editor/PSDPlugin/PDNWrapper.meta
+++ b/Editor/PSDPlugin/PDNWrapper.meta
@@ -1,9 +1,9 @@
-fileFormatVersion: 2
-guid: 9fcfe7284d9f34b4eae286b83227271d
-folderAsset: yes
-timeCreated: 1495006553
-licenseType: Pro
-DefaultImporter:
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 9fcfe7284d9f34b4eae286b83227271d
+folderAsset: yes
+timeCreated: 1495006553
+licenseType: Pro
+DefaultImporter:
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDPlugin/PDNWrapper/BitmapLayer.cs b/Editor/PSDPlugin/PDNWrapper/BitmapLayer.cs
index a6f2521..c824dc0 100644
--- a/Editor/PSDPlugin/PDNWrapper/BitmapLayer.cs
+++ b/Editor/PSDPlugin/PDNWrapper/BitmapLayer.cs
@@ -1,50 +1,50 @@
-using System.Collections;
-using System.Collections.Generic;
-
-namespace PDNWrapper
-{
- internal static class Layer
- {
- public static BitmapLayer CreateBackgroundLayer(int w, int h)
- {
- return new BitmapLayer(w, h);
- }
- }
-
- internal class BitmapLayer
- {
- int width, height;
-
- public Rectangle Bounds
- {
- get {return new Rectangle(0, 0, width, height); }
- }
-
- public void Dispose()
- {
- Surface.Dispose();
- foreach (var layer in ChildLayer)
- layer.Dispose();
- }
-
- public BitmapLayer(int w, int h)
- {
- Surface = new Surface(w, h);
- width = w;
- height = h;
- ChildLayer = new List();
- IsGroup = false;
- }
- public int LayerID { get; set; }
-
- public bool IsGroup {get; set; }
- public BitmapLayer ParentLayer {get; set; }
- public List ChildLayer { get; set; }
- public string Name { get; set; }
- public byte Opacity { get; set; }
- public bool Visible { get; set; }
- public LayerBlendMode BlendMode { get; set; }
-
- public Surface Surface { get; set; }
- }
-}
+using System.Collections;
+using System.Collections.Generic;
+
+namespace PDNWrapper
+{
+ internal static class Layer
+ {
+ public static BitmapLayer CreateBackgroundLayer(int w, int h)
+ {
+ return new BitmapLayer(w, h);
+ }
+ }
+
+ internal class BitmapLayer
+ {
+ int width, height;
+
+ public Rectangle Bounds
+ {
+ get {return new Rectangle(0, 0, width, height); }
+ }
+
+ public void Dispose()
+ {
+ Surface.Dispose();
+ foreach (var layer in ChildLayer)
+ layer.Dispose();
+ }
+
+ public BitmapLayer(int w, int h)
+ {
+ Surface = new Surface(w, h);
+ width = w;
+ height = h;
+ ChildLayer = new List();
+ IsGroup = false;
+ }
+ public int LayerID { get; set; }
+
+ public bool IsGroup {get; set; }
+ public BitmapLayer ParentLayer {get; set; }
+ public List ChildLayer { get; set; }
+ public string Name { get; set; }
+ public byte Opacity { get; set; }
+ public bool Visible { get; set; }
+ public LayerBlendMode BlendMode { get; set; }
+
+ public Surface Surface { get; set; }
+ }
+}
diff --git a/Editor/PSDPlugin/PDNWrapper/BitmapLayer.cs.meta b/Editor/PSDPlugin/PDNWrapper/BitmapLayer.cs.meta
index 395afd5..c427cbf 100644
--- a/Editor/PSDPlugin/PDNWrapper/BitmapLayer.cs.meta
+++ b/Editor/PSDPlugin/PDNWrapper/BitmapLayer.cs.meta
@@ -1,12 +1,12 @@
-fileFormatVersion: 2
-guid: 43a7a92da0ad89c40b5a39ed87329536
-timeCreated: 1495006553
-licenseType: Pro
-MonoImporter:
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 43a7a92da0ad89c40b5a39ed87329536
+timeCreated: 1495006553
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDPlugin/PDNWrapper/Document.cs b/Editor/PSDPlugin/PDNWrapper/Document.cs
index f0fd977..8cd1304 100644
--- a/Editor/PSDPlugin/PDNWrapper/Document.cs
+++ b/Editor/PSDPlugin/PDNWrapper/Document.cs
@@ -1,30 +1,30 @@
-using System.Collections;
-using System.Collections.Generic;
-
-namespace PDNWrapper
-{
- internal class Document
- {
- public int width, height;
-
- public Document(int w, int h)
- {
- width = w;
- height = h;
- Layers = new List();
- }
-
- public void Dispose()
- {
- foreach (var layer in Layers)
- layer.Dispose();
- }
-
- public List Layers { get; set; }
-
- public MeasurementUnit DpuUnit { get; set; }
-
- public double DpuX { get; set; }
- public double DpuY { get; set; }
- }
-}
+using System.Collections;
+using System.Collections.Generic;
+
+namespace PDNWrapper
+{
+ internal class Document
+ {
+ public int width, height;
+
+ public Document(int w, int h)
+ {
+ width = w;
+ height = h;
+ Layers = new List();
+ }
+
+ public void Dispose()
+ {
+ foreach (var layer in Layers)
+ layer.Dispose();
+ }
+
+ public List Layers { get; set; }
+
+ public MeasurementUnit DpuUnit { get; set; }
+
+ public double DpuX { get; set; }
+ public double DpuY { get; set; }
+ }
+}
diff --git a/Editor/PSDPlugin/PDNWrapper/Document.cs.meta b/Editor/PSDPlugin/PDNWrapper/Document.cs.meta
index c26664a..b727bea 100644
--- a/Editor/PSDPlugin/PDNWrapper/Document.cs.meta
+++ b/Editor/PSDPlugin/PDNWrapper/Document.cs.meta
@@ -1,12 +1,12 @@
-fileFormatVersion: 2
-guid: 5d036cb10363b5f4b94b39c7afb3e2d0
-timeCreated: 1495006553
-licenseType: Pro
-MonoImporter:
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: 5d036cb10363b5f4b94b39c7afb3e2d0
+timeCreated: 1495006553
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDPlugin/PDNWrapper/Enums.cs b/Editor/PSDPlugin/PDNWrapper/Enums.cs
index c7c18d9..100e09c 100644
--- a/Editor/PSDPlugin/PDNWrapper/Enums.cs
+++ b/Editor/PSDPlugin/PDNWrapper/Enums.cs
@@ -1,27 +1,27 @@
-namespace PDNWrapper
-{
- internal enum MeasurementUnit
- {
- Pixel = 1,
- Inch = 2,
- Centimeter = 3
- }
-
- internal enum LayerBlendMode
- {
- Normal = 0,
- Multiply = 1,
- Additive = 2,
- ColorBurn = 3,
- ColorDodge = 4,
- Reflect = 5,
- Glow = 6,
- Overlay = 7,
- Difference = 8,
- Negation = 9,
- Lighten = 10,
- Darken = 11,
- Screen = 12,
- Xor = 13
- }
-}
+namespace PDNWrapper
+{
+ internal enum MeasurementUnit
+ {
+ Pixel = 1,
+ Inch = 2,
+ Centimeter = 3
+ }
+
+ internal enum LayerBlendMode
+ {
+ Normal = 0,
+ Multiply = 1,
+ Additive = 2,
+ ColorBurn = 3,
+ ColorDodge = 4,
+ Reflect = 5,
+ Glow = 6,
+ Overlay = 7,
+ Difference = 8,
+ Negation = 9,
+ Lighten = 10,
+ Darken = 11,
+ Screen = 12,
+ Xor = 13
+ }
+}
diff --git a/Editor/PSDPlugin/PDNWrapper/Enums.cs.meta b/Editor/PSDPlugin/PDNWrapper/Enums.cs.meta
index b1cb66e..3a307e6 100644
--- a/Editor/PSDPlugin/PDNWrapper/Enums.cs.meta
+++ b/Editor/PSDPlugin/PDNWrapper/Enums.cs.meta
@@ -1,12 +1,12 @@
-fileFormatVersion: 2
-guid: f396654a3007906488e747d54ae80913
-timeCreated: 1495006554
-licenseType: Pro
-MonoImporter:
- serializedVersion: 2
- defaultReferences: []
- executionOrder: 0
- icon: {instanceID: 0}
- userData:
- assetBundleName:
- assetBundleVariant:
+fileFormatVersion: 2
+guid: f396654a3007906488e747d54ae80913
+timeCreated: 1495006554
+licenseType: Pro
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Editor/PSDPlugin/PDNWrapper/PDNDecodeJob.cs b/Editor/PSDPlugin/PDNWrapper/PDNDecodeJob.cs
index c50d074..71819ae 100644
--- a/Editor/PSDPlugin/PDNWrapper/PDNDecodeJob.cs
+++ b/Editor/PSDPlugin/PDNWrapper/PDNDecodeJob.cs
@@ -1,623 +1,623 @@
-using System.Collections;
-using System.Collections.Generic;
-using Unity.Jobs;
-using UnityEngine;
-using Unity.Collections;
-using System;
-using Unity.Collections.LowLevel.Unsafe;
-
-namespace PaintDotNet.Data.PhotoshopFileType
-{
-
- #region PDNDecodeJob
-
- internal struct PDNDecoderData
- {
- // Inputs.
- public PDNWrapper.Rectangle Rect;
- public PDNWrapper.Rectangle LayerRect;
- public PDNWrapper.Rectangle ClippedRect;
- public int SurfaceWidth;
- public int SurfaceHeight;
- public int SurfaceByteDepth;
- public DecodeType DecoderType;
-
- [NativeDisableParallelForRestriction]
- [ReadOnly]
- public NativeArray ColorChannel0;
-
- [NativeDisableParallelForRestriction]
- [ReadOnly]
- public NativeArray ColorChannel1;
-
- [NativeDisableParallelForRestriction]
- [ReadOnly]
- public NativeArray ColorChannel2;
-
- [NativeDisableParallelForRestriction]
- [ReadOnly]
- public NativeArray ColorChannel3;
-
- [NativeDisableParallelForRestriction]
- [ReadOnly]
- [DeallocateOnJobCompletion]
- public NativeArray ColorModeData;
-
- // Outputs
- [NativeDisableParallelForRestriction]
- public NativeArray DecodedImage;
-
- }
-
- internal struct PDNDecoderJob : IJobParallelFor
- {
-
- public PDNDecoderData Data;
-
- public void Execute(int index)
- {
-
- int idx = Data.Rect.Top + index;
- {
- // Calculate index into ImageData source from row and column.
- int idxSrcPixel = (idx - Data.LayerRect.Top) * Data.LayerRect.Width + (Data.Rect.Left - Data.LayerRect.Left);
- int idxSrcBytes = idxSrcPixel * Data.SurfaceByteDepth;
-
- // Calculate pointers to destination Surface.
- var idxDstStart = idx * Data.SurfaceWidth + Data.ClippedRect.Left;
- var idxDstStops = idx * Data.SurfaceWidth + Data.ClippedRect.Right;
-
- // For 16-bit images, take the higher-order byte from the image data, which is now in little-endian order.
- if (Data.SurfaceByteDepth == 2)
- {
- idxSrcBytes++;
- }
-
- switch (Data.DecoderType)
- {
- case DecodeType.RGB32:
- {
- SetPDNRowRgb32(idxDstStart, idxDstStops, idxSrcBytes);
- }
- break;
- case DecodeType.Grayscale32:
- {
- SetPDNRowGrayscale32(idxDstStart, idxDstStops, idxSrcBytes);
- }
- break;
- case DecodeType.RGB:
- {
- SetPDNRowRgb(idxDstStart, idxDstStops, idxSrcBytes);
- }
- break;
- case DecodeType.CMYK:
- {
- SetPDNRowCmyk(idxDstStart, idxDstStops, idxSrcBytes);
- }
- break;
- case DecodeType.Bitmap:
- {
- SetPDNRowBitmap(idxDstStart, idxDstStops, idxSrcBytes);
- }
- break;
- case DecodeType.Grayscale:
- {
- SetPDNRowGrayscale(idxDstStart, idxDstStops, idxSrcBytes);
- }
- break;
- case DecodeType.Indexed:
- {
- SetPDNRowIndexed(idxDstStart, idxDstStops, idxSrcBytes);
- }
- break;
- case DecodeType.Lab:
- {
- SetPDNRowLab(idxDstStart, idxDstStops, idxSrcBytes);
- }
- break;
- }
-
- }
-
- }
-
- // Case 0:
- private void SetPDNRowRgb32(int dstStart, int dstStops, int idxSrc)
- {
- NativeArray cR = Data.ColorChannel0.Reinterpret(1);
- NativeArray cG = Data.ColorChannel1.Reinterpret(1);
- NativeArray cB = Data.ColorChannel2.Reinterpret(1);
- var c = Data.DecodedImage[dstStart];
- while (dstStart < dstStops)
- {
- c.r = ImageDecoderPdn.RGBByteFromHDRFloat(cR[idxSrc / 4]);
- c.g = ImageDecoderPdn.RGBByteFromHDRFloat(cG[idxSrc / 4]);
- c.b = ImageDecoderPdn.RGBByteFromHDRFloat(cB[idxSrc / 4]);
- Data.DecodedImage[dstStart] = c;
-
- dstStart++;
- idxSrc += 4;
- }
- }
-
- // Case 1:
- private void SetPDNRowGrayscale32(int dstStart, int dstStops, int idxSrc)
- {
- NativeArray channel = Data.ColorChannel0.Reinterpret(1);
- var c = Data.DecodedImage[dstStart];
- while (dstStart < dstStops)
- {
- byte rgbValue = ImageDecoderPdn.RGBByteFromHDRFloat(channel[idxSrc / 4]);
- c.r = rgbValue;
- c.g = rgbValue;
- c.b = rgbValue;
- Data.DecodedImage[dstStart] = c;
-
- dstStart++;
- idxSrc += 4;
- }
- }
-
- // Case 2:
- private void SetPDNRowRgb(int dstStart, int dstStops, int idxSrc)
- {
- var c = Data.DecodedImage[dstStart];
- while (dstStart < dstStops)
- {
- c.r = Data.ColorChannel0[idxSrc];
- c.g = Data.ColorChannel1[idxSrc];
- c.b = Data.ColorChannel2[idxSrc];
- Data.DecodedImage[dstStart] = c;
-
- dstStart++;
- idxSrc += Data.SurfaceByteDepth;
- }
- }
-
- // Case 3:
- ///////////////////////////////////////////////////////////////////////////////
- //
- // The color-conversion formulas come from the Colour Space Conversions FAQ:
- // http://www.poynton.com/PDFs/coloureq.pdf
- //
- // RGB --> CMYK CMYK --> RGB
- // --------------------------------------- --------------------------------------------
- // Black = minimum(1-Red,1-Green,1-Blue) Red = 1-minimum(1,Cyan*(1-Black)+Black)
- // Cyan = (1-Red-Black)/(1-Black) Green = 1-minimum(1,Magenta*(1-Black)+Black)
- // Magenta = (1-Green-Black)/(1-Black) Blue = 1-minimum(1,Yellow*(1-Black)+Black)
- // Yellow = (1-Blue-Black)/(1-Black)
- //
- ///////////////////////////////////////////////////////////////////////////////
- private void SetPDNRowCmyk(int dstStart, int dstStops, int idxSrc)
- {
- var c = Data.DecodedImage[dstStart];
- while (dstStart < dstStops)
- {
- // CMYK values are stored as complements, presumably to allow for some
- // measure of compatibility with RGB-only applications.
- var C = 255 - Data.ColorChannel0[idxSrc];
- var M = 255 - Data.ColorChannel1[idxSrc];
- var Y = 255 - Data.ColorChannel2[idxSrc];
- var K = 255 - Data.ColorChannel3[idxSrc];
-
- int R = 255 - Math.Min(255, C * (255 - K) / 255 + K);
- int G = 255 - Math.Min(255, M * (255 - K) / 255 + K);
- int B = 255 - Math.Min(255, Y * (255 - K) / 255 + K);
-
- c.r = (byte)R;
- c.g = (byte)G;
- c.b = (byte)B;
- Data.DecodedImage[dstStart] = c;
-
- dstStart++;
- idxSrc += Data.SurfaceByteDepth;
- }
- }
-
- // Case 4:
- private void SetPDNRowBitmap(int dstStart, int dstStops, int idxSrc)
- {
- var c = Data.DecodedImage[dstStart];
- while (dstStart < dstStops)
- {
- byte mask = (byte)(0x80 >> (idxSrc % 8));
- byte bwValue = (byte)(Data.ColorChannel0[idxSrc / 8] & mask);
- bwValue = (bwValue == 0) ? (byte)255 : (byte)0;
-
- c.r = bwValue;
- c.g = bwValue;
- c.b = bwValue;
- Data.DecodedImage[dstStart] = c;
-
- dstStart++;
- idxSrc += Data.SurfaceByteDepth;
- }
- }
-
- // Case 5:
- private void SetPDNRowGrayscale(int dstStart, int dstStops, int idxSrc)
- {
- var c = Data.DecodedImage[dstStart];
- while (dstStart < dstStops)
- {
-
- c.r = Data.ColorChannel0[idxSrc];
- c.g = Data.ColorChannel0[idxSrc];
- c.b = Data.ColorChannel0[idxSrc];
- Data.DecodedImage[dstStart] = c;
-
- dstStart++;
- idxSrc += Data.SurfaceByteDepth;
- }
- }
-
- // Case 6:
- private void SetPDNRowIndexed(int dstStart, int dstStops, int idxSrc)
- {
- var c = Data.DecodedImage[dstStart];
- int index = (int)Data.ColorChannel0[idxSrc];
- while (dstStart < dstStops)
- {
- c.r = Data.ColorModeData[index];
- c.g = Data.ColorModeData[index + 256];
- c.b = Data.ColorModeData[index + 2 * 256];
- Data.DecodedImage[dstStart] = c;
-
- dstStart++;
- idxSrc += Data.SurfaceByteDepth;
- }
- }
-
- // Case 7:
- private void SetPDNRowLab(int dstStart, int dstStops, int idxSrc)
- {
- var c = Data.DecodedImage[dstStart];
- while (dstStart < dstStops)
- {
- double exL, exA, exB;
- exL = (double)Data.ColorChannel0[idxSrc];
- exA = (double)Data.ColorChannel1[idxSrc];
- exB = (double)Data.ColorChannel2[idxSrc];
-
- int L = (int)(exL / 2.55);
- int a = (int)(exA - 127.5);
- int b = (int)(exB - 127.5);
-
- // First, convert from Lab to XYZ.
- // Standards used Observer = 2, Illuminant = D65
-
- const double ref_X = 95.047;
- const double ref_Y = 100.000;
- const double ref_Z = 108.883;
-
- double var_Y = ((double)L + 16.0) / 116.0;
- double var_X = (double)a / 500.0 + var_Y;
- double var_Z = var_Y - (double)b / 200.0;
-
- double var_X3 = var_X * var_X * var_X;
- double var_Y3 = var_Y * var_Y * var_Y;
- double var_Z3 = var_Z * var_Z * var_Z;
-
- if (var_Y3 > 0.008856)
- var_Y = var_Y3;
- else
- var_Y = (var_Y - 16 / 116) / 7.787;
-
- if (var_X3 > 0.008856)
- var_X = var_X3;
- else
- var_X = (var_X - 16 / 116) / 7.787;
-
- if (var_Z3 > 0.008856)
- var_Z = var_Z3;
- else
- var_Z = (var_Z - 16 / 116) / 7.787;
-
- double X = ref_X * var_X;
- double Y = ref_Y * var_Y;
- double Z = ref_Z * var_Z;
-
- // Then, convert from XYZ to RGB.
- // Standards used Observer = 2, Illuminant = D65
- // ref_X = 95.047, ref_Y = 100.000, ref_Z = 108.883
-
- double var_R = X * 0.032406 + Y * (-0.015372) + Z * (-0.004986);
- double var_G = X * (-0.009689) + Y * 0.018758 + Z * 0.000415;
- double var_B = X * 0.000557 + Y * (-0.002040) + Z * 0.010570;
-
- if (var_R > 0.0031308)
- var_R = 1.055 * (Math.Pow(var_R, 1 / 2.4)) - 0.055;
- else
- var_R = 12.92 * var_R;
-
- if (var_G > 0.0031308)
- var_G = 1.055 * (Math.Pow(var_G, 1 / 2.4)) - 0.055;
- else
- var_G = 12.92 * var_G;
-
- if (var_B > 0.0031308)
- var_B = 1.055 * (Math.Pow(var_B, 1 / 2.4)) - 0.055;
- else
- var_B = 12.92 * var_B;
-
- int nRed = (int)(var_R * 256.0);
- int nGreen = (int)(var_G * 256.0);
- int nBlue = (int)(var_B * 256.0);
-
- if (nRed < 0)
- nRed = 0;
- else if (nRed > 255)
- nRed = 255;
- if (nGreen < 0)
- nGreen = 0;
- else if (nGreen > 255)
- nGreen = 255;
- if (nBlue < 0)
- nBlue = 0;
- else if (nBlue > 255)
- nBlue = 255;
-
- c.r = (byte)nRed;
- c.g = (byte)nGreen;
- c.b = (byte)nBlue;
- Data.DecodedImage[dstStart] = c;
-
- dstStart++;
- idxSrc += Data.SurfaceByteDepth;
- }
- }
- }
-
- #endregion
-
- #region AlphaDecodeJob
-
- internal struct PDNAlphaMaskData
- {
- // Inputs.
- public PDNWrapper.Rectangle Rect;
- public PDNWrapper.Rectangle LayerRect;
- public PDNWrapper.Rectangle ClippedRect;
- public int SurfaceWidth;
- public int SurfaceHeight;
- public int SurfaceByteDepth;
-
- public int HasAlphaChannel;
- public int HasUserAlphaMask;
- public int UserMaskInvertOnBlend;
- public PDNWrapper.Rectangle UserMaskRect;
- public PDNWrapper.Rectangle UserMaskContextRect;
- public int HasLayerAlphaMask;
- public int LayerMaskInvertOnBlend;
- public PDNWrapper.Rectangle LayerMaskRect;
- public PDNWrapper.Rectangle LayerMaskContextRect;
-
- [NativeDisableParallelForRestriction]
- [ReadOnly]
- [DeallocateOnJobCompletion]
- public NativeArray AlphaChannel0;
-
- [NativeDisableParallelForRestriction]
- [ReadOnly]
- public NativeArray UserMask;
-
- [DeallocateOnJobCompletion]
- [NativeDisableParallelForRestriction]
- public NativeArray UserAlphaMask;
-
- [DeallocateOnJobCompletion]
- [NativeDisableParallelForRestriction]
- public NativeArray UserAlphaMaskEmpty;
-
- [NativeDisableParallelForRestriction]
- [ReadOnly]
- public NativeArray LayerMask;
-
- [DeallocateOnJobCompletion]
- [NativeDisableParallelForRestriction]
- public NativeArray LayerAlphaMask;
-
- [DeallocateOnJobCompletion]
- [NativeDisableParallelForRestriction]
- public NativeArray LayerAlphaMaskEmpty;
-
- // Outputs
- [NativeDisableParallelForRestriction]
- public NativeArray DecodedImage;
-
- // Colors.
- public byte UserMaskBackgroundColor;
- public byte LayerMaskBackgroundColor;
- }
-
- internal struct PDNAlphaMaskJob : IJob
- {
-
- public PDNAlphaMaskData Data;
-
- public void Execute()
- {
-
- for (int idx = Data.Rect.Top; idx < Data.Rect.Bottom; idx++)
- {
- // Calculate index into ImageData source from row and column.
- int idxSrcPixel = (idx - Data.LayerRect.Top) * Data.LayerRect.Width + (Data.Rect.Left - Data.LayerRect.Left);
- int idxSrcBytes = idxSrcPixel * Data.SurfaceByteDepth;
-
- // Calculate pointers to destination Surface.
- var idxDstStart = idx * Data.SurfaceWidth + Data.ClippedRect.Left;
- var idxDstStops = idx * Data.SurfaceWidth + Data.ClippedRect.Right;
-
- // For 16-bit images, take the higher-order byte from the image data, which is now in little-endian order.
- if (Data.SurfaceByteDepth == 2)
- {
- idxSrcBytes++;
- }
-
- SetPDNAlphaRow(idxDstStart, idxDstStops, idxSrcBytes);
- if (0 != Data.HasLayerAlphaMask)
- {
- GetMaskAlphaRow(idx, Data.LayerAlphaMask, Data.LayerAlphaMaskEmpty, Data.LayerMask, Data.LayerMaskInvertOnBlend, Data.LayerMaskBackgroundColor, Data.LayerMaskContextRect, Data.LayerMaskRect);
- }
- if (0 != Data.HasUserAlphaMask)
- {
- GetMaskAlphaRow(idx, Data.UserAlphaMask, Data.UserAlphaMaskEmpty, Data.UserMask, Data.UserMaskInvertOnBlend, Data.UserMaskBackgroundColor, Data.UserMaskContextRect, Data.UserMaskRect);
- }
- ApplyPDNMask(idxDstStart, idxDstStops);
-
- }
- }
-
- private void SetPDNAlphaRow(int dstStart, int dstStops, int idxSrc)
- {
- // Set alpha to fully-opaque if there is no alpha channel
- if (0 == Data.HasAlphaChannel)
- {
- while (dstStart < dstStops)
- {
- var c = Data.DecodedImage[dstStart];
- c.a = 255;
- Data.DecodedImage[dstStart] = c;
- dstStart++;
- }
- }
- // Set the alpha channel data
- else
- {
- NativeArray srcAlphaChannel = Data.AlphaChannel0.Reinterpret(1);
- {
- while (dstStart < dstStops)
- {
- var c = Data.DecodedImage[dstStart];
- c.a = (Data.SurfaceByteDepth < 4) ? Data.AlphaChannel0[idxSrc] : ImageDecoderPdn.RGBByteFromHDRFloat(srcAlphaChannel[idxSrc / 4]);
-
- Data.DecodedImage[dstStart] = c;
- dstStart++;
- idxSrc += Data.SurfaceByteDepth;
- }
- }
- }
- }
-
- private void ApplyPDNMask(int dstStart, int dstStops)
- {
- // Do nothing if there are no masks
- if (0 == Data.HasLayerAlphaMask && 0 == Data.HasUserAlphaMask)
- {
- return;
- }
-
- // Apply one mask
- else if (0 == Data.HasLayerAlphaMask || 0 == Data.HasUserAlphaMask)
- {
- var maskAlpha = (0 == Data.HasLayerAlphaMask) ? Data.UserAlphaMask : Data.LayerAlphaMask;
- var maskStart = 0;
- {
- var c = Data.DecodedImage[dstStart];
- while (dstStart < dstStops)
- {
- c.a = (byte)(Data.DecodedImage[dstStart].a * maskAlpha[maskStart] / 255);
- Data.DecodedImage[dstStart] = c;
- dstStart++;
- maskStart++;
- }
- }
- }
- // Apply both masks in one pass, to minimize rounding error
- else
- {
- var maskStart = 0;
- var c = Data.DecodedImage[dstStart];
- {
- while (dstStart < dstStops)
- {
- var alphaFactor = (Data.LayerAlphaMask[maskStart]) * (Data.UserAlphaMask[maskStart]);
- c.a = (byte)(Data.DecodedImage[dstStart].a * alphaFactor / 65025);
- Data.DecodedImage[dstStart] = c;
-
- dstStart++;
- maskStart++;
- }
- }
- }
- }
-
- private void DecodeMaskAlphaRow32(NativeArray Alpha, int dstStart, int dstStops, NativeArray Mask, int maskStart)
- {
- NativeArray floatArray = Mask.Reinterpret(1);
-
- while (dstStart < dstStops)
- {
- Alpha[dstStart] = ImageDecoderPdn.RGBByteFromHDRFloat(floatArray[maskStart / 4]);
-
- dstStart++;
- maskStart += 4;
- }
- }
-
- private void DecodeMaskAlphaRow(NativeArray Alpha, int dstStart, int dstStops, NativeArray Mask, int maskStart, int byteDepth)
- {
- while (dstStart < dstStops)
- {
- Alpha[dstStart] = Mask[maskStart];
-
- dstStart++;
- maskStart += byteDepth;
- }
- }
-
- private unsafe void GetMaskAlphaRow(int idxSrc, NativeArray alphaBuffer, NativeArray alphaBufferEmpty, NativeArray maskChannel, int MaskInvertOnBlend, byte MaskBackgroundColor, PDNWrapper.Rectangle MaskContextRect, PDNWrapper.Rectangle MaskRect)
- {
- //////////////////////////////////////
- // Transfer mask into the alpha array
- // Background color for areas not covered by the mask
- byte backgroundColor = (0 != MaskInvertOnBlend) ? (byte)(255 - MaskBackgroundColor) : MaskBackgroundColor;
- {
- var alphaBufferPtr = NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(alphaBuffer);
- UnsafeUtility.MemSet(alphaBufferPtr, backgroundColor, alphaBuffer.Length);
- }
- // Only process if not Empty.
- if (alphaBufferEmpty[idxSrc] == 0)
- {
- // Get pointers to starting positions
- int alphaColumn = MaskContextRect.X;
- // It's possible that the layer's rect is larger than the clip and it's offset.
- // Since we only copy out the alpha based on the MaskContext size
- // The copy will start from where the MaskContextRect is
- if(Data.LayerRect.X > 0)
- alphaColumn = MaskContextRect.X - Data.LayerRect.X;
- var pAlpha = alphaColumn;
- var pAlphaEnd = pAlpha + MaskContextRect.Width;
-
- int maskRow = idxSrc - MaskRect.Y;
- int maskColumn = MaskContextRect.X - MaskRect.X;
- int idxMaskPixel = (maskRow * MaskRect.Width) + maskColumn;
- var pMask = idxMaskPixel * Data.SurfaceByteDepth;
-
- // Take the high-order byte if values are 16-bit (little-endian)
- if (Data.SurfaceByteDepth == 2)
- {
- pMask++;
- }
-
- // Decode mask into the alpha array.
- if (Data.SurfaceByteDepth == 4)
- {
- DecodeMaskAlphaRow32(alphaBuffer, pAlpha, pAlphaEnd, maskChannel, pMask);
- }
- else
- {
- DecodeMaskAlphaRow(alphaBuffer, pAlpha, pAlphaEnd, maskChannel, pMask, Data.SurfaceByteDepth);
- }
-
- // Obsolete since Photoshop CS6, but retained for compatibility with older versions. Note that the background has already been inverted.
- if (0 != MaskInvertOnBlend)
- {
- PhotoshopFile.Util.Invert(alphaBuffer, pAlpha, pAlphaEnd);
- }
- }
- }
- }
-
- #endregion
+using System.Collections;
+using System.Collections.Generic;
+using Unity.Jobs;
+using UnityEngine;
+using Unity.Collections;
+using System;
+using Unity.Collections.LowLevel.Unsafe;
+
+namespace PaintDotNet.Data.PhotoshopFileType
+{
+
+ #region PDNDecodeJob
+
+ internal struct PDNDecoderData
+ {
+ // Inputs.
+ public PDNWrapper.Rectangle Rect;
+ public PDNWrapper.Rectangle LayerRect;
+ public PDNWrapper.Rectangle ClippedRect;
+ public int SurfaceWidth;
+ public int SurfaceHeight;
+ public int SurfaceByteDepth;
+ public DecodeType DecoderType;
+
+ [NativeDisableParallelForRestriction]
+ [ReadOnly]
+ public NativeArray ColorChannel0;
+
+ [NativeDisableParallelForRestriction]
+ [ReadOnly]
+ public NativeArray ColorChannel1;
+
+ [NativeDisableParallelForRestriction]
+ [ReadOnly]
+ public NativeArray ColorChannel2;
+
+ [NativeDisableParallelForRestriction]
+ [ReadOnly]
+ public NativeArray ColorChannel3;
+
+ [NativeDisableParallelForRestriction]
+ [ReadOnly]
+ [DeallocateOnJobCompletion]
+ public NativeArray ColorModeData;
+
+ // Outputs
+ [NativeDisableParallelForRestriction]
+ public NativeArray DecodedImage;
+
+ }
+
+ internal struct PDNDecoderJob : IJobParallelFor
+ {
+
+ public PDNDecoderData Data;
+
+ public void Execute(int index)
+ {
+
+ int idx = Data.Rect.Top + index;
+ {
+ // Calculate index into ImageData source from row and column.
+ int idxSrcPixel = (idx - Data.LayerRect.Top) * Data.LayerRect.Width + (Data.Rect.Left - Data.LayerRect.Left);
+ int idxSrcBytes = idxSrcPixel * Data.SurfaceByteDepth;
+
+ // Calculate pointers to destination Surface.
+ var idxDstStart = idx * Data.SurfaceWidth + Data.ClippedRect.Left;
+ var idxDstStops = idx * Data.SurfaceWidth + Data.ClippedRect.Right;
+
+ // For 16-bit images, take the higher-order byte from the image data, which is now in little-endian order.
+ if (Data.SurfaceByteDepth == 2)
+ {
+ idxSrcBytes++;
+ }
+
+ switch (Data.DecoderType)
+ {
+ case DecodeType.RGB32:
+ {
+ SetPDNRowRgb32(idxDstStart, idxDstStops, idxSrcBytes);
+ }
+ break;
+ case DecodeType.Grayscale32:
+ {
+ SetPDNRowGrayscale32(idxDstStart, idxDstStops, idxSrcBytes);
+ }
+ break;
+ case DecodeType.RGB:
+ {
+ SetPDNRowRgb(idxDstStart, idxDstStops, idxSrcBytes);
+ }
+ break;
+ case DecodeType.CMYK:
+ {
+ SetPDNRowCmyk(idxDstStart, idxDstStops, idxSrcBytes);
+ }
+ break;
+ case DecodeType.Bitmap:
+ {
+ SetPDNRowBitmap(idxDstStart, idxDstStops, idxSrcBytes);
+ }
+ break;
+ case DecodeType.Grayscale:
+ {
+ SetPDNRowGrayscale(idxDstStart, idxDstStops, idxSrcBytes);
+ }
+ break;
+ case DecodeType.Indexed:
+ {
+ SetPDNRowIndexed(idxDstStart, idxDstStops, idxSrcBytes);
+ }
+ break;
+ case DecodeType.Lab:
+ {
+ SetPDNRowLab(idxDstStart, idxDstStops, idxSrcBytes);
+ }
+ break;
+ }
+
+ }
+
+ }
+
+ // Case 0:
+ private void SetPDNRowRgb32(int dstStart, int dstStops, int idxSrc)
+ {
+ NativeArray cR = Data.ColorChannel0.Reinterpret(1);
+ NativeArray cG = Data.ColorChannel1.Reinterpret(1);
+ NativeArray cB = Data.ColorChannel2.Reinterpret(1);
+ var c = Data.DecodedImage[dstStart];
+ while (dstStart < dstStops)
+ {
+ c.r = ImageDecoderPdn.RGBByteFromHDRFloat(cR[idxSrc / 4]);
+ c.g = ImageDecoderPdn.RGBByteFromHDRFloat(cG[idxSrc / 4]);
+ c.b = ImageDecoderPdn.RGBByteFromHDRFloat(cB[idxSrc / 4]);
+ Data.DecodedImage[dstStart] = c;
+
+ dstStart++;
+ idxSrc += 4;
+ }
+ }
+
+ // Case 1:
+ private void SetPDNRowGrayscale32(int dstStart, int dstStops, int idxSrc)
+ {
+ NativeArray channel = Data.ColorChannel0.Reinterpret(1);
+ var c = Data.DecodedImage[dstStart];
+ while (dstStart < dstStops)
+ {
+ byte rgbValue = ImageDecoderPdn.RGBByteFromHDRFloat(channel[idxSrc / 4]);
+ c.r = rgbValue;
+ c.g = rgbValue;
+ c.b = rgbValue;
+ Data.DecodedImage[dstStart] = c;
+
+ dstStart++;
+ idxSrc += 4;
+ }
+ }
+
+ // Case 2:
+ private void SetPDNRowRgb(int dstStart, int dstStops, int idxSrc)
+ {
+ var c = Data.DecodedImage[dstStart];
+ while (dstStart < dstStops)
+ {
+ c.r = Data.ColorChannel0[idxSrc];
+ c.g = Data.ColorChannel1[idxSrc];
+ c.b = Data.ColorChannel2[idxSrc];
+ Data.DecodedImage[dstStart] = c;
+
+ dstStart++;
+ idxSrc += Data.SurfaceByteDepth;
+ }
+ }
+
+ // Case 3:
+ ///////////////////////////////////////////////////////////////////////////////
+ //
+ // The color-conversion formulas come from the Colour Space Conversions FAQ:
+ // http://www.poynton.com/PDFs/coloureq.pdf
+ //
+ // RGB --> CMYK CMYK --> RGB
+ // --------------------------------------- --------------------------------------------
+ // Black = minimum(1-Red,1-Green,1-Blue) Red = 1-minimum(1,Cyan*(1-Black)+Black)
+ // Cyan = (1-Red-Black)/(1-Black) Green = 1-minimum(1,Magenta*(1-Black)+Black)
+ // Magenta = (1-Green-Black)/(1-Black) Blue = 1-minimum(1,Yellow*(1-Black)+Black)
+ // Yellow = (1-Blue-Black)/(1-Black)
+ //
+ ///////////////////////////////////////////////////////////////////////////////
+ private void SetPDNRowCmyk(int dstStart, int dstStops, int idxSrc)
+ {
+ var c = Data.DecodedImage[dstStart];
+ while (dstStart < dstStops)
+ {
+ // CMYK values are stored as complements, presumably to allow for some
+ // measure of compatibility with RGB-only applications.
+ var C = 255 - Data.ColorChannel0[idxSrc];
+ var M = 255 - Data.ColorChannel1[idxSrc];
+ var Y = 255 - Data.ColorChannel2[idxSrc];
+ var K = 255 - Data.ColorChannel3[idxSrc];
+
+ int R = 255 - Math.Min(255, C * (255 - K) / 255 + K);
+ int G = 255 - Math.Min(255, M * (255 - K) / 255 + K);
+ int B = 255 - Math.Min(255, Y * (255 - K) / 255 + K);
+
+ c.r = (byte)R;
+ c.g = (byte)G;
+ c.b = (byte)B;
+ Data.DecodedImage[dstStart] = c;
+
+ dstStart++;
+ idxSrc += Data.SurfaceByteDepth;
+ }
+ }
+
+ // Case 4:
+ private void SetPDNRowBitmap(int dstStart, int dstStops, int idxSrc)
+ {
+ var c = Data.DecodedImage[dstStart];
+ while (dstStart < dstStops)
+ {
+ byte mask = (byte)(0x80 >> (idxSrc % 8));
+ byte bwValue = (byte)(Data.ColorChannel0[idxSrc / 8] & mask);
+ bwValue = (bwValue == 0) ? (byte)255 : (byte)0;
+
+ c.r = bwValue;
+ c.g = bwValue;
+ c.b = bwValue;
+ Data.DecodedImage[dstStart] = c;
+
+ dstStart++;
+ idxSrc += Data.SurfaceByteDepth;
+ }
+ }
+
+ // Case 5:
+ private void SetPDNRowGrayscale(int dstStart, int dstStops, int idxSrc)
+ {
+ var c = Data.DecodedImage[dstStart];
+ while (dstStart < dstStops)
+ {
+
+ c.r = Data.ColorChannel0[idxSrc];
+ c.g = Data.ColorChannel0[idxSrc];
+ c.b = Data.ColorChannel0[idxSrc];
+ Data.DecodedImage[dstStart] = c;
+
+ dstStart++;
+ idxSrc += Data.SurfaceByteDepth;
+ }
+ }
+
+ // Case 6:
+ private void SetPDNRowIndexed(int dstStart, int dstStops, int idxSrc)
+ {
+ var c = Data.DecodedImage[dstStart];
+ int index = (int)Data.ColorChannel0[idxSrc];
+ while (dstStart < dstStops)
+ {
+ c.r = Data.ColorModeData[index];
+ c.g = Data.ColorModeData[index + 256];
+ c.b = Data.ColorModeData[index + 2 * 256];
+ Data.DecodedImage[dstStart] = c;
+
+ dstStart++;
+ idxSrc += Data.SurfaceByteDepth;
+ }
+ }
+
+ // Case 7:
+ private void SetPDNRowLab(int dstStart, int dstStops, int idxSrc)
+ {
+ var c = Data.DecodedImage[dstStart];
+ while (dstStart < dstStops)
+ {
+ double exL, exA, exB;
+ exL = (double)Data.ColorChannel0[idxSrc];
+ exA = (double)Data.ColorChannel1[idxSrc];
+ exB = (double)Data.ColorChannel2[idxSrc];
+
+ int L = (int)(exL / 2.55);
+ int a = (int)(exA - 127.5);
+ int b = (int)(exB - 127.5);
+
+ // First, convert from Lab to XYZ.
+ // Standards used Observer = 2, Illuminant = D65
+
+ const double ref_X = 95.047;
+ const double ref_Y = 100.000;
+ const double ref_Z = 108.883;
+
+ double var_Y = ((double)L + 16.0) / 116.0;
+ double var_X = (double)a / 500.0 + var_Y;
+ double var_Z = var_Y - (double)b / 200.0;
+
+ double var_X3 = var_X * var_X * var_X;
+ double var_Y3 = var_Y * var_Y * var_Y;
+ double var_Z3 = var_Z * var_Z * var_Z;
+
+ if (var_Y3 > 0.008856)
+ var_Y = var_Y3;
+ else
+ var_Y = (var_Y - 16 / 116) / 7.787;
+
+ if (var_X3 > 0.008856)
+ var_X = var_X3;
+ else
+ var_X = (var_X - 16 / 116) / 7.787;
+
+ if (var_Z3 > 0.008856)
+ var_Z = var_Z3;
+ else
+ var_Z = (var_Z - 16 / 116) / 7.787;
+
+ double X = ref_X * var_X;
+ double Y = ref_Y * var_Y;
+ double Z = ref_Z * var_Z;
+
+ // Then, convert from XYZ to RGB.
+ // Standards used Observer = 2, Illuminant = D65
+ // ref_X = 95.047, ref_Y = 100.000, ref_Z = 108.883
+
+ double var_R = X * 0.032406 + Y * (-0.015372) + Z * (-0.004986);
+ double var_G = X * (-0.009689) + Y * 0.018758 + Z * 0.000415;
+ double var_B = X * 0.000557 + Y * (-0.002040) + Z * 0.010570;
+
+ if (var_R > 0.0031308)
+ var_R = 1.055 * (Math.Pow(var_R, 1 / 2.4)) - 0.055;
+ else
+ var_R = 12.92 * var_R;
+
+ if (var_G > 0.0031308)
+ var_G = 1.055 * (Math.Pow(var_G, 1 / 2.4)) - 0.055;
+ else
+ var_G = 12.92 * var_G;
+
+ if (var_B > 0.0031308)
+ var_B = 1.055 * (Math.Pow(var_B, 1 / 2.4)) - 0.055;
+ else
+ var_B = 12.92 * var_B;
+
+ int nRed = (int)(var_R * 256.0);
+ int nGreen = (int)(var_G * 256.0);
+ int nBlue = (int)(var_B * 256.0);
+
+ if (nRed < 0)
+ nRed = 0;
+ else if (nRed > 255)
+ nRed = 255;
+ if (nGreen < 0)
+ nGreen = 0;
+ else if (nGreen > 255)
+ nGreen = 255;
+ if (nBlue < 0)
+ nBlue = 0;
+ else if (nBlue > 255)
+ nBlue = 255;
+
+ c.r = (byte)nRed;
+ c.g = (byte)nGreen;
+ c.b = (byte)nBlue;
+ Data.DecodedImage[dstStart] = c;
+
+ dstStart++;
+ idxSrc += Data.SurfaceByteDepth;
+ }
+ }
+ }
+
+ #endregion
+
+ #region AlphaDecodeJob
+
+ internal struct PDNAlphaMaskData
+ {
+ // Inputs.
+ public PDNWrapper.Rectangle Rect;
+ public PDNWrapper.Rectangle LayerRect;
+ public PDNWrapper.Rectangle ClippedRect;
+ public int SurfaceWidth;
+ public int SurfaceHeight;
+ public int SurfaceByteDepth;
+
+ public int HasAlphaChannel;
+ public int HasUserAlphaMask;
+ public int UserMaskInvertOnBlend;
+ public PDNWrapper.Rectangle UserMaskRect;
+ public PDNWrapper.Rectangle UserMaskContextRect;
+ public int HasLayerAlphaMask;
+ public int LayerMaskInvertOnBlend;
+ public PDNWrapper.Rectangle LayerMaskRect;
+ public PDNWrapper.Rectangle LayerMaskContextRect;
+
+ [NativeDisableParallelForRestriction]
+ [ReadOnly]
+ [DeallocateOnJobCompletion]
+ public NativeArray AlphaChannel0;
+
+ [NativeDisableParallelForRestriction]
+ [ReadOnly]
+ public NativeArray UserMask;
+
+ [DeallocateOnJobCompletion]
+ [NativeDisableParallelForRestriction]
+ public NativeArray UserAlphaMask;
+
+ [DeallocateOnJobCompletion]
+ [NativeDisableParallelForRestriction]
+ public NativeArray UserAlphaMaskEmpty;
+
+ [NativeDisableParallelForRestriction]
+ [ReadOnly]
+ public NativeArray LayerMask;
+
+ [DeallocateOnJobCompletion]
+ [NativeDisableParallelForRestriction]
+ public NativeArray LayerAlphaMask;
+
+ [DeallocateOnJobCompletion]
+ [NativeDisableParallelForRestriction]
+ public NativeArray LayerAlphaMaskEmpty;
+
+ // Outputs
+ [NativeDisableParallelForRestriction]
+ public NativeArray DecodedImage;
+
+ // Colors.
+ public byte UserMaskBackgroundColor;
+ public byte LayerMaskBackgroundColor;
+ }
+
+ internal struct PDNAlphaMaskJob : IJob
+ {
+
+ public PDNAlphaMaskData Data;
+
+ public void Execute()
+ {
+
+ for (int idx = Data.Rect.Top; idx < Data.Rect.Bottom; idx++)
+ {
+ // Calculate index into ImageData source from row and column.
+ int idxSrcPixel = (idx - Data.LayerRect.Top) * Data.LayerRect.Width + (Data.Rect.Left - Data.LayerRect.Left);
+ int idxSrcBytes = idxSrcPixel * Data.SurfaceByteDepth;
+
+ // Calculate pointers to destination Surface.
+ var idxDstStart = idx * Data.SurfaceWidth + Data.ClippedRect.Left;
+ var idxDstStops = idx * Data.SurfaceWidth + Data.ClippedRect.Right;
+
+ // For 16-bit images, take the higher-order byte from the image data, which is now in little-endian order.
+ if (Data.SurfaceByteDepth == 2)
+ {
+ idxSrcBytes++;
+ }
+
+ SetPDNAlphaRow(idxDstStart, idxDstStops, idxSrcBytes);
+ if (0 != Data.HasLayerAlphaMask)
+ {
+ GetMaskAlphaRow(idx, Data.LayerAlphaMask, Data.LayerAlphaMaskEmpty, Data.LayerMask, Data.LayerMaskInvertOnBlend, Data.LayerMaskBackgroundColor, Data.LayerMaskContextRect, Data.LayerMaskRect);
+ }
+ if (0 != Data.HasUserAlphaMask)
+ {
+ GetMaskAlphaRow(idx, Data.UserAlphaMask, Data.UserAlphaMaskEmpty, Data.UserMask, Data.UserMaskInvertOnBlend, Data.UserMaskBackgroundColor, Data.UserMaskContextRect, Data.UserMaskRect);
+ }
+ ApplyPDNMask(idxDstStart, idxDstStops);
+
+ }
+ }
+
+ private void SetPDNAlphaRow(int dstStart, int dstStops, int idxSrc)
+ {
+ // Set alpha to fully-opaque if there is no alpha channel
+ if (0 == Data.HasAlphaChannel)
+ {
+ while (dstStart < dstStops)
+ {
+ var c = Data.DecodedImage[dstStart];
+ c.a = 255;
+ Data.DecodedImage[dstStart] = c;
+ dstStart++;
+ }
+ }
+ // Set the alpha channel data
+ else
+ {
+ NativeArray srcAlphaChannel = Data.AlphaChannel0.Reinterpret(1);
+ {
+ while (dstStart < dstStops)
+ {
+ var c = Data.DecodedImage[dstStart];
+ c.a = (Data.SurfaceByteDepth < 4) ? Data.AlphaChannel0[idxSrc] : ImageDecoderPdn.RGBByteFromHDRFloat(srcAlphaChannel[idxSrc / 4]);
+
+ Data.DecodedImage[dstStart] = c;
+ dstStart++;
+ idxSrc += Data.SurfaceByteDepth;
+ }
+ }
+ }
+ }
+
+ private void ApplyPDNMask(int dstStart, int dstStops)
+ {
+ // Do nothing if there are no masks
+ if (0 == Data.HasLayerAlphaMask && 0 == Data.HasUserAlphaMask)
+ {
+ return;
+ }
+
+ // Apply one mask
+ else if (0 == Data.HasLayerAlphaMask || 0 == Data.HasUserAlphaMask)
+ {
+ var maskAlpha = (0 == Data.HasLayerAlphaMask) ? Data.UserAlphaMask : Data.LayerAlphaMask;
+ var maskStart = 0;
+ {
+ var c = Data.DecodedImage[dstStart];
+ while (dstStart < dstStops)
+ {
+ c.a = (byte)(Data.DecodedImage[dstStart].a * maskAlpha[maskStart] / 255);
+ Data.DecodedImage[dstStart] = c;
+ dstStart++;
+ maskStart++;
+ }
+ }
+ }
+ // Apply both masks in one pass, to minimize rounding error
+ else
+ {
+ var maskStart = 0;
+ var c = Data.DecodedImage[dstStart];
+ {
+ while (dstStart < dstStops)
+ {
+ var alphaFactor = (Data.LayerAlphaMask[maskStart]) * (Data.UserAlphaMask[maskStart]);
+ c.a = (byte)(Data.DecodedImage[dstStart].a * alphaFactor / 65025);
+ Data.DecodedImage[dstStart] = c;
+
+ dstStart++;
+ maskStart++;
+ }
+ }
+ }
+ }
+
+ private void DecodeMaskAlphaRow32(NativeArray Alpha, int dstStart, int dstStops, NativeArray Mask, int maskStart)
+ {
+ NativeArray floatArray = Mask.Reinterpret(1);
+
+ while (dstStart < dstStops)
+ {
+ Alpha[dstStart] = ImageDecoderPdn.RGBByteFromHDRFloat(floatArray[maskStart / 4]);
+
+ dstStart++;
+ maskStart += 4;
+ }
+ }
+
+ private void DecodeMaskAlphaRow(NativeArray Alpha, int dstStart, int dstStops, NativeArray Mask, int maskStart, int byteDepth)
+ {
+ while (dstStart < dstStops)
+ {
+ Alpha[dstStart] = Mask[maskStart];
+
+ dstStart++;
+ maskStart += byteDepth;
+ }
+ }
+
+ private unsafe void GetMaskAlphaRow(int idxSrc, NativeArray alphaBuffer, NativeArray