void UpdatePreviewTexture(TextureRecipe targetRecipe, Texture2D previewTex)
        {
            if (!refreshPreviewTexture)
            {
                return;
            }

            refreshPreviewTexture = false;

            GeneratorFactory.createMappings();
            RecipeBuildPreProcess.bakeSubAssets(targetRecipe);

            TextureRecipeRenderer renderer = new TextureRecipeRenderer(targetRecipe);

            renderer.renderSetup(previewTex);
            renderer.renderRecipeInternal();

            previewTex.ReadPixels(new Rect(0, 0, previewTex.width, previewTex.height), 0, 0);
            previewTex.Apply();

            RenderTexture.active = null;

            renderer.renderTeardown();
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            TextureRecipe targetRecipe  = (TextureRecipe)target;
            var           texWidthProp  = serializedObject.FindProperty("TextureWidth");
            var           texHeightProp = serializedObject.FindProperty("TextureHeight");

            texWidthProp.intValue  = EditorGUILayout.IntField("Width", texWidthProp.intValue);
            texHeightProp.intValue = EditorGUILayout.IntField("Height", texHeightProp.intValue);
            serializedObject.ApplyModifiedProperties();

            if (GUILayout.Button("Bake"))
            {
                GeneratorFactory.createMappings();
                RecipeBuildPreProcess.bakeSubAssets(targetRecipe);

                TextureRecipeRenderer renderer = new TextureRecipeRenderer(targetRecipe);
                renderer.renderSetup();
                renderer.renderRecipeInternal();

                TextureWriter.WriteRenderBufferToTextureFile(targetRecipe.TextureWidth, targetRecipe.TextureHeight, targetRecipe);
                RenderTexture.active = null;

                renderer.renderTeardown();
            }

            reorderableList.DoLayoutList();

            int listIndex = reorderableList.index;

            var layerList = serializedObject.FindProperty("layerList");

            if (listIndex >= 0 && listIndex < layerList.arraySize)
            {
                var listItem = layerList.GetArrayElementAtIndex(listIndex);
                if (null != listItem.objectReferenceValue)
                {
                    if (subEditorType != listItem.objectReferenceValue.GetType())
                    {
                        subEditor = null;
                    }
                    EditorGUI.BeginChangeCheck();

                    ShaderLayerEditor.recipe = (TextureRecipe)target;
                    CreateCachedEditor(listItem.objectReferenceValue, null, ref subEditor);
                    subEditorType = listItem.objectReferenceValue.GetType();

                    subEditor.serializedObject.Update();
                    subEditor.OnInspectorGUI();
                    subEditor.serializedObject.ApplyModifiedProperties();

                    serializedObject.ApplyModifiedProperties();
                    if (EditorGUI.EndChangeCheck() && targetRecipe.autoRefresh)
                    {
                        //do we need this if we set dirty on the target every frame?
                        EditorUtility.SetDirty(listItem.objectReferenceValue);
                        refreshPreviewTexture = true;
                    }

                    if (ShaderLayerEditor.nodeEditor && ShaderLayerEditor.nodeEditor.refreshShader && targetRecipe.autoRefresh)
                    {
                        refreshPreviewTexture = true;
                        ShaderLayerEditor.nodeEditor.refreshShader = false;
                    }
                }
            }

            //We have to do this every frame otherwise changes to the child objects aren't reflected in the inspector when we Undo them
            //there is perhaps an issue with the order of operations
            EditorUtility.SetDirty(target);
        }