public void CopyInputValuesTo(HEU_SessionBase session, HEU_InputNode destInputNode) { destInputNode._pendingInputObjectType = _inputObjectType; if(destInputNode._inputObjectType == InputObjectType.HDA) { destInputNode.ResetConnectionForForceUpdate(session); } destInputNode._inputObjects.Clear(); foreach(HEU_InputObjectInfo inputObj in _inputObjects) { HEU_InputObjectInfo newInputObject = new HEU_InputObjectInfo(); inputObj.CopyTo(newInputObject); //newInputObject._syncdTransform = Matrix4x4.identity; destInputNode._inputObjects.Add(newInputObject); } destInputNode._inputAsset = _inputAsset; destInputNode._connectedInputAsset = _connectedInputAsset; destInputNode._keepWorldTransform = _keepWorldTransform; destInputNode._packGeometryBeforeMerging = _packGeometryBeforeMerging; }
public void CopyInputValuesTo(HEU_SessionBase session, HEU_InputNode destInputNode) { destInputNode._pendingInputObjectType = _inputObjectType; if (destInputNode._inputObjectType == InputObjectType.HDA) { destInputNode.ResetConnectionForForceUpdate(session); } destInputNode.RemoveAllInputEntries(); foreach (HEU_InputObjectInfo srcInputObject in _inputObjects) { HEU_InputObjectInfo newInputObject = new HEU_InputObjectInfo(); srcInputObject.CopyTo(newInputObject); destInputNode._inputObjects.Add(newInputObject); } foreach (HEU_InputHDAInfo srcInputInfo in _inputAssetInfos) { HEU_InputHDAInfo newInputInfo = new HEU_InputHDAInfo(); srcInputInfo.CopyTo(newInputInfo); destInputNode._inputAssetInfos.Add(newInputInfo); } destInputNode._keepWorldTransform = _keepWorldTransform; destInputNode._packGeometryBeforeMerging = _packGeometryBeforeMerging; }
/// <summary> /// Destroy all generated data. /// </summary> public void DestroyAllData() { HEU_PartData.DestroyParts(_parts); if (_inputNode != null) { HEU_SessionBase session = null; if (ParentAsset != null) { ParentAsset.RemoveInputNode(_inputNode); session = ParentAsset.GetAssetSession(false); } _inputNode.DestroyAllData(session); HEU_GeneralUtility.DestroyImmediate(_inputNode); _inputNode = null; } if (_geoCurve != null) { if (ParentAsset != null) { ParentAsset.RemoveCurve(_geoCurve); } _geoCurve.DestroyAllData(); HEU_GeneralUtility.DestroyImmediate(_geoCurve); _geoCurve = null; } DestroyVolumeCache(); }
/// <summary> /// Populate the UI cache for the given input node /// </summary> /// <param name="inputNode"></param> public static void PopulateCache(HEU_InputNode inputNode) { if (inputNode._uiCache == null) { inputNode._uiCache = new HEU_InputNodeUICache(); inputNode._uiCache._inputNodeSerializedObject = new SerializedObject(inputNode); inputNode._uiCache._inputObjectTypeProperty = HEU_EditorUtility.GetSerializedProperty(inputNode._uiCache._inputNodeSerializedObject, "_inputObjectType"); inputNode._uiCache._keepWorldTransformProperty = HEU_EditorUtility.GetSerializedProperty(inputNode._uiCache._inputNodeSerializedObject, "_keepWorldTransform"); inputNode._uiCache._packBeforeMergeProperty = HEU_EditorUtility.GetSerializedProperty(inputNode._uiCache._inputNodeSerializedObject, "_packGeometryBeforeMerging"); inputNode._uiCache._inputObjectsProperty = HEU_EditorUtility.GetSerializedProperty(inputNode._uiCache._inputNodeSerializedObject, "_inputObjects"); inputNode._uiCache._inputAssetProperty = HEU_EditorUtility.GetSerializedProperty(inputNode._uiCache._inputNodeSerializedObject, "_inputAsset"); int inputCount = inputNode._uiCache._inputObjectsProperty.arraySize; for (int i = 0; i < inputCount; ++i) { SerializedProperty inputObjectProperty = inputNode._uiCache._inputObjectsProperty.GetArrayElementAtIndex(i); HEU_InputNodeUICache.HEU_InputObjectUICache objectCache = new HEU_InputNodeUICache.HEU_InputObjectUICache(); objectCache._gameObjectProperty = inputObjectProperty.FindPropertyRelative("_gameObject"); objectCache._transformOffsetProperty = inputObjectProperty.FindPropertyRelative("_useTransformOffset"); objectCache._translateProperty = inputObjectProperty.FindPropertyRelative("_translateOffset"); objectCache._rotateProperty = inputObjectProperty.FindPropertyRelative("_rotateOffset"); objectCache._scaleProperty = inputObjectProperty.FindPropertyRelative("_scaleOffset"); inputNode._uiCache._inputObjectCache.Add(objectCache); } } }
// LOGIC ------------------------------------------------------------------------------------------------------ public static HEU_InputNode CreateSetupInput(HAPI_NodeId nodeID, int inputIndex, string inputName, InputNodeType inputNodeType, HEU_HoudiniAsset parentAsset) { HEU_InputNode newInput = ScriptableObject.CreateInstance<HEU_InputNode>(); newInput._nodeID = nodeID; newInput._inputIndex = inputIndex; newInput._inputName = inputName; newInput._inputNodeType = inputNodeType; newInput._parentAsset = parentAsset; newInput._requiresUpload = false; newInput._requiresCook = false; return newInput; }
/// <summary> /// Process the part at the given index, creating its data (geometry), /// and adding it to the list of parts. /// </summary> /// <param name="session"></param> /// <param name="partID"></param> /// <returns>A valid HEU_PartData if it has been successfully processed.</returns> private void ProcessPart(HEU_SessionBase session, int partID, ref HAPI_PartInfo partInfo, ref HEU_PartData partData) { HEU_HoudiniAsset parentAsset = ParentAsset; bool bResult = true; //Debug.LogFormat("Part: name={0}, id={1}, type={2}, instanced={3}, instance count={4}, instance part count={5}", HEU_SessionManager.GetString(partInfo.nameSH, session), partID, partInfo.type, partInfo.isInstanced, partInfo.instanceCount, partInfo.instancedPartCount); #if HEU_PROFILER_ON float processPartStartTime = Time.realtimeSinceStartup; #endif bool isPartEditable = IsIntermediateOrEditable(); bool isAttribInstancer = false; if (IsGeoInputType()) { // Setup for input node to accept inputs if (_inputNode == null) { string partName = HEU_SessionManager.GetString(partInfo.nameSH, session); _inputNode = HEU_InputNode.CreateSetupInput(GeoID, 0, partName, HEU_InputNode.InputNodeType.NODE, ParentAsset); if (_inputNode != null) { ParentAsset.AddInputNode(_inputNode); } } if (HEU_HAPIUtility.IsSupportedPolygonType(partInfo.type) && partInfo.vertexCount == 0) { // No geometry for input asset if (partData != null) { // Clean up existing part HEU_PartData.DestroyPart(partData); partData = null; } // No need to process further since we don't have geometry return; } } else { // Preliminary check for attribute instancing (mesh type with no verts but has points with instances) if (HEU_HAPIUtility.IsSupportedPolygonType(partInfo.type) && partInfo.vertexCount == 0 && partInfo.pointCount > 0) { HAPI_AttributeInfo instanceAttrInfo = new HAPI_AttributeInfo(); HEU_GeneralUtility.GetAttributeInfo(session, GeoID, partID, HEU_PluginSettings.UnityInstanceAttr, ref instanceAttrInfo); if (instanceAttrInfo.exists && instanceAttrInfo.count > 0) { isAttribInstancer = true; } } } if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INVALID) { // Clean up invalid parts if (partData != null) { HEU_PartData.DestroyPart(partData); partData = null; } } else if (partInfo.type < HAPI_PartType.HAPI_PARTTYPE_MAX) { // Process the part based on type. Keep or ignore. // We treat parts of type curve as curves, along with geo nodes that are editable and type curves if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_CURVE) { if (partData == null) { partData = ScriptableObject.CreateInstance <HEU_PartData>(); } partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.CURVE, isPartEditable, _containerObjectNode.IsInstancer(), false); SetupGameObjectAndTransform(partData, parentAsset); partData.ProcessCurvePart(session); } else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_VOLUME) { // We only process "height" volume parts. Other volume parts are ignored for now. #if TERRAIN_SUPPORTED HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo(); bResult = session.GetVolumeInfo(GeoID, partID, ref volumeInfo); if (!bResult) { Debug.LogErrorFormat("Unable to get volume info for geo node {0} and part {1} ", GeoID, partID); } else { if (Displayable && !IsIntermediateOrEditable()) { if (partData == null) { partData = ScriptableObject.CreateInstance <HEU_PartData>(); } else { // Clear volume data (case where switching from polygonal mesh to volume output) partData.ClearGeneratedMeshOutput(); } partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.VOLUME, isPartEditable, _containerObjectNode.IsInstancer(), false); SetupGameObjectAndTransform(partData, ParentAsset); } } #else Debug.LogWarningFormat("Terrain (heightfield volume) is not yet supported."); #endif } else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INSTANCER || isAttribInstancer) { if (partData == null) { partData = ScriptableObject.CreateInstance <HEU_PartData>(); } else { partData.ClearGeneratedMeshOutput(); partData.ClearGeneratedVolumeOutput(); } partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.INSTANCER, isPartEditable, _containerObjectNode.IsInstancer(), isAttribInstancer); SetupGameObjectAndTransform(partData, parentAsset); } else if (HEU_HAPIUtility.IsSupportedPolygonType(partInfo.type)) { if (partData == null) { partData = ScriptableObject.CreateInstance <HEU_PartData>(); } else { // Clear volume data (case where switching from something other output to mesh) partData.ClearGeneratedVolumeOutput(); } partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.MESH, isPartEditable, _containerObjectNode.IsInstancer(), false); // This check allows to ignore editable non-display nodes by default, but commented out to allow // them for now. Users can also ignore them by turning on IgnoreNonDisplayNodes //if (Displayable || (Editable && ParentAsset.EditableNodesToolsEnabled)) { SetupGameObjectAndTransform(partData, parentAsset); } } else { Debug.LogWarningFormat("Unsupported part type {0}", partInfo.type); } if (partData != null) { // Success! _parts.Add(partData); // Set unique name for the part string partName = HEU_PluginSettings.UseFullPathNamesForOutput ? GeneratePartFullName(partData.PartName) : partData.PartName; partData.SetGameObjectName(partName); // For intermediate or default-type editable nodes, setup the HEU_AttributeStore if (isPartEditable) { partData.SyncAttributesStore(session, _geoInfo.nodeId, ref partInfo); } else { // Remove attributes store if it has it partData.DestroyAttributesStore(); } } } #if HEU_PROFILER_ON Debug.LogFormat("PART PROCESS TIME:: NAME={0}, TIME={1}", HEU_SessionManager.GetString(partInfo.nameSH, session), (Time.realtimeSinceStartup - processPartStartTime)); #endif }
public static void ExecuteToolOperatorMultiple(string toolName, string toolPath, GameObject[] inputObjects) { GameObject outputObjectToSelect = null; GameObject go = HEU_HAPIUtility.InstantiateHDA(toolPath, Vector3.zero, HEU_SessionManager.GetOrCreateDefaultSession(), false); if(go == null) { Debug.LogWarningFormat("Failed to instantiate tool: {0}", toolName); return; } HEU_HoudiniAssetRoot assetRoot = go.GetComponent<HEU_HoudiniAssetRoot>(); if (assetRoot != null) { HEU_HoudiniAsset asset = assetRoot._houdiniAsset; HEU_SessionBase session = asset.GetAssetSession(true); int numInputs = inputObjects.Length; List<HEU_InputNode> inputNodes = asset.GetInputNodes(); if (inputNodes == null || inputNodes.Count == 0) { Debug.LogErrorFormat("Unable to assign input geometry due to no asset inputs on selected tool."); } else { // User could have selected any number of inputs objects, and asset could have any number of inputs. // So use minimum of either to set input object into asset input. int minInputCount = Mathf.Min(inputNodes.Count, numInputs); for (int i = 0; i < minInputCount; ++i) { if (!IsValidInput(inputObjects[i])) { continue; } GameObject inputObject = inputObjects[i]; HEU_InputNode inputNode = inputNodes[i]; inputNode.ResetInputNode(session); inputNode.ChangeInputType(session, HEU_InputNode.InputObjectType.UNITY_MESH); HEU_InputObjectInfo inputInfo = inputNode.AddInputEntryAtEnd(inputObject); inputInfo._useTransformOffset = false; inputNode.KeepWorldTransform = true; inputNode.PackGeometryBeforeMerging = false; inputNode.RequiresUpload = true; } asset.RequestCook(true, true, true, true); outputObjectToSelect = assetRoot.gameObject; } } if (outputObjectToSelect != null) { HEU_EditorUtility.SelectObject(outputObjectToSelect); } }
public static void ExecuteToolOperatorSingle(string toolName, string toolPath, GameObject[] inputObjects) { // Single operator means single asset input. If multiple inputs are provided, create tool for each input. List<GameObject> outputObjectsToSelect = new List<GameObject>(); int numInputs = inputObjects.Length; for (int i = 0; i < numInputs; ++i) { if(!IsValidInput(inputObjects[i])) { continue; } GameObject inputObject = inputObjects[i]; GameObject go = HEU_HAPIUtility.InstantiateHDA(toolPath, Vector3.zero, HEU_SessionManager.GetOrCreateDefaultSession(), false); if (go != null) { HEU_HoudiniAssetRoot assetRoot = go.GetComponent<HEU_HoudiniAssetRoot>(); if (assetRoot != null) { HEU_HoudiniAsset asset = assetRoot._houdiniAsset; HEU_SessionBase session = asset.GetAssetSession(true); List<HEU_InputNode> inputNodes = asset.GetInputNodes(); if (inputNodes == null || inputNodes.Count == 0) { Debug.LogErrorFormat("Unable to assign input geometry due to no asset inputs on selected tool."); } else { HEU_InputNode inputNode = inputNodes[0]; inputNode.ResetInputNode(session); inputNode.ChangeInputType(session, HEU_InputNode.InputObjectType.UNITY_MESH); HEU_InputObjectInfo inputInfo = inputNode.AddInputEntryAtEnd(inputObject); inputInfo._useTransformOffset = false; inputNode.KeepWorldTransform = true; inputNode.PackGeometryBeforeMerging = false; inputNode.RequiresUpload = true; asset.RequestCook(true, true, true, true); outputObjectsToSelect.Add(assetRoot.gameObject); } } } else { Debug.LogWarningFormat("Failed to instantiate tool: {0}", toolName); } } if (outputObjectsToSelect.Count > 0) { HEU_EditorUtility.SelectObjects(outputObjectsToSelect.ToArray()); } }
/// <summary> /// Create an input node network and upload the given set of input objects. /// This creates a SOP/merge node, and input nodes for each object in inputObjects /// which are then connected to the merge node. /// It finds the input interface that supports each object in inputObjects for creating /// the input node and uploading the data based on the type of data. /// </summary> /// <param name="session">Session to create the input node in</param> /// <param name="assetID">Main asset ID</param> /// <param name="connectMergeID">Created SOP/merge node ID</param> /// <param name="inputObjects">List of input objects to upload</param> /// <param name="inputObjectsConnectedAssetIDs">List of input node IDs for the input nodes created</param> /// <param name="inputNode">The specified inputNode to create the node for (used for settings)</param> /// <returns>True if successfully uploading input nodes</returns> internal static bool CreateInputNodeWithMultiObjects(HEU_SessionBase session, HAPI_NodeId assetID, ref HAPI_NodeId connectMergeID, ref List<HEU_InputObjectInfo> inputObjects, ref List<HAPI_NodeId> inputObjectsConnectedAssetIDs, HEU_InputNode inputNode) { bool bKeepWorldTransform = inputNode.KeepWorldTransform; // Create the merge SOP node that the input nodes are going to connect to. if (!session.CreateNode(-1, "SOP/merge", null, true, out connectMergeID)) { HEU_Logger.LogErrorFormat("Unable to create merge SOP node for connecting input assets."); return false; } int numObjects = inputObjects.Count; for (int i = 0; i < numObjects; ++i) { HAPI_NodeId newConnectInputID = HEU_Defines.HEU_INVALID_NODE_ID; inputObjectsConnectedAssetIDs.Add(newConnectInputID); // Skipping null gameobjects. Though if this causes issues, can always let it continue // to create input node, but not upload mesh data if (inputObjects[i]._gameObject == null) { continue; } HEU_InputInterface inputInterface = GetInputInterface(inputObjects[i]); if (inputInterface == null) { HEU_Logger.LogWarningFormat("No input interface found for gameobject: {0}. Skipping upload!", inputObjects[i]._gameObject.name); continue; } // Apply settings based on the interface type. System.Type inputInterfaceType = inputInterface.GetType(); if (inputInterfaceType == typeof(HEU_InputInterfaceMesh)) { HEU_InputInterfaceMesh meshInterface = inputInterface as HEU_InputInterfaceMesh; meshInterface.Initialize(inputNode.MeshSettings); } if (inputInterfaceType == typeof(HEU_InputInterfaceTilemap)) { HEU_InputInterfaceTilemap tilemapInterface = inputInterface as HEU_InputInterfaceTilemap; tilemapInterface.Initialize(inputNode.TilemapSettings); } bool bResult = inputInterface.CreateInputNodeWithDataUpload(session, connectMergeID, inputObjects[i]._gameObject, out newConnectInputID); if (!bResult || newConnectInputID == HEU_Defines.HEU_INVALID_NODE_ID) { HEU_Logger.LogError("Failed to upload input."); continue; } inputObjectsConnectedAssetIDs[i] = newConnectInputID; if (!session.ConnectNodeInput(connectMergeID, i, newConnectInputID)) { HEU_Logger.LogErrorFormat("Unable to connect input nodes!"); return false; } UploadInputObjectTransform(session, inputObjects[i], newConnectInputID, bKeepWorldTransform); } return true; }
private static void DrawSelectionWindow(HEU_InputNode.InputObjectType inputObjectType, HEU_InputNode inputNode) { using (var hs1 = new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button(new GUIContent("Selection Window", "Use a custom window to select the objects from the Hierarchy."))) { if (HEU_InputNode.GetInternalObjectType(inputObjectType) == HEU_InputNode.InternalObjectType.HDA) { HEU_SelectionWindow.ShowWindow(HandleSelectedObjectsForInputHDAs, typeof(HEU_HoudiniAssetRoot), inputNode); } else if (inputObjectType == HEU_InputNode.InputObjectType.TERRAIN) { HEU_SelectionWindow.ShowWindow(HandleSelectedObjectsForInputObjects, typeof(Terrain), inputNode); } else if (inputObjectType == HEU_InputNode.InputObjectType.BOUNDING_BOX) { HEU_SelectionWindow.ShowWindow(HandleSelectedObjectsForInputObjects, typeof(HEU_BoundingVolume), inputNode); } else if (inputObjectType == HEU_InputNode.InputObjectType.TILEMAP) { HEU_SelectionWindow.ShowWindow(HandleSelectedObjectsForInputObjects, typeof(Tilemap), inputNode); } else { HEU_SelectionWindow.ShowWindow(HandleSelectedObjectsForInputObjects, typeof(GameObject), inputNode); } } if (!inputNode._usingSelectFromHierarchy) { string title = "Select from Hierarchy (Locks Inspector)"; float shortenLength = 420; float reallyShortLength = 320; float screenWidth = Screen.width; if (screenWidth < reallyShortLength) { title = "From Hierarchy"; } else if (screenWidth < shortenLength) { title = "Select from Hierarchy"; } if (GUILayout.Button(new GUIContent(title, "Locks the inspector and so you can select GameObjects from the Hierarchy. Once select, press Use Current Selection to add the specified objects as inputs."))) { SetInspectorLock(true); inputNode._usingSelectFromHierarchy = true; } } else { if (GUILayout.Button("Use Current Selection")) { SetInspectorLock(false); inputNode._usingSelectFromHierarchy = false; GameObject[] selection = Selection.gameObjects; List <GameObject> filteredObjects = new List <GameObject>(selection); filteredObjects = filteredObjects.Filter((GameObject obj) => { if (obj == null) { return(false); } bool result = true; if (HEU_InputNode.GetInternalObjectType(inputObjectType) == HEU_InputNode.InternalObjectType.HDA && obj.GetComponent <HEU_HoudiniAssetRoot>() == null) { result = false; } else if (inputObjectType == HEU_InputNode.InputObjectType.TERRAIN && obj.GetComponent <Terrain>() == null) { result = false; } else if (inputObjectType == HEU_InputNode.InputObjectType.BOUNDING_BOX && obj.GetComponent <HEU_BoundingVolume>() == null) { result = false; } else if (inputObjectType == HEU_InputNode.InputObjectType.TILEMAP && obj.GetComponent <Tilemap>() == null) { result = false; } if (result == false) { HEU_Logger.LogWarning("Houdini GameObject selection: " + obj.name + " filtered out due to invalid type!"); return(false); } return(true); }); if (HEU_InputNode.GetInternalObjectType(inputObjectType) == HEU_InputNode.InternalObjectType.HDA) { HandleSelectedObjectsForInputHDAs(filteredObjects.ToArray(), inputNode); } else { HandleSelectedObjectsForInputObjects(filteredObjects.ToArray(), inputNode); } // Populate input cache if modified. if (inputNode._uiCache == null) { PopulateCache(inputNode); } if (inputNode.ParentAsset && inputNode.ParentAsset.RootGameObject) { // Select this gameObject so it doesn't jump to the last selection as soon as it unlocks. Selection.activeGameObject = inputNode.ParentAsset.RootGameObject.gameObject; } } } } }
public static void HandleSelectedObjectsForInputObjects(GameObject[] selectedObjects, HEU_InputNode inputNode) { inputNode.HandleSelectedObjectsForInputObjects(selectedObjects); inputNode._uiCache._inputNodeSerializedObject.ApplyModifiedProperties(); inputNode.RequiresUpload = true; inputNode.ClearUICache(); }
/// <summary> /// Draw the UI for the given input node /// </summary> /// <param name="inputNode"></param> public static void EditorDrawInputNode(HEU_InputNode inputNode) { int plusButtonWidth = 20; const string inputTypeTooltip = @"Input type of the object. The HDA type can accept any object with a HEU_HoudiniAssetRoot component. (Including curves) The UNITY_MESH type can accept any GameObject (Including Terrain, HEU_BoundingVolumes)."; GUIContent inputTypeLabel = new GUIContent("Input Type", inputTypeTooltip); GUIContent translateLabel = new GUIContent(" Translate"); GUIContent rotateLabel = new GUIContent(" Rotate"); GUIContent scaleLabel = new GUIContent(" Scale"); PopulateCache(inputNode); EditorGUI.BeginChangeCheck(); EditorGUILayout.BeginVertical(EditorStyles.helpBox); string labelName = inputNode.LabelName; if (!string.IsNullOrEmpty(labelName)) { EditorGUILayout.LabelField(labelName); } EditorGUI.indentLevel++; HEU_InputNode.InputObjectType inputObjectType = (HEU_InputNode.InputObjectType)inputNode._uiCache._inputObjectTypeProperty.intValue; HEU_InputNode.InputObjectType userSelectedInputObjectType = (HEU_InputNode.InputObjectType)EditorGUILayout.EnumPopup(inputTypeLabel, inputObjectType); if (userSelectedInputObjectType != inputObjectType) { SerializedProperty pendingInputObjectTypeProperty = HEU_EditorUtility.GetSerializedProperty(inputNode._uiCache._inputNodeSerializedObject, "_pendingInputObjectType"); if (pendingInputObjectTypeProperty != null) { pendingInputObjectTypeProperty.intValue = (int)userSelectedInputObjectType; } } else { EditorGUILayout.PropertyField(inputNode._uiCache._keepWorldTransformProperty); EditorGUILayout.PropertyField(inputNode._uiCache._packBeforeMergeProperty); if (HEU_InputNode.GetInternalObjectType(inputObjectType) == HEU_InputNode.InternalObjectType.HDA) { SerializedProperty inputAssetsProperty = inputNode._uiCache._inputAssetsProperty; if (inputAssetsProperty != null) { int inputCount = inputAssetsProperty.arraySize; bool bSkipElements = false; HEU_EditorUI.DrawSeparator(); EditorGUILayout.LabelField(string.Format("{0} input objects", inputCount)); using (var hs1 = new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button("Add Slot")) { inputAssetsProperty.InsertArrayElementAtIndex(inputCount); bSkipElements = true; } if (GUILayout.Button("Clear")) { inputAssetsProperty.ClearArray(); bSkipElements = true; } } DrawSelectionWindow(HEU_InputNode.InputObjectType.HDA, inputNode); if (!bSkipElements) { using (var vs1 = new EditorGUILayout.VerticalScope()) { for (int i = 0; i < inputCount; ++i) { using (var hs2 = new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("Input " + (i + 1)); if (GUILayout.Button("+", GUILayout.Width(plusButtonWidth))) { inputAssetsProperty.InsertArrayElementAtIndex(i); break; } if (GUILayout.Button("-", GUILayout.Width(plusButtonWidth))) { inputAssetsProperty.DeleteArrayElementAtIndex(i); break; } } EditorGUI.indentLevel++; using (var vs4 = new EditorGUILayout.VerticalScope()) { if (i < inputNode._uiCache._inputAssetCache.Count) { HEU_InputNodeUICache.HEU_InputAssetUICache assetCache = inputNode._uiCache._inputAssetCache[i]; UnityEngine.Object setObject = EditorGUILayout.ObjectField(assetCache._gameObjectProperty.objectReferenceValue, typeof(HEU_HoudiniAssetRoot), true); if (setObject != assetCache._gameObjectProperty.objectReferenceValue) { GameObject inputGO = setObject != null ? (setObject as HEU_HoudiniAssetRoot).gameObject : null; // Check not setting same asset as self if (inputGO == null || inputGO != inputNode.ParentAsset.RootGameObject) { assetCache._gameObjectProperty.objectReferenceValue = inputGO; } } } } EditorGUI.indentLevel--; } } } } } else if (HEU_InputNode.GetInternalObjectType(inputObjectType) == HEU_InputNode.InternalObjectType.UNITY_MESH) { SerializedProperty inputObjectsProperty = inputNode._uiCache._inputObjectsProperty; if (inputObjectsProperty != null) { bool bSkipElements = false; HEU_EditorUI.DrawSeparator(); EditorGUILayout.LabelField(string.Format("{0} input objects", inputObjectsProperty.arraySize)); using (var hs1 = new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button("Add Slot")) { inputObjectsProperty.arraySize++; FixUpScaleProperty(inputObjectsProperty, inputObjectsProperty.arraySize - 1); bSkipElements = true; } if (GUILayout.Button("Clear")) { inputObjectsProperty.ClearArray(); bSkipElements = true; } } DrawSelectionWindow(inputObjectType, inputNode); if (inputObjectType == HEU_InputNode.InputObjectType.UNITY_MESH && inputNode.MeshSettings != null) { HEU_EditorUI.DrawHeadingLabel("Mesh settings"); EditorGUI.indentLevel++; { UnityEditor.SerializedProperty exportCollidersProperty = inputNode._uiCache._meshSettingsProperty.FindPropertyRelative("_exportColliders"); exportCollidersProperty.boolValue = HEU_EditorUI.DrawToggleLeft(exportCollidersProperty.boolValue, _meshExportCollidersContent.text, _meshExportCollidersContent.tooltip); } EditorGUI.indentLevel--; } else if (inputObjectType == HEU_InputNode.InputObjectType.TILEMAP && inputNode.TilemapSettings != null) { HEU_EditorUI.DrawHeadingLabel("Tilemap settings"); EditorGUI.indentLevel++; { UnityEditor.SerializedProperty createGroupsForTilesProperty = inputNode._uiCache._tilemapSettingsProperty.FindPropertyRelative("_createGroupsForTiles"); UnityEditor.SerializedProperty exportUnusedTilesProperty = inputNode._uiCache._tilemapSettingsProperty.FindPropertyRelative("_exportUnusedTiles"); UnityEditor.SerializedProperty applyTileColorProperty = inputNode._uiCache._tilemapSettingsProperty.FindPropertyRelative("_applyTileColor"); UnityEditor.SerializedProperty applyTilemapOrientationProperty = inputNode._uiCache._tilemapSettingsProperty.FindPropertyRelative("_applyTilemapOrientation"); createGroupsForTilesProperty.boolValue = HEU_EditorUI.DrawToggleLeft(createGroupsForTilesProperty.boolValue, _tilemapCreateGroupsContent.text, _tilemapCreateGroupsContent.tooltip); exportUnusedTilesProperty.boolValue = HEU_EditorUI.DrawToggleLeft(exportUnusedTilesProperty.boolValue, _tilemapExportUnusedTilesContent.text, _tilemapExportUnusedTilesContent.tooltip); applyTileColorProperty.boolValue = HEU_EditorUI.DrawToggleLeft(applyTileColorProperty.boolValue, _tilemapColorContent.text, _tilemapColorContent.tooltip); applyTilemapOrientationProperty.boolValue = HEU_EditorUI.DrawToggleLeft(applyTilemapOrientationProperty.boolValue, _tilemapOrientationContent.text, _tilemapOrientationContent.tooltip); } EditorGUI.indentLevel--; } if (!bSkipElements) { using (var vs1 = new EditorGUILayout.VerticalScope()) { int inputCount = inputObjectsProperty.arraySize; for (int i = 0; i < inputCount; ++i) { using (var hs2 = new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("Input " + (i + 1)); { if (GUILayout.Button("+", GUILayout.Width(plusButtonWidth))) { inputObjectsProperty.InsertArrayElementAtIndex(i); FixUpScaleProperty(inputObjectsProperty, i); break; } if (GUILayout.Button("-", GUILayout.Width(plusButtonWidth))) { inputObjectsProperty.DeleteArrayElementAtIndex(i); break; } } } EditorGUI.indentLevel++; using (var vs4 = new EditorGUILayout.VerticalScope()) { if (i < inputNode._uiCache._inputObjectCache.Count && i < inputNode.InputObjects.Count) { HEU_InputNodeUICache.HEU_InputObjectUICache objectCache = inputNode._uiCache._inputObjectCache[i]; GameObject oldObject = inputNode.InputObjects[i]._gameObject; GameObject newObject = null; switch (inputObjectType) { case HEU_InputNode.InputObjectType.TERRAIN: inputNode.InputObjects[i]._terrainReference = EditorGUILayout.ObjectField(inputNode.InputObjects[i]._terrainReference, typeof(Terrain), true) as Terrain; if (inputNode.InputObjects[i]._terrainReference != null) { newObject = inputNode.InputObjects[i]._terrainReference.gameObject; } break; case HEU_InputNode.InputObjectType.BOUNDING_BOX: inputNode.InputObjects[i]._boundingVolumeReference = EditorGUILayout.ObjectField(inputNode.InputObjects[i]._boundingVolumeReference, typeof(HEU_BoundingVolume), true) as HEU_BoundingVolume; if (inputNode.InputObjects[i]._boundingVolumeReference != null) { newObject = inputNode.InputObjects[i]._boundingVolumeReference.gameObject; } break; case HEU_InputNode.InputObjectType.TILEMAP: inputNode.InputObjects[i]._tilemapReference = EditorGUILayout.ObjectField(inputNode.InputObjects[i]._tilemapReference, typeof(Tilemap), true) as Tilemap; if (inputNode.InputObjects[i]._tilemapReference != null) { newObject = inputNode.InputObjects[i]._tilemapReference.gameObject; } break; default: newObject = EditorGUILayout.ObjectField(inputNode.InputObjects[i]._gameObject, typeof(GameObject), true) as GameObject; break; } if (oldObject != newObject) { Undo.RecordObject(inputNode, "GameObject Assign"); inputNode.InputObjects[i]._gameObject = newObject; // Set the reference to avoid strange bugs when switching input type modes inputNode.InputObjects[i].SetReferencesFromGameObject(); EditorUtility.SetDirty(inputNode); } using (new EditorGUI.DisabledScope(!inputNode._uiCache._keepWorldTransformProperty.boolValue)) { objectCache._transformOffsetProperty.boolValue = HEU_EditorUI.DrawToggleLeft(objectCache._transformOffsetProperty.boolValue, "Transform Offset"); if (objectCache._transformOffsetProperty.boolValue) { objectCache._translateProperty.vector3Value = EditorGUILayout.Vector3Field(translateLabel, objectCache._translateProperty.vector3Value); objectCache._rotateProperty.vector3Value = EditorGUILayout.Vector3Field(rotateLabel, objectCache._rotateProperty.vector3Value); objectCache._scaleProperty.vector3Value = EditorGUILayout.Vector3Field(scaleLabel, objectCache._scaleProperty.vector3Value); } } } } EditorGUI.indentLevel--; } } } } } } EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); if (EditorGUI.EndChangeCheck()) { inputNode._uiCache._inputNodeSerializedObject.ApplyModifiedProperties(); // When cooking, this will force input data to be uploaded inputNode.RequiresUpload = true; inputNode.ClearUICache(); } }
/// <summary> /// Draw the UI for the given input node /// </summary> /// <param name="inputNode"></param> public static void EditorDrawInputNode(HEU_InputNode inputNode) { int plusButtonWidth = 20; //GUIStyle boldLabelStyle = new GUIStyle(EditorStyles.boldLabel); //boldLabelStyle.alignment = TextAnchor.UpperLeft; GUIContent inputTypeLabel = new GUIContent("Input Type"); GUIContent translateLabel = new GUIContent(" Translate"); GUIContent rotateLabel = new GUIContent(" Rotate"); GUIContent scaleLabel = new GUIContent(" Scale"); PopulateCache(inputNode); EditorGUI.BeginChangeCheck(); EditorGUILayout.BeginVertical(EditorStyles.helpBox); string labelName = inputNode.LabelName; if (!string.IsNullOrEmpty(labelName)) { EditorGUILayout.LabelField(labelName); } EditorGUI.indentLevel++; HEU_InputNode.InputObjectType inputObjectType = (HEU_InputNode.InputObjectType)inputNode._uiCache._inputObjectTypeProperty.intValue; HEU_InputNode.InputObjectType userSelectedInputObjectType = (HEU_InputNode.InputObjectType)EditorGUILayout.EnumPopup(inputTypeLabel, inputObjectType); if (userSelectedInputObjectType != inputObjectType) { SerializedProperty pendingInputObjectTypeProperty = HEU_EditorUtility.GetSerializedProperty(inputNode._uiCache._inputNodeSerializedObject, "_pendingInputObjectType"); if (pendingInputObjectTypeProperty != null) { pendingInputObjectTypeProperty.intValue = (int)userSelectedInputObjectType; } } else { EditorGUILayout.PropertyField(inputNode._uiCache._keepWorldTransformProperty); EditorGUILayout.PropertyField(inputNode._uiCache._packBeforeMergeProperty); if (inputObjectType == HEU_InputNode.InputObjectType.HDA) { SerializedProperty inputAssetsProperty = inputNode._uiCache._inputAssetsProperty; if (inputAssetsProperty != null) { int inputCount = inputAssetsProperty.arraySize; bool bSkipElements = false; HEU_EditorUI.DrawSeparator(); EditorGUILayout.LabelField(string.Format("{0} input objects", inputCount)); using (var hs1 = new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button("Add Slot")) { inputAssetsProperty.InsertArrayElementAtIndex(inputCount); bSkipElements = true; } if (GUILayout.Button("Add Selection")) { HEU_SelectionWindow.ShowWindow(inputNode.HandleSelectedObjectsForInputHDAs, typeof(HEU_HoudiniAssetRoot)); } if (GUILayout.Button("Clear")) { inputAssetsProperty.ClearArray(); bSkipElements = true; } } if (!bSkipElements) { using (var vs1 = new EditorGUILayout.VerticalScope()) { for (int i = 0; i < inputCount; ++i) { using (var hs2 = new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("Input " + (i + 1)); if (GUILayout.Button("+", GUILayout.Width(plusButtonWidth))) { inputAssetsProperty.InsertArrayElementAtIndex(i); break; } if (GUILayout.Button("-", GUILayout.Width(plusButtonWidth))) { inputAssetsProperty.DeleteArrayElementAtIndex(i); break; } } EditorGUI.indentLevel++; using (var vs4 = new EditorGUILayout.VerticalScope()) { HEU_InputNodeUICache.HEU_InputAssetUICache assetCache = inputNode._uiCache._inputAssetCache[i]; UnityEngine.Object setObject = EditorGUILayout.ObjectField(assetCache._gameObjectProperty.objectReferenceValue, typeof(HEU_HoudiniAssetRoot), true); if (setObject != assetCache._gameObjectProperty.objectReferenceValue) { GameObject inputGO = setObject != null ? (setObject as HEU_HoudiniAssetRoot).gameObject : null; // Check not setting same asset as self if (inputGO == null || inputGO != inputNode.ParentAsset.RootGameObject) { assetCache._gameObjectProperty.objectReferenceValue = inputGO; } } } EditorGUI.indentLevel--; } } } } } //else if (inputObjectType == HEU_InputNode.InputObjectType.CURVE) //{ // TODO INPUT CURVE //} else if (inputObjectType == HEU_InputNode.InputObjectType.UNITY_MESH) { SerializedProperty inputObjectsProperty = inputNode._uiCache._inputObjectsProperty; if (inputObjectsProperty != null) { bool bSkipElements = false; HEU_EditorUI.DrawSeparator(); EditorGUILayout.LabelField(string.Format("{0} input objects", inputObjectsProperty.arraySize)); using (var hs1 = new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button("Add Slot")) { inputObjectsProperty.arraySize++; FixUpScaleProperty(inputObjectsProperty, inputObjectsProperty.arraySize - 1); bSkipElements = true; } if (GUILayout.Button("Add Selection")) { HEU_SelectionWindow.ShowWindow(inputNode.HandleSelectedObjectsForInputObjects, typeof(GameObject)); } if (GUILayout.Button("Clear")) { inputObjectsProperty.ClearArray(); bSkipElements = true; } } if (!bSkipElements) { using (var vs1 = new EditorGUILayout.VerticalScope()) { int inputCount = inputObjectsProperty.arraySize; for (int i = 0; i < inputCount; ++i) { using (var hs2 = new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("Input " + (i + 1)); //using (var vs3 = new EditorGUILayout.VerticalScope()) { if (GUILayout.Button("+", GUILayout.Width(plusButtonWidth))) { inputObjectsProperty.InsertArrayElementAtIndex(i); FixUpScaleProperty(inputObjectsProperty, i); break; } if (GUILayout.Button("-", GUILayout.Width(plusButtonWidth))) { inputObjectsProperty.DeleteArrayElementAtIndex(i); break; } } } EditorGUI.indentLevel++; using (var vs4 = new EditorGUILayout.VerticalScope()) { HEU_InputNodeUICache.HEU_InputObjectUICache objectCache = inputNode._uiCache._inputObjectCache[i]; EditorGUILayout.PropertyField(objectCache._gameObjectProperty, GUIContent.none); using (new EditorGUI.DisabledScope(!inputNode._uiCache._keepWorldTransformProperty.boolValue)) { objectCache._transformOffsetProperty.boolValue = HEU_EditorUI.DrawToggleLeft(objectCache._transformOffsetProperty.boolValue, "Transform Offset"); if (objectCache._transformOffsetProperty.boolValue) { objectCache._translateProperty.vector3Value = EditorGUILayout.Vector3Field(translateLabel, objectCache._translateProperty.vector3Value); objectCache._rotateProperty.vector3Value = EditorGUILayout.Vector3Field(rotateLabel, objectCache._rotateProperty.vector3Value); objectCache._scaleProperty.vector3Value = EditorGUILayout.Vector3Field(scaleLabel, objectCache._scaleProperty.vector3Value); } } } EditorGUI.indentLevel--; } } } } } } EditorGUI.indentLevel--; EditorGUILayout.EndVertical(); if (EditorGUI.EndChangeCheck()) { inputNode._uiCache._inputNodeSerializedObject.ApplyModifiedProperties(); // When cooking, this will force input data to be uploaded inputNode.RequiresUpload = true; } }
public static void ShowWindow(SelectionResultHandler selectionHandler, System.Type selectionType, HEU_InputNode inputNode = null) { bool bUtility = false; bool bFocus = true; string title = "Input Selection"; HEU_SelectionWindow window = EditorWindow.GetWindow <HEU_SelectionWindow>(bUtility, title, bFocus); window.autoRepaintOnSceneChange = true; window._inputNode = inputNode; window._selectionHandler = selectionHandler; window._selectionType = selectionType; }
/// <summary> /// Process the part at the given index, creating its data (geometry), /// and adding it to the list of parts. /// </summary> /// <param name="session"></param> /// <param name="partID"></param> /// <returns>A valid HEU_PartData if it has been successfully processed.</returns> private void ProcessPart(HEU_SessionBase session, int partID, ref HAPI_PartInfo partInfo, ref HEU_PartData partData) { HEU_HoudiniAsset parentAsset = ParentAsset; bool bResult = true; //Debug.LogFormat("Part: name={0}, id={1}, type={2}, instanced={3}, instance count={4}, instance part count={5}", HEU_SessionManager.GetString(partInfo.nameSH, session), partID, partInfo.type, partInfo.isInstanced, partInfo.instanceCount, partInfo.instancedPartCount); #if HEU_PROFILER_ON float processPartStartTime = Time.realtimeSinceStartup; #endif bool isPartEditable = IsIntermediateOrEditable(); if (IsGeoInputType()) { // Setup for input node to accept inputs if (_inputNode == null) { string partName = HEU_SessionManager.GetString(partInfo.nameSH, session); _inputNode = HEU_InputNode.CreateSetupInput(GeoID, 0, partName, HEU_InputNode.InputNodeType.NODE, ParentAsset); if (_inputNode != null) { ParentAsset.AddInputNode(_inputNode); } } if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_MESH && partInfo.vertexCount == 0) { // No geometry for input asset if (partData != null) { // Clean up existing part HEU_PartData.DestroyPart(partData); partData = null; } // No need to process further since we don't have geometry return; } } if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INVALID) { // Clean up invalid parts if (partData != null) { HEU_PartData.DestroyPart(partData); partData = null; } } else if (partInfo.type < HAPI_PartType.HAPI_PARTTYPE_MAX) { // Process the part based on type. Keep or ignore. // We treat parts of type curve as curves, along with geo nodes that are editable and type curves if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_CURVE) { if (partData == null) { partData = ScriptableObject.CreateInstance <HEU_PartData>(); } partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.CURVE, isPartEditable); SetupGameObjectAndTransform(partData, parentAsset); partData.ProcessCurvePart(session); } else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_VOLUME) { // We only process "height" volume parts. Other volume parts are ignored for now. #if TERRAIN_SUPPORTED HAPI_VolumeInfo volumeInfo = new HAPI_VolumeInfo(); bResult = session.GetVolumeInfo(GeoID, partID, ref volumeInfo); if (!bResult) { Debug.LogErrorFormat("Unable to get volume info for geo node {0} and part {1} ", GeoID, partID); } else { if (Displayable && !IsIntermediateOrEditable()) { if (partData == null) { partData = ScriptableObject.CreateInstance <HEU_PartData>(); } partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.VOLUME, isPartEditable); SetupGameObjectAndTransform(partData, ParentAsset); } } #else Debug.LogWarningFormat("Terrain (heightfield volume) is not yet supported."); #endif } else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_MESH) { if (partData == null) { partData = ScriptableObject.CreateInstance <HEU_PartData>(); } partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.MESH, isPartEditable); SetupGameObjectAndTransform(partData, parentAsset); } else if (partInfo.type == HAPI_PartType.HAPI_PARTTYPE_INSTANCER) { if (partData == null) { partData = ScriptableObject.CreateInstance <HEU_PartData>(); } partData.Initialize(session, partID, GeoID, _containerObjectNode.ObjectID, this, ref partInfo, HEU_PartData.PartOutputType.INSTANCER, isPartEditable); SetupGameObjectAndTransform(partData, parentAsset); } else { Debug.LogWarningFormat("Unsupported part type {0}", partInfo.type); } if (partData != null) { // Success! _parts.Add(partData); // Set unique name for the part string partFullName = GeneratePartFullName(partData.PartName); partFullName = HEU_EditorUtility.GetUniqueNameForSibling(ParentAsset.RootGameObject.transform, partFullName); partData.SetGameObjectName(partFullName); // For intermediate or default-type editable nodes, setup the HEU_AttributeStore if (isPartEditable) { partData.SyncAttributesStore(session, _geoInfo.nodeId, ref partInfo); } else { // Remove attributes store if it has it partData.DestroyAttributesStore(); } HEU_GeneralUtility.AssignUnityTag(session, GeoID, partData.PartID, partData._gameObject); HEU_GeneralUtility.MakeStaticIfHasAttribute(session, GeoID, partData.PartID, partData._gameObject); } } #if HEU_PROFILER_ON Debug.LogFormat("PART PROCESS TIME:: NAME={0}, TIME={1}", HEU_SessionManager.GetString(partInfo.nameSH, session), (Time.realtimeSinceStartup - processPartStartTime)); #endif }