private void DrawPiskelEditorToolWindow(int id)
        {
            EditorGUI.BeginChangeCheck();
            var newIndex = EditorGUILayout.Popup(_selectedLayerIndex, _curveBindings.Select(i => i.propertyName).ToArray());

            if (EditorGUI.EndChangeCheck() && newIndex != _selectedLayerIndex)
            {
                InitializeFramesList();
            }

            _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
            _spritesListUi.DoLayoutList();
            EditorGUILayout.EndScrollView();

            EditorGUI.BeginDisabledGroup(!_hasListChanged);
            if (GUILayout.Button("Save changes"))
            {
                string savePath =
                    EditorUtility.SaveFilePanelInProject("Save Piskel animation", piskelTarget.name, "piskel", "Select where to save the current animation.");
                if (!string.IsNullOrEmpty(savePath))
                {
                    PiskelDocument document = PiskelDocument.FromAnimation(_animation);
                    File.WriteAllText(savePath, document.ToPiskelJson());
                    AssetDatabase.ImportAsset(savePath);
                    _hasListChanged = false;
                }
            }
            EditorGUI.EndDisabledGroup();

            GUILayout.FlexibleSpace();
        }
        private void WritePiskelOutput()
        {
            var outputWidth  = m_Settings.imageInputSettings.outputWidth;
            var outputHeight = m_Settings.imageInputSettings.outputHeight;

            var finalWidth = outputWidth * _renderedFrames.Count();

            if (finalWidth > SystemInfo.maxTextureSize)
            {
                Debug.Log("The output texture width is too large, try lowering the capture resolution or make the animation shorter");
                return;
            }

            Texture2D renderedFrame = new Texture2D(outputWidth * _currentFrame, outputHeight);

            for (var index = 0; index < _renderedFrames.Count; index++)
            {
                var pixels = _renderedFrames[index].GetPixels32();
                renderedFrame.SetPixels32(index * outputWidth, 0, outputWidth, outputHeight, pixels);
            }
            _renderedFrames.Clear();

            PiskelChunk[] chunks = new PiskelChunk[1];
            chunks[0] = new PiskelChunk();
            chunks[0].SetTexture(renderedFrame);
            chunks[0].layout = new PiskelChunk.IntArray[_currentFrame];
            for (int i = 0; i < _currentFrame; i++)
            {
                chunks[0].layout[i] = new PiskelChunk.IntArray()
                {
                    array = new[] { i }
                };
            }

            PiskelDocument piskelDocument = new PiskelDocument
            {
                name   = Path.GetFileNameWithoutExtension(settings.outputFile),
                width  = outputWidth,
                height = outputHeight,
                fps    = m_Settings.outputFrameRate,
                layers = new PiskelLayer[1]
            };

            piskelDocument.layers[0] = new PiskelLayer
            {
                chunks     = chunks,
                name       = "Layer0",
                frameCount = _currentFrame,
                opacity    = 1.0f
            };

            var jsonString = piskelDocument.ToPiskelJson();

            File.WriteAllText(settings.outputFile, jsonString);
            AssetDatabase.Refresh();
        }
        public override void OnImportAsset(AssetImportContext ctx)
        {
            var piskel = PiskelDocument.FromPiskelJson(File.ReadAllText(ctx.assetPath));

            // Creates the root first and save it as main asset.
            var go = new GameObject("root");

            ctx.AddObjectToAsset("root", go);
            ctx.SetMainObject(go);

            // Create a Clip
            var clip = new AnimationClip();

            clip.name      = piskel.name;
            clip.frameRate = piskel.fps;
            // Create clip settings to make it loop
            var settings = new AnimationClipSettings
            {
                loopTime = true
            };

            AnimationUtility.SetAnimationClipSettings(clip, settings);
            ctx.AddObjectToAsset("clip", clip);

            var animator = go.AddComponent <PiskelPlayer>();

            animator.clip = clip;

            for (var i = 0; i < piskel.layers.Length; i++)
            {
                GameObject layerObj;
                if (firstLayerIsRoot && i == 0)
                {
                    layerObj = go;
                }
                else
                {
                    layerObj = new GameObject(piskel.layers[i].name);
                    layerObj.transform.parent = go.transform;
                }

                var spriteRenderer = layerObj.AddComponent <SpriteRenderer>();
                spriteRenderer.sortingOrder = layerOrderingStartIndex + i;
                spriteRenderer.color        = new Color(1, 1, 1, piskel.layers[i].opacity);

                piskel.GenerateTexturesAndSpritesForLayer(i, out var textures, out var sprites, spriteSettings);
                foreach (var texture2D in textures)
                {
                    texture2D.hideFlags = HideFlags.HideInHierarchy;
                    ctx.AddObjectToAsset(texture2D.name, texture2D);
                }
                spriteRenderer.sprite = sprites.Length > 0 ? sprites[0] : null;
                var keys = new ObjectReferenceKeyframe[sprites.Length];
                for (var index = 0; index < sprites.Length; index++)
                {
                    var sprite = sprites[index];
                    ctx.AddObjectToAsset(sprite.name, sprite);
                    keys[index] = new ObjectReferenceKeyframe()
                    {
                        time = (1 / clip.frameRate) * index, value = sprite
                    };
                }

                var binding = new EditorCurveBinding
                {
                    path         = layerObj == go ? "" : layerObj.name,
                    type         = typeof(SpriteRenderer),
                    propertyName = "m_Sprite"
                };
                AnimationUtility.SetObjectReferenceCurve(clip, binding, keys);
            }
        }