using System; using System.Collections.Generic; using PDNWrapper; using UnityEngine; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; namespace UnityEditor.U2D.PSD { class ExtractLayerTask { struct ConvertBufferJob : IJobParallelFor { [ReadOnly] [DeallocateOnJobCompletion] public NativeArray original; [ReadOnly] [DeallocateOnJobCompletion] public NativeArray width; [ReadOnly] [DeallocateOnJobCompletion] public NativeArray height; [DeallocateOnJobCompletion] public NativeArray output; public unsafe void Execute(int index) { Color32* originalColor = (Color32*)original[index]; Color32* otuputColor = (Color32*)output[index]; for (int i = 0; i < height[index]; ++i) { int originalYOffset = i * width[index]; int outputYOffset = (height[index] - i - 1) * width[index]; for (int j = 0; j < width[index]; ++j) { otuputColor[j + outputYOffset] = originalColor[j + originalYOffset]; } } } } public static unsafe void Execute(List extractedLayer, List layers, bool importHiddenLayer) { UnityEngine.Profiling.Profiler.BeginSample("ExtractLayer_PrepareJob"); var tempExtractLayer = new List(); int layerWithBuffer = ExtractLayer(tempExtractLayer, layers, importHiddenLayer); if (layerWithBuffer == 0) return; var job = new ConvertBufferJob(); job.original = new NativeArray(layerWithBuffer, Allocator.TempJob); job.output = new NativeArray(layerWithBuffer, Allocator.TempJob); job.width = new NativeArray(layerWithBuffer, Allocator.TempJob); job.height = new NativeArray(layerWithBuffer, Allocator.TempJob); for (int i = 0, jobIndex = 0; i < tempExtractLayer.Count; ++i) { var el = tempExtractLayer[i]; if (el.texture.Length == 0 || el.width == 0 || el.height == 0) { extractedLayer.Add(el); continue; } job.original[jobIndex] = new IntPtr(el.texture.GetUnsafeReadOnlyPtr()); el.texture = new NativeArray(el.texture.Length, Allocator.Persistent); extractedLayer.Add(el); job.output[jobIndex] = new IntPtr(el.texture.GetUnsafePtr()); job.width[jobIndex] = el.width; job.height[jobIndex] = el.height; ++jobIndex; } var jobsPerThread = layerWithBuffer / (SystemInfo.processorCount == 0 ? 8 : SystemInfo.processorCount); jobsPerThread = Mathf.Max(jobsPerThread, 1); var handle = job.Schedule(layerWithBuffer, jobsPerThread); UnityEngine.Profiling.Profiler.EndSample(); handle.Complete(); } static int ExtractLayer(List extractedLayer, List layers, bool importHiddenLayer) { // parent is the previous element in extracedLayer int parentGroupIndex = extractedLayer.Count - 1; int actualLayerWithBuffer = 0; foreach (var l in layers) { if (!importHiddenLayer && !l.Visible) continue; if (l.IsGroup) { extractedLayer.Add(new PSDLayer(new NativeArray(0, Allocator.Persistent), parentGroupIndex, l.IsGroup, l.Name, 0, 0, l.LayerID)); actualLayerWithBuffer += ExtractLayer(extractedLayer, l.ChildLayer, importHiddenLayer); } else { extractedLayer.Add(new PSDLayer(l.Surface.color, parentGroupIndex, l.IsGroup, l.Name, l.Surface.width, l.Surface.height, l.LayerID)); ++actualLayerWithBuffer; } } return actualLayerWithBuffer; } } }