/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Public

    public virtual void OnEnable()
    {
        myAsset    = target as HoudiniAsset;
        myUndoInfo = myAsset.prAssetUndoInfo;

        myParmChanges    = true;
        myUnbuiltChanges = false;
        myFocusChanged   = true;

        myHelpScrollPosition = new Vector2(0.0f, 0.0f);

        HoudiniHost.myRepaintDelegate     += this.refresh;
        HoudiniHost.myDeselectionDelegate += this.deselect;
        HoudiniHost.mySelectionTarget      = myAsset.gameObject;

        // If selection is a prefab build it ( parameters only ) to allow
        // editing of parameters. Only need to build once, the first time
        // it is selected.
        if (myAsset.isPrefab())
        {
            // Reloading prefab after play mode change since OnEnable
            // never gets called for prefab. This only needs to be done
            // if prefab has already been built.
            if (myAsset.prReloadPrefabOnPlaymodeChange &&
                HoudiniHost.isAssetValid(myAsset.prAssetId, myAsset.prAssetValidationId))
            {
                myAsset.prReloadPrefabOnPlaymodeChange = false;
                myAsset.build(false,                    // reload_asset
                              false,                    // unload_asset_first
                              true,                     // serializatin_recovery_only
                              false,                    // force_reconnect
                              false,                    // is_duplication
                              false,                    // cook_downstream_assets
                              false                     // use_delay_for_progress_bar
                              );
            }
            else if (
                myAsset.prAssetId != myAsset.prBackupAssetId ||
                !HoudiniHost.isAssetValid(myAsset.prAssetId, myAsset.prAssetValidationId))
            {
                myAsset.prAssetId = -1;
                myAsset.build(true,                     // reload_asset
                              true,                     // unload_asset_first
                              true,                     // serializatin_recovery_only
                              false,                    // force_reconnect
                              false,                    // is_duplication
                              false,                    // cook_downstream_assets
                              false                     // use_delay_for_progress_bar
                              );
                EditorUtility.SetDirty(myAsset);
            }
        }
    }
    public override void OnInspectorGUI()
    {
        bool gui_enable = GUI.enabled;

        // We can only build or do anything if we can link to our libraries.
#if !(UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || (UNITY_METRO && UNITY_EDITOR))
        HoudiniGUI.help(HoudiniConstants.HAPI_UNSUPPORTED_PLATFORM_MSG, MessageType.Info);
        GUI.enabled = false;
#else
        if (!HoudiniHost.isInstallationOk())
        {
            HoudiniGUI.help(HoudiniHost.getMissingEngineInstallHelpString(), MessageType.Info);
            GUI.enabled = false;
        }
#endif // !( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) )

        try
        {
            myDelayBuild  = false;
            myParmChanges = false;

            ///////////////////////////////////////////////////////////////////////
            // Draw Game Object Controls

            if (HoudiniHost.isAssetValid(myAsset.prAssetId, myAsset.prAssetValidationId) &&
                (myAsset.prTransformInputCount > 0 || myAsset.prGeoInputCount > 0) &&
                myAsset.prAssetSubType != HAPI_AssetSubType.HAPI_ASSETSUBTYPE_CURVE &&
                !myAsset.isPrefab())
            {
                myAsset.prShowInputControls = HoudiniGUI.foldout("Inputs", myAsset.prShowInputControls, true);

                if (myAsset.prShowInputControls)
                {
                    if (myAsset.prHAPIAssetType == HAPI_AssetType.HAPI_ASSETTYPE_OBJ)
                    {
                        for (int ii = 0; ii < myAsset.prTransformInputCount; ++ii)
                        {
                            myParmChanges |= setTransformInput(ii);
                        }
                    }

                    if (myAsset.prUpStreamGeoObjects == null || myAsset.prUpStreamGeoAssets == null ||
                        myAsset.prUpStreamGeoObjects.Count <= 0 || myAsset.prUpStreamGeoAssets.Count <= 0)
                    {
                        return;
                    }

                    for (int input_index = 0; input_index < myAsset.prGeoInputCount; ++input_index)
                    {
                        bool join_last            = false;
                        bool no_label_toggle_last = true;

                        HoudiniGUIParm geo_input = new HoudiniGUIParm(
                            "geo_input_" + input_index, myAsset.prGeoInputNames[input_index]);
                        Object obj = (Object)myAsset.prUpStreamGeoObjects[input_index];
                        myParmChanges |= HoudiniGUI.objectField(
                            ref geo_input, ref obj, typeof(GameObject), ref join_last, ref no_label_toggle_last);

                        if (myParmChanges || !myAsset.isGeoInputValid(input_index))
                        {
                            if (!obj)
                            {
                                myAsset.removeGeoInput(input_index);
                                myAsset.buildClientSide();
                            }
                            else
                            {
                                GameObject new_obj = (GameObject)obj;
                                myAsset.prUpStreamGeoObjects[input_index] = new_obj;

                                // Select the asset component (if it exists).
                                HoudiniAsset asset = new_obj.GetComponent <HoudiniAsset>();

                                // If we're selecting a specific object to input than try and
                                // get the object id. Note that by getting the HAPI_ObjectControl
                                // component we also cover the geo and part controls because
                                // they all inherit from HAPI_ObjectControl. The user can therefore
                                // drag any gameObject under the asset into another asset's
                                // input and have it all work.
                                int object_index = 0;
                                HoudiniObjectControl obj_control = new_obj.GetComponent <HoudiniObjectControl>();
                                if (obj_control)
                                {
                                    object_index = obj_control.prObjectId;
                                    asset        = obj_control.prAsset;
                                }

                                if (asset == null)
                                {
                                    myAsset.addGeoAsGeoInput(new_obj, input_index);
                                    myAsset.buildClientSide();
                                }
                                else if (myAsset.prUpStreamGeoAssets[input_index] != asset)
                                {
                                    if (myAsset == asset)
                                    {
                                        Debug.LogError("Can't connect an asset to itself!");
                                    }
                                    else
                                    {
                                        myAsset.addAssetAsGeoInput(asset, object_index, input_index);
                                        myAsset.buildClientSide();
                                    }
                                }
                            }
                        }
                    }     // for
                }         // if
            }             // if

            // Draw Cook Log Pane
            myAsset.prShowCookLog = HoudiniGUI.foldout("Asset Cook Log", myAsset.prShowCookLog, true);
            if (myAsset.prShowCookLog)
            {
                drawCookLog();
            }
        }
        catch (HoudiniError e)
        {
            Debug.LogError(e.ToString());
        }

        GUI.enabled = gui_enable;
    }
    static void ReplacePrefab()
    {
        HoudiniAsset prefab_asset = prPrefabToReplace.GetComponent <HoudiniAsset>();

        if (prPrefabToReplace && prefab_asset)
        {
            foreach (GameObject obj in GameObject.FindObjectsOfType(typeof(GameObject)))
            {
                HoudiniAsset asset         = obj.GetComponent <HoudiniAsset>();
                GameObject   prefab_parent = PrefabUtility.GetPrefabParent(obj) as GameObject;
                if (asset && PrefabUtility.Equals(prefab_parent, prPrefabToReplace))
                {
                    // this is the asset the prefab is being created/changed from
                    if (asset.prAssetId == prefab_asset.prAssetId)
                    {
                        // If the prefab's backup id refers to a valid asset then this signifies the
                        // prefab is being changed due to an "Apply" from a prefab instance. We need
                        // to delete the prefab asset since we are re-creating the prefab.
                        bool is_applying_changes = HoudiniHost.isAssetValid(
                            prefab_asset.prBackupAssetId, prefab_asset.prBackupAssetValidationId);
                        if (is_applying_changes)
                        {
                            try
                            {
                                HoudiniHost.destroyAsset(prefab_asset.prBackupAssetId);
                            }
                            catch (HoudiniError error)
                            {
                                Debug.LogError("Asset failed to unload: " + error.ToString());
                            }

                            prefab_asset.reset();
                            prefab_asset.prParms.reset();
                        }

                        // replace prefab with original asset with all children game objects removed
                        HoudiniControl.destroyChildren(asset.transform);
                        GameObject new_prefab = PrefabUtility.ReplacePrefab(asset.gameObject,
                                                                            prPrefabToReplace,
                                                                            ReplacePrefabOptions.ConnectToPrefab) as GameObject;
                        HoudiniAsset new_prefab_asset = new_prefab.GetComponent <HoudiniAsset>();

                        // If applying changes to prefab from prefab instance we also need to retrieve
                        // all the overriden parameters on the prefab instance so that we can apply
                        // these changes properly to all the other instances. This must be done after
                        // prefab has been replaced.
                        if (is_applying_changes)
                        {
                            foreach (HAPI_ParmInfo parm_info in asset.prParms.prParms)
                            {
                                if (asset.prParms.isParmOverridden(parm_info.id))
                                {
                                    new_prefab_asset.prUpdatePrefabInstanceParmNames.Add(parm_info.name);
                                }
                            }
                        }

                        // Set asset id of prefab to -1 since it has not been built yet.
                        // Call SetDirty so changes to prefab will be saved to disk and
                        // OnEnable will be called on original asset so that it can be
                        // rebuilt in order to re-create its game objects.
                        new_prefab_asset.prAssetId           = -1;
                        new_prefab_asset.prAssetValidationId = -1;
                        EditorUtility.SetDirty(new_prefab_asset);

                        break;
                    }
                }
            }
        }
    }