public void DrawGPUInstancerPrototypeAddButton() { Rect prototypeRect = GUILayoutUtility.GetRect(PROTOTYPE_RECT_SIZE, PROTOTYPE_RECT_SIZE, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false)); Rect iconRect = new Rect(prototypeRect.position + PROTOTYPE_RECT_PADDING_VECTOR, PROTOTYPE_RECT_SIZE_VECTOR); iconRect.height -= 22; GPUInstancerEditorConstants.DrawColoredButton(GPUInstancerEditorConstants.Contents.add, GPUInstancerEditorConstants.Colors.lightBlue, Color.white, FontStyle.Bold, iconRect, () => { _pickerOverride = null; pickerControlID = EditorGUIUtility.GetControlID(FocusType.Passive) + 100; ShowObjectPicker(); }, true, true, (o) => { AddPickerObject(o); }); iconRect.y += iconRect.height; iconRect.height = 22; GPUInstancerEditorConstants.DrawColoredButton(GPUInstancerEditorConstants.Contents.addMulti, GPUInstancerEditorConstants.Colors.darkBlue, Color.white, FontStyle.Bold, iconRect, () => { GPUInstancerMultiAddWindow.ShowWindow(GUIUtility.GUIToScreenPoint(iconRect.position), this); }, true, true, (o) => { AddPickerObject(o); }); }
/// <summary> /// Can be used to change the mesh of a prototype at runtime /// </summary> /// <param name="manager">GPUI Manager</param> /// <param name="prototype">GPUI Prototype</param> /// <param name="mesh">New mesh to set on the renderer</param> /// <param name="lodLevel">LOD level</param> /// <param name="rendererIndex">Renderer index on the LOD level</param> /// <param name="subMeshIndex">Submesh index of the renderer</param> public static void ChangeMesh(GPUInstancerManager manager, GPUInstancerPrototype prototype, Mesh mesh, int lodLevel = 0, int rendererIndex = 0, int subMeshIndex = 0) { GPUInstancerRuntimeData runtimeData = manager.GetRuntimeData(prototype, true); if (runtimeData == null) { return; } GPUInstancerRenderer gpuiRenderer = runtimeData.instanceLODs[lodLevel].renderers[rendererIndex]; if (gpuiRenderer.mesh.subMeshCount != mesh.subMeshCount) { Debug.LogError("ChangeMesh method can not be used with a mesh that has different amount of submeshes than the original mesh."); return; } if (gpuiRenderer.mesh.vertexCount != mesh.vertexCount) { int argsLastIndex = gpuiRenderer.argsBufferOffset; // Setup the indirect renderer buffer: for (int j = 0; j < gpuiRenderer.mesh.subMeshCount; j++) { runtimeData.args[argsLastIndex++] = gpuiRenderer.mesh.GetIndexCount(j); // index count per instance runtimeData.args[argsLastIndex++] = 0; // (uint)runtimeData.bufferSize; runtimeData.args[argsLastIndex++] = gpuiRenderer.mesh.GetIndexStart(j); // start index location runtimeData.args[argsLastIndex++] = 0; // base vertex location runtimeData.args[argsLastIndex++] = 0; // start instance location } runtimeData.argsBuffer.SetData(runtimeData.args); } gpuiRenderer.mesh = mesh; }
public virtual void AddPickerObject(UnityEngine.Object pickerObject, GPUInstancerPrototype overridePrototype = null) { if (overridePrototype != null && GPUInstancerDefines.previewCache != null) { GPUInstancerDefines.previewCache.RemovePreview(overridePrototype); } }
/// <summary> /// Can be used to change the material of a prototype at runtime /// </summary> /// <param name="manager">GPUI Manager</param> /// <param name="prototype">GPUI Prototype</param> /// <param name="material">New material to set on the renderer</param> /// <param name="lodLevel">LOD level</param> /// <param name="rendererIndex">Renderer index on the LOD level</param> /// <param name="subMeshIndex">Submesh index of the renderer</param> public static void ChangeMaterial(GPUInstancerManager manager, GPUInstancerPrototype prototype, Material material, int lodLevel = 0, int rendererIndex = 0, int subMeshIndex = 0) { GPUInstancerRuntimeData runtimeData = manager.GetRuntimeData(prototype, true); if (runtimeData == null) { return; } GPUInstancerRenderer gpuiRenderer = runtimeData.instanceLODs[lodLevel].renderers[rendererIndex]; // Generate proxy GO with a Mesh Renderer to get material property blocks GameObject proxyGameObject = new GameObject("ProxyGO"); MeshFilter meshFilter = proxyGameObject.AddComponent <MeshFilter>(); MeshRenderer proxyRenderer = proxyGameObject.AddComponent <MeshRenderer>(); // Set mesh to proxy GO meshFilter.mesh = gpuiRenderer.mesh; // Set new material to runtime data gpuiRenderer.materials[subMeshIndex] = GPUInstancerConstants.gpuiSettings.shaderBindings.GetInstancedMaterial(material); // Set new material to proxy GO proxyRenderer.materials[subMeshIndex] = material; // Get material property blocks proxyRenderer.GetPropertyBlock(gpuiRenderer.mpb); if (gpuiRenderer.shadowMPB != null) { proxyRenderer.GetPropertyBlock(gpuiRenderer.shadowMPB); } // Destroy proxy GO GameObject.Destroy(proxyGameObject); // Setup new materials for instancing GPUInstancerUtility.SetAppendBuffers(runtimeData); }
/// <summary> /// Generates instancing renderer data for a given GameObject, at the first LOD level. /// </summary> public virtual bool CreateRenderersFromGameObject(GPUInstancerPrototype prototype) { if (prototype.prefabObject == null) { return(false); } if (prototype.isShadowCasting) { if (prototype.shadowLODMap == null || prototype.shadowLODMap.Length != 16) { prototype.shadowLODMap = new float[] { 0, 4, 0, 0, 1, 5, 0, 0, 2, 6, 0, 0, 3, 7, 0, 0 }; } } if (prototype.prefabObject.GetComponent <LODGroup>() != null) { return(GenerateLODsFromLODGroup(prototype)); } else { if (instanceLODs == null || instanceLODs.Count == 0) { AddLod(); } return(CreateRenderersFromMeshRenderers(0, prototype)); } }
public void RemovePreview(GPUInstancerPrototype prototype) { if (_previewCache.ContainsKey(prototype)) { _previewCache.Remove(prototype); } }
protected override void OnEnable() { base.OnEnable(); prototypeContents = null; _pickerOverride = null; _manager = (target as GPUInstancerManager); FillPrototypeList(); prop_useFloatingOriginHandler = serializedObject.FindProperty("useFloatingOriginHandler"); prop_floatingOriginTransform = serializedObject.FindProperty("floatingOriginTransform"); prop_layerMask = serializedObject.FindProperty("layerMask"); prop_disableLightProbes = serializedObject.FindProperty("lightProbeDisabled"); showSceneSettingsBox = _manager.showSceneSettingsBox; showPrototypeBox = _manager.showPrototypeBox; showAdvancedBox = _manager.showAdvancedBox; showHelpText = _manager.showHelpText; showDebugBox = _manager.showDebugBox; showGlobalValuesBox = _manager.showGlobalValuesBox; showRegisteredPrefabsBox = _manager.showRegisteredPrefabsBox; showPrototypesBox = _manager.showPrototypesBox; }
public bool DeleteBillboardTextures(GPUInstancerPrototype selectedPrototype) { bool billboardsDeleted = false; #if UNITY_EDITOR if (selectedPrototype.billboard != null && selectedPrototype.billboard.albedoAtlasTexture != null) { BillboardAtlasBinding billboardAtlasBinding = GetBillboardAtlasBinding(selectedPrototype.prefabObject, selectedPrototype.billboard.atlasResolution, selectedPrototype.billboard.frameCount); if (billboardAtlasBinding != null) { if (selectedPrototype.isBillboardDisabled || (selectedPrototype is GPUInstancerDetailPrototype && !((GPUInstancerDetailPrototype)selectedPrototype).usePrototypeMesh) || EditorUtility.DisplayDialog( GPUInstancerConstants.TEXT_deleteConfirmation, GPUInstancerConstants.TEXT_deleteBillboard + "\n\"" + selectedPrototype.ToString() + "\"", GPUInstancerConstants.TEXT_delete, GPUInstancerConstants.TEXT_keepTextures)) { RemoveBillboardAtlas(billboardAtlasBinding); AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(billboardAtlasBinding.albedoAtlasTexture)); AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(billboardAtlasBinding.normalAtlasTexture)); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); billboardsDeleted = true; } } } #endif return(billboardsDeleted); }
public virtual void DrawGPUInstancerPrototypeButton(GPUInstancerPrototype prototype, GUIContent prototypeContent, bool isSelected, UnityAction handleSelect) { if (prototypeContent.image == null) { prototypeContent.image = GetPreview(prototype); } Rect prototypeRect = GUILayoutUtility.GetRect(PROTOTYPE_RECT_SIZE, PROTOTYPE_RECT_SIZE, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false)); Rect iconRect = new Rect(prototypeRect.position + new Vector2(PROTOTYPE_RECT_PADDING, PROTOTYPE_RECT_PADDING), new Vector2(PROTOTYPE_RECT_SIZE - PROTOTYPE_RECT_PADDING * 2, PROTOTYPE_RECT_SIZE - PROTOTYPE_RECT_PADDING * 2)); GUI.SetNextControlName(prototypeContent.tooltip); if (isSelected) { GPUInstancerEditorConstants.DrawColoredButton(prototypeContent, string.IsNullOrEmpty(prototype.warningText) ? GPUInstancerEditorConstants.Colors.lightGreen : GPUInstancerEditorConstants.Colors.lightred, Color.black, FontStyle.Normal, iconRect, null); } else { GPUInstancerEditorConstants.DrawColoredButton(prototypeContent, string.IsNullOrEmpty(prototype.warningText) ? GUI.backgroundColor : GPUInstancerEditorConstants.Colors.darkred, Color.black, FontStyle.Normal, iconRect, () => { if (handleSelect != null) { handleSelect(); } }); } }
public Texture2D GetPreview(GPUInstancerPrototype prototype) { if (_previewCache.ContainsKey(prototype)) { return(_previewCache[prototype]); } return(null); }
public void DrawGPUInstancerPrototypeButton(GPUInstancerPrototype prototype, GUIContent prototypeContent) { base.DrawGPUInstancerPrototypeButton(prototype, prototypeContent, _manager.selectedPrototype == prototype, () => { _manager.selectedPrototype = prototype; GUI.FocusControl(prototypeContent.tooltip); }); }
/// <summary> /// Returns the array that stores the transform data of the instances /// </summary> /// <param name="manager">GPUI Manager</param> /// <param name="prototype">GPUI Prototype</param> /// <returns>Instance data array</returns> public static Matrix4x4[] GetInstanceDataArray(GPUInstancerManager manager, GPUInstancerPrototype prototype) { GPUInstancerRuntimeData runtimeData = manager.GetRuntimeData(prototype, true); if (runtimeData == null) { return(null); } return(runtimeData.instanceDataArray); }
public ComputeBuffer GetTransformDataBuffer(GPUInstancerPrototype prototype) { GPUInstancerRuntimeData runtimeData = GetRuntimeData(prototype); if (runtimeData != null) { return(runtimeData.transformationMatrixVisibilityBuffer); } return(null); }
public GPUInstancerRuntimeData GetRuntimeData(GPUInstancerPrototype prototype, bool logError = false) { GPUInstancerRuntimeData runtimeData = null; if (!runtimeDataDictionary.TryGetValue(prototype, out runtimeData) && logError) { Debug.LogError("Can not find runtime data for prototype: " + prototype + ". Please check if the prototype was added to the Manager and the initialize method was called."); } return(runtimeData); }
public void AddPreview(GPUInstancerPrototype prototype, Texture2D preview) { if (_previewCache.ContainsKey(prototype)) { _previewCache[prototype] = preview; } else { _previewCache.Add(prototype, preview); } }
public void ClearEmptyPreviews() { GPUInstancerPrototype[] prototypes = new GPUInstancerPrototype[_previewCache.Count]; _previewCache.Keys.CopyTo(prototypes, 0); foreach (GPUInstancerPrototype prototype in prototypes) { if (!_previewCache[prototype]) { _previewCache.Remove(prototype); } } }
public override float GetMaxDistance(GPUInstancerPrototype selectedPrototype) { if (selectedPrototype == null) { return(GPUInstancerEditorConstants.MAX_DETAIL_DISTANCE); } return(selectedPrototype is GPUInstancerPrefabPrototype ? GPUInstancerEditorConstants.MAX_PREFAB_DISTANCE : (selectedPrototype is GPUInstancerTreePrototype ? GPUInstancerEditorConstants.MAX_TREE_DISTANCE : GPUInstancerEditorConstants.MAX_DETAIL_DISTANCE)); }
public ComputeBuffer GetTransformDataBuffer(GPUInstancerPrototype prototype) { if (runtimeDataList != null && runtimeDataList.Count > 0) { GPUInstancerRuntimeData runtimeData = runtimeDataList.Find(rd => rd != null && rd.prototype == prototype); if (runtimeData != null) { return(runtimeData.transformationMatrixVisibilityBuffer); } } return(null); }
public static void DrawGPUInstancerPrototypeInfo(GPUInstancerPrototype selectedPrototype, UnityAction <string> DrawHelpText, Object component, UnityAction OnEditorDataChanged, GPUInstancerShaderBindings shaderBindings, GPUInstancerEditorSimulator simulator, GPUInstancerTerrainSettings terrainSettings) { GPUInstancerTreePrototype treePrototype = (GPUInstancerTreePrototype)selectedPrototype; EditorGUILayout.BeginVertical(GPUInstancerEditorConstants.Styles.box); GPUInstancerEditorConstants.DrawCustomLabel(GPUInstancerEditorConstants.TEXT_treeSettings, GPUInstancerEditorConstants.Styles.boldLabel); treePrototype.isApplyRotation = EditorGUILayout.Toggle(GPUInstancerEditorConstants.TEXT_useRandomTreeTotation, treePrototype.isApplyRotation); DrawHelpText(GPUInstancerEditorConstants.HELPTEXT_useRandomTreeTotation); EditorGUILayout.EndVertical(); }
public static UnityEngine.Object GetPreviewObject(GPUInstancerPrototype prototype) { UnityEngine.Object previewObject = prototype.prefabObject; if (prototype is GPUInstancerDetailPrototype) { if (((GPUInstancerDetailPrototype)prototype).prototypeTexture != null) { previewObject = ((GPUInstancerDetailPrototype)prototype).prototypeTexture; } } return(previewObject); }
public override void DeletePrototype(GPUInstancerPrototype prototype, bool removeSO = true) { if (terrainSettings != null && terrain != null && terrain.terrainData != null) { int treePrototypeIndex = prototypeList.IndexOf(prototype); TreePrototype[] treePrototypes = terrain.terrainData.treePrototypes; List <TreePrototype> newTreePrototypes = new List <TreePrototype>(treePrototypes); List <TreeInstance> newTreeInstanceList = new List <TreeInstance>(); TreeInstance treeInstance; for (int i = 0; i < terrain.terrainData.treeInstances.Length; i++) { treeInstance = terrain.terrainData.treeInstances[i]; if (treeInstance.prototypeIndex < treePrototypeIndex) { newTreeInstanceList.Add(treeInstance); } else if (treeInstance.prototypeIndex > treePrototypeIndex) { treeInstance.prototypeIndex = treeInstance.prototypeIndex - 1; newTreeInstanceList.Add(treeInstance); } } if (newTreePrototypes.Count > treePrototypeIndex) { newTreePrototypes.RemoveAt(treePrototypeIndex); } terrain.terrainData.treeInstances = newTreeInstanceList.ToArray(); terrain.terrainData.treePrototypes = newTreePrototypes.ToArray(); terrain.terrainData.RefreshPrototypes(); if (removeSO) { base.DeletePrototype(prototype, removeSO); } GeneratePrototypes(false); if (!removeSO) { base.DeletePrototype(prototype, removeSO); } } else { base.DeletePrototype(prototype, removeSO); } }
public virtual void DeletePrototype(GPUInstancerPrototype prototype, bool removeSO = true) { #if UNITY_EDITOR UnityEditor.Undo.RecordObject(this, "Delete prototype"); #endif prototypeList.Remove(prototype); if (removeSO && prototype.useGeneratedBillboard && prototype.billboard != null) { if (GPUInstancerConstants.gpuiSettings.billboardAtlasBindings.DeleteBillboardTextures(prototype)) { prototype.billboard = null; } } }
/// <summary> /// SetInstanceCount can be used to discard instances that are indexed higher than the given index count /// </summary> /// <param name="manager">GPUI Manager</param> /// <param name="prototype">GPUI Prototype</param> /// <param name="instanceCount">New instance count to set on the runtime data</param> public static void SetInstanceCount(GPUInstancerManager manager, GPUInstancerPrototype prototype, int instanceCount) { GPUInstancerRuntimeData runtimeData = manager.GetRuntimeData(prototype, true); if (runtimeData == null) { return; } if (instanceCount > runtimeData.bufferSize) { Debug.LogError("Instance count can not be higher than the buffer size."); return; } runtimeData.instanceCount = instanceCount; }
public override void DrawGPUInstancerPrototypeInfo(GPUInstancerPrototype selectedPrototype) { if (selectedPrototype is GPUInstancerDetailPrototype) { GPUInstancerDetailManagerEditor.DrawGPUInstancerPrototypeInfo(selectedPrototype, (string t) => { DrawHelpText(t); }, _mapMagicIntegration, null, _mapMagicIntegration.shaderBindings, null, _mapMagicIntegration.terrainSettings, _mapMagicIntegration.detailLayer); } else if (selectedPrototype is GPUInstancerTreePrototype) { GPUInstancerTreeManagerEditor.DrawGPUInstancerPrototypeInfo(selectedPrototype, (string t) => { DrawHelpText(t); }, _mapMagicIntegration, null, _mapMagicIntegration.shaderBindings, null, _mapMagicIntegration.terrainSettings); } else { GPUInstancerPrefabManagerEditor.DrawGPUInstancerPrototypeInfo(selectedPrototype, (string t) => { DrawHelpText(t); }); } }
public void DrawGPUInstancerPrototypeAddButtonTextMode() { Rect prototypeRect = GUILayoutUtility.GetRect(PROTOTYPE_TEXT_RECT_SIZE_X, PROTOTYPE_TEXT_RECT_SIZE_Y, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false)); Rect iconRect = new Rect(prototypeRect.position + PROTOTYPE_RECT_PADDING_VECTOR, PROTOTYPE_TEXT_RECT_SIZE_VECTOR); GPUInstancerEditorConstants.DrawColoredButton(GPUInstancerEditorConstants.Contents.addTextMode, GPUInstancerEditorConstants.Colors.lightBlue, Color.white, FontStyle.Bold, iconRect, () => { _pickerOverride = null; pickerControlID = EditorGUIUtility.GetControlID(FocusType.Passive) + 100; ShowObjectPicker(); }, true, true, (o) => { AddPickerObject(o); }); }
public static bool CheckForBillboardExtentions(GPUInstancerPrototype selectedPrototype, GPUInstancerBillboardAtlasBindings billboardAtlasBindings) { bool hasExtentionBillboard = false; if (GPUInstancerDefines.billboardExtentions != null && GPUInstancerDefines.billboardExtentions.Count > 0) { foreach (Extention.GPUInstancerBillboardExtention billboardExtention in GPUInstancerDefines.billboardExtentions) { try { if (billboardExtention.IsBillboardAdded(selectedPrototype.prefabObject)) { Mesh generatedMesh = billboardExtention.GetBillboardMesh(selectedPrototype.prefabObject); Material generatedMaterial = billboardExtention.GetBillboardMaterial(selectedPrototype.prefabObject); bool isInLODGroup = billboardExtention.IsInLODGroup(selectedPrototype.prefabObject); if (generatedMesh != null && generatedMaterial != null) { if (selectedPrototype.billboard == null) { selectedPrototype.billboard = new GPUInstancerBillboard(); } selectedPrototype.useGeneratedBillboard = true; selectedPrototype.billboard.useCustomBillboard = true; selectedPrototype.billboard.customBillboardInLODGroup = isInLODGroup; selectedPrototype.billboard.customBillboardMesh = generatedMesh; selectedPrototype.billboard.customBillboardMaterial = generatedMaterial; hasExtentionBillboard = true; break; } } } catch (System.Exception e) { EditorUtility.ClearProgressBar(); Debug.LogError("Error generating billboard: " + e.Message + " StackTrace:" + e.StackTrace); } } } return(hasExtentionBillboard); }
/// <summary> /// Generates instancing renderer data for a given GameObject, at the first LOD level. /// </summary> /// <param name="gameObject">GameObject</param> /// <param name="settings">GPU Instancer settings to find appropriate shader for materials</param> /// <param name="includeChildren">if true, renderers for all found children of this gameObject will be created as well</param> public bool CreateRenderersFromGameObject(GPUInstancerPrototype prototype, GPUInstancerShaderBindings shaderBindings) { if (prototype.prefabObject == null) { return(false); } if (prototype.prefabObject.GetComponent <LODGroup>() != null) { return(GenerateLODsFromLODGroup(prototype.prefabObject.GetComponent <LODGroup>(), shaderBindings, prototype.isShadowCasting)); } else { if (instanceLODs == null || instanceLODs.Count == 0) { AddLod(); } return(CreateRenderersFromGameObject(0, prototype.prefabObject, shaderBindings, prototype.isShadowCasting)); } }
public override void DrawPrefabField(GPUInstancerPrototype selectedPrototype) { EditorGUILayout.BeginHorizontal(); base.DrawPrefabField(selectedPrototype); if (!Application.isPlaying) { Rect prototypeRect = GUILayoutUtility.GetRect(120, 20, GUILayout.ExpandWidth(false), GUILayout.ExpandHeight(false)); GPUInstancerEditorConstants.DrawColoredButton(GPUInstancerEditorConstants.Contents.editPrefab, GPUInstancerEditorConstants.Colors.green, Color.white, FontStyle.Bold, prototypeRect, () => { _pickerOverride = selectedPrototype; pickerControlID = EditorGUIUtility.GetControlID(FocusType.Passive) + 100; ShowObjectPicker(); }, true, true, (o) => { AddPickerObject(o, selectedPrototype); prototypeContents = null; }); } EditorGUILayout.EndHorizontal(); }
public void DrawGPUInstancerPrototypeButton(GPUInstancerPrototype prototype, GUIContent prototypeContent) { base.DrawGPUInstancerPrototypeButton(prototype, prototypeContent, _manager.selectedPrototypeList.Contains(prototype), () => { if (_manager.selectedPrototypeList.Count == 1 && Event.current.shift) { int oldIndex = prototypeList.IndexOf(_manager.selectedPrototypeList[0]); int newIndex = prototypeList.IndexOf(prototype); for (int i = (oldIndex < newIndex ? oldIndex : newIndex); i <= (oldIndex < newIndex ? newIndex : oldIndex); i++) { if (!_manager.selectedPrototypeList.Contains(prototypeList[i])) { _manager.selectedPrototypeList.Add(prototypeList[i]); } } } else if (Event.current.control) { if (_manager.selectedPrototypeList.Contains(prototype)) { _manager.selectedPrototypeList.Remove(prototype); } else { _manager.selectedPrototypeList.Add(prototype); } } else { _manager.selectedPrototypeList.Clear(); _manager.selectedPrototypeList.Add(prototype); } UpdatePrototypeSelection(); GUI.FocusControl(prototypeContent.tooltip); }, _manager.isPrototypeTextMode); }
public Texture GetPreview(GPUInstancerPrototype prototype) { UnityEngine.Object previewObject = GetPreviewObject(prototype); if (previewObject == null) { return(null); } //Texture2D preview = AssetPreview.GetAssetPreview(previewObject); //if (preview != null) //{ // // Copy preview texture so that if unity destroys it we have our own texture reference // Texture2D newTx = new Texture2D(preview.width, preview.height); // newTx.SetPixels(preview.GetPixels()); // newTx.Apply(); // return newTx; //} if (previewObject is Texture2D) { return(GetPreviewTextureFromTexture2D((Texture2D)previewObject)); } return(GetPreviewTexture(prototype)); }