/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Private

    private void generateAssetBakeControls()
    {
        // Start Time
        {
            float value   = myAsset.prBakeStartTime;
            bool  changed = HoudiniGUI.floatField(
                "bake_start_time", "Start Time", ref value,
                myUndoInfo, ref myUndoInfo.bakeStartTime);

            if (changed)
            {
                myAsset.prBakeStartTime = value;
            }
        }

        // End Time
        {
            float value   = myAsset.prBakeEndTime;
            bool  changed = HoudiniGUI.floatField(
                "bake_end_time", "End Time", ref value,
                myUndoInfo, ref myUndoInfo.bakeEndTime);
            if (changed)
            {
                myAsset.prBakeEndTime = value;
            }
        }

        // Samples per second
        {
            int  value   = myAsset.prBakeSamplesPerSecond;
            bool changed = HoudiniGUI.intField(
                "bake_samples_per_second", "Samples Per Second", ref value,
                1, 120, myUndoInfo, ref myUndoInfo.bakeSamplesPerSecond);

            if (changed)
            {
                myAsset.prBakeSamplesPerSecond = value;
            }
        }

        if (GUILayout.Button("Bake Animation"))
        {
            HoudiniProgressBar progress_bar = new HoudiniProgressBar();
            progress_bar.prUseDelay = false;
            myAsset.bakeAnimations(
                myAsset.prBakeStartTime,
                myAsset.prBakeEndTime,
                myAsset.prBakeSamplesPerSecond,
                myAsset.gameObject,
                progress_bar);
            progress_bar.clearProgressBar();
        }
    }
    protected bool generateAssetControl(int index, ref bool join_last, ref bool no_label_toggle_last)
    {
        if (myParms.prParms == null)
        {
            return(false);
        }

        if (myParms.prParms[index].invisible)
        {
            return(false);
        }

        bool changed = false;

        HAPI_ParmInfo[]      parms        = myParms.prParms;
        HAPI_ParmInfo        parm         = parms[index];
        HAPI_ParmInfoStrings parm_strings = myParms.prParmInfoStrings[index];

        int[]   parm_int_values   = myParms.prParmIntValues;
        float[] parm_float_values = myParms.prParmFloatValues;

        HoudiniGUIParm gui_parm = new HoudiniGUIParm(parm, parm_strings);

        ///////////////////////////////////////////////////////////////////////
        // Integer Parameter
        if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_MULTIPARMLIST)
        {
            changed = HoudiniGUI.multiparmField(
                ref gui_parm, ref myDelayBuild, ref parm_int_values,
                ref join_last, ref no_label_toggle_last);
        }
        else if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_INT)
        {
            if (parm.choiceCount > 0 && parm.choiceIndex >= 0)
            {
                // Draw popup (menu) field.
                List <string> labels = new List <string>();
                List <int>    values = new List <int>();

                // Go through our choices.
                for (int i = 0; i < parm.choiceCount; ++i)
                {
                    if (myParms.prParmChoiceLists[parm.choiceIndex + i].parentParmId != parm.id)
                    {
                        Debug.LogError("Parm choice parent parm id ("
                                       + myParms.prParmChoiceLists[parm.choiceIndex + i].parentParmId
                                       + ") not matching current parm id (" + parm.id + ")!\n"
                                       + "Choice index: " + (parm.choiceIndex + i) + ", "
                                       + "Choice count: " + parm.choiceCount);
                    }

                    labels.Add(myParms.prParmChoiceInfoStrings[parm.choiceIndex + i].label);
                    values.Add(i);
                }

                changed = HoudiniGUI.dropdown(
                    ref gui_parm, ref parm_int_values,
                    labels.ToArray(), values.ToArray(),
                    ref join_last, ref no_label_toggle_last,
                    null, ref parm_int_values);
            }
            else
            {
                changed = HoudiniGUI.intField(
                    ref gui_parm, ref myDelayBuild, ref parm_int_values,
                    ref join_last, ref no_label_toggle_last, null,
                    ref parm_int_values);
            }     // if parm.choiceCount
        }         // if parm.type is INT
        ///////////////////////////////////////////////////////////////////////
        // Float Parameter
        else if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_FLOAT)
        {
            changed = HoudiniGUI.floatField(
                ref gui_parm, ref myDelayBuild, ref parm_float_values,
                ref join_last, ref no_label_toggle_last, null,
                ref parm_float_values);
        }         // if parm.type is FLOAT
        ///////////////////////////////////////////////////////////////////////
        // String Parameter
        else if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_STRING)
        {
            if (parm.choiceCount > 0 && parm.choiceIndex >= 0)
            {
                // Draw popup (menu) field.
                List <string> labels = new List <string>();
                List <string> values = new List <string>();

                // Go through our choices.
                for (int i = 0; i < parm.choiceCount; ++i)
                {
                    if (myParms.prParmChoiceLists[parm.choiceIndex + i].parentParmId != parm.id)
                    {
                        Debug.LogError(
                            "Parm choice parent parm id ("
                            + myParms.prParmChoiceLists[parm.choiceIndex + i].parentParmId
                            + ") not matching current parm id (" + parm.id + ")!\n"
                            + "Choice index: " + (parm.choiceIndex + i) + ", "
                            + "Choice count: " + parm.choiceCount);
                    }

                    labels.Add(myParms.prParmChoiceInfoStrings[parm.choiceIndex + i].label);
                    values.Add(myParms.prParmChoiceInfoStrings[parm.choiceIndex + i].value);
                }

                string[] values_temp = myParms.getParmStrings(parm);
                gui_parm.valuesIndex = 0;                 // Since we're piping a de-handled temp array.

                changed = HoudiniGUI.dropdown(
                    ref gui_parm, ref values_temp,
                    labels.ToArray(), values.ToArray(),
                    ref join_last, ref no_label_toggle_last,
                    null, ref values_temp);

                if (changed)
                {
                    myParms.setParmStrings(parm, values_temp);
                }
            }
            else
            {
                string[] values = myParms.getParmStrings(parm);

                // The given string array is only for this parm so we need to set the values index to 0.
                gui_parm.valuesIndex = 0;

                changed = HoudiniGUI.stringField(
                    ref gui_parm, ref myDelayBuild, ref values,
                    ref join_last, ref no_label_toggle_last, null,
                    ref values);

                // Set the to be changed strings into the cache
                if (changed)
                {
                    myParms.setParmStrings(parm, values);
                }
            }
        }
        ///////////////////////////////////////////////////////////////////////
        // File Path Field
        else if (parm.isPath())
        {
            string[] path = myParms.getParmStrings(parm);

            if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_PATH_FILE_GEO)
            {
                gui_parm.label += " (geo)";
            }
            else if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_PATH_FILE_IMAGE)
            {
                gui_parm.label += " (image)";
            }

            // Asset ID might still be invalid here so don't fail if it is.
            // It is invalid if the asset didn't cook yet after a scene load.
            try
            {
                string file_pattern = parm.typeInfo;
                if (file_pattern != "")
                {
                    gui_parm.label += " (" + file_pattern + ")";
                }
            }
            catch {}

            HAPI_Permissions permissions = parm.permissions;
            if (permissions == HAPI_Permissions.HAPI_PERMISSIONS_READ_ONLY)
            {
                gui_parm.label += " (read-only)";
                changed         = HoudiniGUI.fileOpenField(
                    ref gui_parm, ref myDelayBuild, ref path[0],
                    ref join_last, ref no_label_toggle_last);
            }
            else
            {
                if (permissions == HAPI_Permissions.HAPI_PERMISSIONS_WRITE_ONLY)
                {
                    gui_parm.label += " (write-only)";
                }

                changed = HoudiniGUI.fileSaveField(
                    ref gui_parm, ref myDelayBuild, ref path[0],
                    ref join_last, ref no_label_toggle_last);
            }

            if (changed)
            {
                myParms.setParmStrings(parm, path);
            }
        }
        ///////////////////////////////////////////////////////////////////////
        // Node Path Field
        else if (parm.isNode())
        {
            // Asset ID might still be invalid here so don't fail if it is.
            // It is invalid if the asset didn't cook yet after a scene load.
            try
            {
                string op_filter = parm.typeInfo;
                if (op_filter != "")
                {
                    gui_parm.label += " (" + op_filter + ")";
                }
            }
            catch {}

            HAPI_ParmInput     parm_input  = myParms.prParmInputs[parm.id];
            UnityEngine.Object temp_object = parm_input.inputObject;
            GameObject         undo_object = null;
            changed = HoudiniGUI.objectField(
                ref gui_parm, ref temp_object, typeof(GameObject),
                ref join_last, ref no_label_toggle_last, null, ref undo_object);

            if (changed)
            {
                parm_input.newInputObject   = (GameObject)temp_object;
                myParms.prParmInputs[index] = parm_input;
            }
        }
        ///////////////////////////////////////////////////////////////////////
        // Toggle Parameter
        else if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_TOGGLE)
        {
            changed = HoudiniGUI.toggle(
                ref gui_parm, ref parm_int_values,
                ref join_last, ref no_label_toggle_last,
                null, ref parm_int_values);
        }
        ///////////////////////////////////////////////////////////////////////
        // Color Parameter
        else if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_COLOR)
        {
            changed = HoudiniGUI.colourField(
                ref gui_parm, ref myDelayBuild, ref parm_float_values,
                ref join_last, ref no_label_toggle_last, null,
                ref parm_float_values);
        }
        ///////////////////////////////////////////////////////////////////////
        // Button Parameter
        else if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_BUTTON)
        {
            if (parm.choiceCount > 0 && parm.choiceIndex >= 0)
            {
                // Draw popup (menu) field.
                List <string> labels = new List <string>();
                List <int>    values = new List <int>();

                // Go through our choices.
                for (int i = 0; i < parm.choiceCount; ++i)
                {
                    if (myParms.prParmChoiceLists[parm.choiceIndex + i].parentParmId != parm.id)
                    {
                        Debug.LogError(
                            "Parm choice parent parm id ("
                            + myParms.prParmChoiceLists[parm.choiceIndex + i].parentParmId
                            + ") not matching current parm id (" + parm.id + ")!\n"
                            + "Choice index: " + (parm.choiceIndex + i) + ", "
                            + "Choice count: " + parm.choiceCount);
                    }

                    labels.Add(myParms.prParmChoiceInfoStrings[parm.choiceIndex + i].label);
                    values.Add(i);
                }

                changed = HoudiniGUI.dropdown(
                    ref gui_parm, ref parm_int_values,
                    labels.ToArray(), values.ToArray(),
                    ref join_last, ref no_label_toggle_last,
                    null, ref parm_int_values);
            }
            else
            {
                changed = HoudiniGUI.button(ref gui_parm, ref join_last, ref no_label_toggle_last);
            }
        }
        ///////////////////////////////////////////////////////////////////////
        // Label
        else if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_LABEL)
        {
            HoudiniGUI.label(ref gui_parm, ref join_last, ref no_label_toggle_last);
        }
        ///////////////////////////////////////////////////////////////////////
        // Separator
        else if (parm.type == HAPI_ParmType.HAPI_PARMTYPE_SEPARATOR)
        {
            HoudiniGUI.separator();
        }

        if (myAsset.hasProgressBarBeenUsed() && parm.id == myParms.prLastChangedParmId)
        {
            // TODO: Set the focus back to this control since the progress bar would have stolen it.
        }


        if (changed)
        {
            myParms.prLastChangedParmId = parm.id;
        }

        return(changed);
    }
    private void generateMaterialSettings()
    {
        if (GUILayout.Button("Re-Render"))
        {
            HoudiniAssetUtility.reApplyMaterials(myAsset);
        }

        // Material Shader Type
        {
            HAPI_ShaderType   value   = myAsset.prMaterialShaderType;
            bool              is_bold = myParentPrefabAsset && myParentPrefabAsset.prMaterialShaderType != value;
            string[]          labels  = { "OpenGL", "Houdini Mantra Renderer" };
            HAPI_ShaderType[] values  = { HAPI_ShaderType.HAPI_SHADER_OPENGL, HAPI_ShaderType.HAPI_SHADER_MANTRA };
            bool              changed = HoudiniGUI.dropdown(
                "material_renderer", "Material Renderer", ref value,
                is_bold, labels, values, myUndoInfo,
                ref myUndoInfo.materialShaderType);
            if (changed)
            {
                myAsset.prMaterialShaderType = (HAPI_ShaderType)value;
                HoudiniAssetUtility.reApplyMaterials(myAsset);
            }
        }

        // Render Resolution
        {
            bool  delay_build = false;
            int[] values      = new int[2];
            values[0] = (int)myAsset.prRenderResolution[0];
            values[1] = (int)myAsset.prRenderResolution[1];
            int[] undo_values = new int[2];
            undo_values[0] = (int)myUndoInfo.renderResolution[0];
            undo_values[1] = (int)myUndoInfo.renderResolution[1];
            HoudiniGUIParm gui_parm = new HoudiniGUIParm("render_resolution", "Render Resolution", 2);

            gui_parm.isBold =
                myParentPrefabAsset &&
                (int)myParentPrefabAsset.prRenderResolution[0] != values[0] &&
                (int)myParentPrefabAsset.prRenderResolution[1] != values[1];

            bool changed = HoudiniGUI.intField(
                ref gui_parm, ref delay_build, ref values,
                myUndoInfo, ref undo_values);
            if (changed)
            {
                Vector2 new_resolution = new Vector2((float)values[0], (float)values[1]);
                myAsset.prRenderResolution  = new_resolution;
                myUndoInfo.renderResolution = new_resolution;
            }
        }

        // Show Vertex Colours
        createToggleForProperty(
            "show_only_vertex_colours", "Show Only Vertex Colors",
            "prShowOnlyVertexColours", ref myUndoInfo.showOnlyVertexColours,
            () => HoudiniAssetUtility.reApplyMaterials(myAsset));

        // Generate Tangents
        createToggleForProperty(
            "generate_tangents", "Generate Tangents", "prGenerateTangents",
            ref myUndoInfo.generateTangents,
            () => myAssetOTL.build(
                true,                   // reload_asset
                false,                  // unload_asset_first
                false,                  // serialization_recovery_only
                true,                   // force_reconnect
                false,                  // is_duplication
                myAsset.prCookingTriggersDownCooks,
                true                    // use_delay_for_progress_bar
                ), !HoudiniHost.isGenerateTangentsDefault());
    }