Exemple #1
0
 public static void RegisterIndirectInstancedAsset(IndirectInstancedAsset assetToRegister)
 {
     if (!m_registeredInstancedAssets.Contains(assetToRegister))
     {
         m_assetsToRegister.Add(assetToRegister);
     }
 }
Exemple #2
0
        private static bool DetectInstancedAssets()
        {
            if (m_pickingColorRT != null && m_pickingColorTex != null && IsInSceneBounds(m_mousePosition, m_trueScreenDimensions))
            {
                RenderTexture currentRT = RenderTexture.active;
                //Graphics.Blit(m_pickingColorRT, m_debugRT);
                RenderTexture.active = m_pickingColorRT;
                m_pickingColorTex.ReadPixels(new Rect(m_mousePosition.x, m_trueScreenDimensions.y - m_mousePosition.y, 1, 1), 0, 0, false);
                RenderTexture.active = currentRT;

                Vector2 decoded = Vector2.zero;
                bool    instancedAssetDetected = DecodeInstanceFromColor(m_pickingColorTex.GetPixel(0, 0), ref decoded);
                if (instancedAssetDetected)
                {
                    int objectID   = (int)decoded.x;
                    int instanceID = (int)decoded.y;
                    //Debug.Log("Object ID is: " + objectID + " and Instance ID is: " + instanceID);
                    IndirectInstancedAsset selectedAsset = m_registeredInstancedAssets[objectID];
                    Vector3 position = selectedAsset.m_instanceData.m_positions[instanceID];
                    //Debug.Log("Position of selected asset is: " + position.ToString("f3"));
                }
                return(instancedAssetDetected);
            }
            return(false);
        }
Exemple #3
0
        private static void OnUnregisterIndirectInstancedAsset(IndirectInstancedAsset assetToUnregister)
        {
            Debug.Log("Unregistered an indirect instanced asset");

            //successfully unregistering an asset implies the indexes of assets in the registered list might change, which will change objectIDs
            //the shaders global objectID parameter must be updated to reflect this change
            DeselectInstancedAssets();

            IndirectInstancedAsset asset;

            Material[][] toUpdate;
            for (int objectID = 0; objectID < m_registeredInstancedAssets.Count; objectID++)
            {
                asset    = m_registeredInstancedAssets[objectID];
                toUpdate = m_registeredMaterialArrays[asset];
                for (int i = 0; i < toUpdate.Length; i++)
                {
                    for (int j = 0; j < toUpdate[i].Length; j++)
                    {
                        toUpdate[i][j].SetFloat("_ObjectID", objectID);
                    }
                }
            }

            if (m_registeredCommandBuffers != null && m_registeredCommandBuffers.ContainsKey(assetToUnregister))
            {
                CommandBuffer toClear = m_registeredCommandBuffers[assetToUnregister];
                if (toClear != null && m_sceneWindowInstance.m_debugCamera != null)
                {
                    m_sceneWindowInstance.m_debugCamera.RemoveCommandBuffer(CameraEvent.BeforeImageEffects, toClear);
                    toClear.Clear();
                }
                m_registeredCommandBuffers.Remove(assetToUnregister);
            }

            if (m_registeredMaterialArrays != null && m_registeredMaterialArrays.ContainsKey(assetToUnregister))
            {
                Material[][] toClear = m_registeredMaterialArrays[assetToUnregister];
                if (toClear != null)
                {
                    ClearObjectArray <Material>(toClear, x => { DestroyImmediate(x, false); Debug.Log("Destroying Material"); });
                }
                m_registeredMaterialArrays.Remove(assetToUnregister);
            }

            if (m_registeredEditorComputeBuffers != null && m_registeredEditorComputeBuffers.ContainsKey(assetToUnregister))
            {
                ComputeBuffer[] toClear = m_registeredEditorComputeBuffers[assetToUnregister];
                if (toClear != null)
                {
                    ClearObjectArray <ComputeBuffer>(toClear, x => { if (x != null)
                                                                     {
                                                                         x.Release(); x = null;
                                                                     }
                                                     });
                }
                m_registeredEditorComputeBuffers.Remove(assetToUnregister);
            }
        }
Exemple #4
0
 public static void UnregisterIndirectInstancedAsset(IndirectInstancedAsset assetToUnregister)
 {
     m_assetsToRegister.Remove(assetToUnregister);
     if (m_registeredInstancedAssets.Remove(assetToUnregister))
     {
         OnUnregisterIndirectInstancedAsset(assetToUnregister);
     }
 }
Exemple #5
0
        private static void OnRegisterIndirectInstancedAsset(IndirectInstancedAsset assetToRegister)
        {
            m_registeredInstancedAssets.Add(assetToRegister);
            Debug.Log("Registered an indirect instanced asset");

            int objectID = m_registeredInstancedAssets.IndexOf(assetToRegister);
            int numLods  = assetToRegister.m_LodSettings.Length;

            //initialize materials and gpu buffers, and bind the gpu buffers to their respective materials
            Material[][]    colorPickingMatArray = new Material[numLods][];
            ComputeBuffer[] editorAppendBuffer   = new ComputeBuffer[numLods];
            for (int i = 0; i < numLods; i++)
            {
                editorAppendBuffer[i] = new ComputeBuffer(assetToRegister.m_instanceCount, sizeof(float), ComputeBufferType.Counter);
                assetToRegister.SetComputeBuffer(editorAppendBuffer[i], "lod" + i + "IDBuffer");

                colorPickingMatArray[i] = new Material[assetToRegister.m_LodSettings[i].materialReferences.Length];
                for (int j = 0; j < colorPickingMatArray[i].Length; j++)
                {
                    colorPickingMatArray[i][j] = new Material(Shader.Find("JacksInstancing/ColorPickerShader"));
                    colorPickingMatArray[i][j].SetBuffer("batchDataBuffer", assetToRegister.m_appendBuffers[i]);
                    colorPickingMatArray[i][j].SetBuffer("instanceIDBuffer", editorAppendBuffer[i]);

                    int cullMode = (int)assetToRegister.m_LodSettings[i].materialReferences[j].editorFaceCulling;
                    colorPickingMatArray[i][j].SetInt("_CullMode", cullMode);

                    colorPickingMatArray[i][j].SetFloat("_ObjectID", objectID);

                    Debug.Log("Pass count is: " + assetToRegister.m_LodSettings[i].materialReferences[j].material.passCount);
                    for (int k = 0; k < assetToRegister.m_LodSettings[i].materialReferences[j].material.passCount; k++)
                    {
                        Debug.Log(assetToRegister.m_LodSettings[i].materialReferences[j].material.GetPassName(k));
                    }
                }
            }
            m_registeredMaterialArrays.Add(assetToRegister, colorPickingMatArray);
            m_registeredEditorComputeBuffers.Add(assetToRegister, editorAppendBuffer);

            //initialize the command buffer to draw this instanced asset
            CommandBuffer pickingColorCommand = new CommandBuffer();

            pickingColorCommand.name = assetToRegister.name + " Color Picking Draw";

            pickingColorCommand.SetRenderTarget(m_pickingColorRT);
            for (int i = 0; i < numLods; i++)
            {
                for (int j = 0; j < assetToRegister.m_LodSettings[i].mesh.subMeshCount; j++)
                {
                    if (colorPickingMatArray[i][j] != null)
                    {
                        pickingColorCommand.DrawMeshInstancedIndirect(assetToRegister.m_LodSettings[i].mesh, j, colorPickingMatArray[i][j], 0, assetToRegister.m_argsBuffersArray[i][j], 0);
                    }
                }
            }

            m_sceneWindowInstance.m_debugCamera.AddCommandBuffer(CameraEvent.BeforeImageEffects, pickingColorCommand);
            m_registeredCommandBuffers.Add(assetToRegister, pickingColorCommand);
        }
        void OnGUI()
        {
            if (m_thisWindow == null)
            {
                m_thisWindow = (ObjectSpawner)EditorWindow.GetWindow(typeof(ObjectSpawner));
            }
            if (m_thisWindow != null)
            {
                m_thisWindow.minSize = m_minWindowSize;
            }

            //selectedStyle = EditorStyles.miniButton;
            //selectedStyle.normal.background = Texture2D.blackTexture;

            GUILayout.Label("Jack's Custom Instancing Manager", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            int registeredCount = SceneViewInstancing.m_registeredInstancedAssets.Count;

            for (int i = 0; i < registeredCount; i++)
            {
                IndirectInstancedAsset asset = SceneViewInstancing.m_registeredInstancedAssets[i];
                if (!m_activeIcons.Exists(x => x.asset == asset))
                {
                    SelectableIcon newIcon = new SelectableIcon();
                    newIcon.asset      = asset;
                    newIcon.icon       = null;
                    newIcon.isSelected = false;
                    m_activeIcons.Add(newIcon);
                }
            }

            //repaint unloaded icons and remove icons of assets that are no longer active in the scene
            for (int i = 0; i < m_activeIcons.Count; i++)
            {
                Mesh instancedObject = m_activeIcons[i].asset.m_LodSettings[0].mesh;
                if (instancedObject != null)
                {
                    bool           isLoadingAssetPreview = AssetPreview.IsLoadingAssetPreview(instancedObject.GetInstanceID());
                    SelectableIcon icon = m_activeIcons[i];
                    icon.icon = AssetPreview.GetAssetPreview(instancedObject);
                    if (!icon.icon)
                    {
                        // We have a static preview it just hasn't been loaded yet. Repaint until we have it loaded.
                        if (isLoadingAssetPreview)
                        {
                            Repaint();
                        }
                        icon.icon = AssetPreview.GetMiniThumbnail(instancedObject);
                    }
                    m_activeIcons[i] = icon; //we cannot modify 1 part of a struct, we need to make a copy, modify it, then set the original to the copy
                }

                IndirectInstancedAsset asset = m_activeIcons[i].asset;
                if (!SceneViewInstancing.m_registeredInstancedAssets.Contains(asset))
                {
                    m_activeIcons.RemoveAt(i);
                }
            }

            int windowWidth = (int)EditorGUIUtility.currentViewWidth;
            int numColumns  = Mathf.FloorToInt(windowWidth / m_buttonDimension);
            int numRows     = Mathf.CeilToInt((float)registeredCount / numColumns);

            GUILayout.BeginArea(new Rect(10, 40, numColumns * m_buttonDimension, numRows * m_buttonDimension), Texture2D.whiteTexture, EditorStyles.helpBox);
            for (int i = 0; i < m_activeIcons.Count; i++)
            {
                if (i % numColumns == 0)
                {
                    GUILayout.BeginHorizontal();
                }

                SelectableIcon icon = m_activeIcons[i];
                if (icon.isSelected)
                {
                    GUI.backgroundColor = Color.blue;
                }
                else
                {
                    GUI.backgroundColor = Color.white;
                }

                if (GUILayout.Button(icon.icon, GUILayout.Width(64), GUILayout.Height(64)))
                {
                    icon.isSelected  = !icon.isSelected;
                    m_activeIcons[i] = icon;
                    Debug.Log(icon.isSelected);
                }

                if (i % numColumns == (numColumns - 1))
                {
                    GUILayout.EndHorizontal();
                }
            }
            GUILayout.EndArea();
        }
Exemple #7
0
        private static void DrawHandle()
        {
            Tools.hidden = false;
            if (m_selectedInstancedAssets.Count > 0)
            {
                Tools.hidden = true;

                Vector2 lastSelectedInstance            = m_lastSelectedInstancedObject;
                IndirectInstancedAsset asset            = m_registeredInstancedAssets[(int)lastSelectedInstance.x];
                Vector3    lastSelectedInstancePosition = asset.m_instanceData.m_positions[(int)lastSelectedInstance.y];
                Vector4    vec4Rotation = asset.m_instanceData.m_rotations[(int)lastSelectedInstance.y];
                Quaternion lastSelectedInstanceRotation = InstancingUtilities.QuaternionFromVector(vec4Rotation);

                if (Tools.pivotMode == PivotMode.Center)
                {
                    Bounds selectedObjectsBounds = new Bounds(lastSelectedInstancePosition, Vector3.zero);
                    for (int i = 0; i < m_selectedInstancedAssets.Count; i++)
                    {
                        lastSelectedInstance = m_selectedInstancedAssets[i];
                        asset = m_registeredInstancedAssets[(int)lastSelectedInstance.x];
                        lastSelectedInstancePosition = asset.m_instanceData.m_positions[(int)lastSelectedInstance.y];
                        selectedObjectsBounds.Encapsulate(lastSelectedInstancePosition);
                    }
                    for (int i = 0; i < Selection.transforms.Length; i++)
                    {
                        selectedObjectsBounds.Encapsulate(Selection.transforms[i].position);
                    }
                    lastSelectedInstancePosition = selectedObjectsBounds.center;
                }

                float handleSize = HandleUtility.GetHandleSize(lastSelectedInstancePosition);

                Quaternion previousRotation;
                if (Tools.pivotRotation == PivotRotation.Global)
                {
                    previousRotation = Tools.handleRotation;
                }
                else
                {
                    previousRotation = lastSelectedInstanceRotation;
                }

                EditorGUI.BeginChangeCheck();
                Transform[] selectedGameObjects = Selection.transforms;
                switch (Tools.current)
                {
                case Tool.Move:

                    if (m_currentEvent.type == EventType.MouseDown)
                    {
                        Debug.Log("Rebuilding initial lists.");
                        //build a list of initial sizes of selected instances
                        m_selectedInitialInstances.Clear();
                        for (int i = 0; i < m_selectedInstancedAssets.Count; i++)
                        {
                            Debug.Log("adding");
                            Vector2 currentInstance = m_selectedInstancedAssets[i];
                            Vector3 position        = m_registeredInstancedAssets[(int)currentInstance.x].m_instanceData.m_positions[(int)currentInstance.y];
                            m_selectedInitialInstances.Add(position);
                            Debug.Log("Count is: " + m_selectedInitialInstances.Count);
                        }

                        //build a list of initial sizes of selected game objects
                        m_selectedInitialGameObjects.Clear();
                        for (int i = 0; i < selectedGameObjects.Length; i++)
                        {
                            Vector3 position = selectedGameObjects[i].localPosition;
                            m_selectedInitialGameObjects.Add(position);
                        }
                    }

                    Vector3 newPosition;
                    if (Tools.pivotRotation == PivotRotation.Global)
                    {
                        newPosition = Handles.PositionHandle(lastSelectedInstancePosition, Quaternion.identity);
                    }
                    else
                    {
                        newPosition = Handles.PositionHandle(lastSelectedInstancePosition, lastSelectedInstanceRotation);
                    }

                    float xAxisMovement = newPosition.x - lastSelectedInstancePosition.x;
                    float yAxisMovement = newPosition.y - lastSelectedInstancePosition.y;
                    float zAxisMovement = newPosition.z - lastSelectedInstancePosition.z;

                    if (EditorGUI.EndChangeCheck())
                    {
                        UndoStateInstance.m_instance.m_lastUsedTool = Tool.Move;
                        //set undo state here, else last used tool will change on mouse down and cause incorrect undo history based on tool swapping
                        UndoStateInstance.m_instance.SetUndoState(m_selectedInitialInstances, m_selectedInstancedAssets);

                        for (int i = 0; i < m_selectedInstancedAssets.Count; i++)
                        {
                            Vector2 currentInstance             = m_selectedInstancedAssets[i];
                            IndirectInstancedAsset currentAsset = m_registeredInstancedAssets[(int)currentInstance.x];

                            Undo.RegisterCompleteObjectUndo(UndoStateInstance.m_instance, "Undo instanced move");
                            UndoStateInstance.m_instance.IncrementModifiedCounter();

                            if (Mathf.Abs(xAxisMovement) > 0.01f)
                            {
                                currentAsset.m_instanceData.m_positions[(int)currentInstance.y].x += xAxisMovement;
                            }
                            if (Mathf.Abs(yAxisMovement) > 0.01f)
                            {
                                currentAsset.m_instanceData.m_positions[(int)currentInstance.y].y += yAxisMovement;
                            }
                            if (Mathf.Abs(zAxisMovement) > 0.01f)
                            {
                                currentAsset.m_instanceData.m_positions[(int)currentInstance.y].z += zAxisMovement;
                            }

                            if (Mathf.Abs(xAxisMovement) > 0.01f || Mathf.Abs(yAxisMovement) > 0.01f || Mathf.Abs(zAxisMovement) > 0.01f)
                            {
                                currentAsset.AddDirtyPosition((int)currentInstance.y);
                            }
                        }

                        Undo.RecordObjects(selectedGameObjects, "Undo game object move");
                        for (int i = 0; i < selectedGameObjects.Length; i++)
                        {
                            Vector3 displacedPosition = selectedGameObjects[i].position;
                            if (Mathf.Abs(xAxisMovement) > 0.01f)
                            {
                                displacedPosition.x += xAxisMovement;
                            }
                            if (Mathf.Abs(yAxisMovement) > 0.01f)
                            {
                                displacedPosition.y += yAxisMovement;
                            }
                            if (Mathf.Abs(zAxisMovement) > 0.01f)
                            {
                                displacedPosition.z += zAxisMovement;
                            }

                            selectedGameObjects[i].position = displacedPosition;
                        }
                    }
                    break;

                case Tool.Rotate:

                    //allows rotation back to (0,0,0) with shift + n
                    if (m_currentEvent.keyCode == KeyCode.N && m_currentEvent.shift)
                    {
                        for (int i = 0; i < m_selectedInstancedAssets.Count; i++)
                        {
                            Vector2 currentInstance             = m_selectedInstancedAssets[i];
                            IndirectInstancedAsset currentAsset = m_registeredInstancedAssets[(int)currentInstance.x];
                            currentAsset.m_instanceData.m_rotations[(int)currentInstance.y] = new Vector4(0, 0, 0, 1);     //The identity quaternion
                            currentAsset.AddDirtyRotation((int)currentInstance.y);
                        }
                        //also reset the gizmo, this isnt really needed as the next frame will already be correct and 1 frame is not noticeable, but added for consistency
                        Tools.handleRotation = Quaternion.identity;
                        previousRotation     = Quaternion.identity;
                    }

                    if (m_currentEvent.type == EventType.MouseDown)
                    {
                        Debug.Log("Rebuilding initial lists.");
                        //build a list of initial sizes of selected instances
                        m_selectedInitialInstances.Clear();
                        for (int i = 0; i < m_selectedInstancedAssets.Count; i++)
                        {
                            Vector2 currentInstance = m_selectedInstancedAssets[i];
                            Vector4 rotation        = m_registeredInstancedAssets[(int)currentInstance.x].m_instanceData.m_rotations[(int)currentInstance.y];
                            m_selectedInitialInstances.Add(rotation);
                        }

                        //build a list of initial sizes of selected game objects
                        m_selectedInitialGameObjects.Clear();
                        for (int i = 0; i < selectedGameObjects.Length; i++)
                        {
                            Vector4 rotation = InstancingUtilities.VectorFromQuaternion(selectedGameObjects[i].rotation);
                            m_selectedInitialGameObjects.Add(rotation);
                        }
                    }

                    Quaternion newRotation = Handles.RotationHandle(previousRotation, lastSelectedInstancePosition);     //The new rotation value modified by the user's interaction with the handle.
                    if (EditorGUI.EndChangeCheck())
                    {
                        UndoStateInstance.m_instance.m_lastUsedTool = Tool.Rotate;
                        UndoStateInstance.m_instance.SetUndoState(m_selectedInitialInstances, m_selectedInstancedAssets);

                        Quaternion delta = Quaternion.Inverse(previousRotation) * newRotation;
                        for (int i = 0; i < m_selectedInstancedAssets.Count; i++)
                        {
                            Vector2 currentInstance                        = m_selectedInstancedAssets[i];
                            IndirectInstancedAsset currentAsset            = m_registeredInstancedAssets[(int)currentInstance.x];
                            Quaternion             instancedObjectRotation = InstancingUtilities.QuaternionFromVector(currentAsset.m_instanceData.m_rotations[(int)currentInstance.y]);

                            Undo.RegisterCompleteObjectUndo(UndoStateInstance.m_instance, "Undo instanced rotation");
                            UndoStateInstance.m_instance.IncrementModifiedCounter();

                            //lhs happens first, so if we want a local space rotation, we do a delta rotation in the objects frame of reference by object quaternion on lhs
                            //if we want a world space rotation, then lhs is the delta, and the objects rotation happens after, in the world space frame of reference
                            if (Tools.pivotRotation == PivotRotation.Local)
                            {
                                instancedObjectRotation = instancedObjectRotation * delta;
                            }
                            else
                            {
                                instancedObjectRotation = delta * instancedObjectRotation;
                            }

                            currentAsset.m_instanceData.m_rotations[(int)currentInstance.y] = InstancingUtilities.VectorFromQuaternion(instancedObjectRotation);
                            currentAsset.AddDirtyRotation((int)currentInstance.y);
                        }

                        Undo.RecordObjects(selectedGameObjects, "Undo game object rotation");
                        for (int i = 0; i < selectedGameObjects.Length; i++)
                        {
                            Quaternion gameObjectRotation = selectedGameObjects[i].rotation;
                            if (Tools.pivotRotation == PivotRotation.Local)
                            {
                                gameObjectRotation = gameObjectRotation * delta;
                            }
                            else
                            {
                                gameObjectRotation = delta * gameObjectRotation;
                            }
                            selectedGameObjects[i].rotation = gameObjectRotation;
                        }

                        //https://math.stackexchange.com/questions/40164/how-do-you-rotate-a-vector-by-a-unit-quaternion
                        Tools.handleRotation = newRotation;
                    }
                    break;

                case Tool.Scale:

                    //allows scaling back to (1,1,1) with shift + n
                    if (m_currentEvent.keyCode == KeyCode.N && m_currentEvent.shift)
                    {
                        for (int i = 0; i < m_selectedInstancedAssets.Count; i++)
                        {
                            Vector2 currentInstance             = m_selectedInstancedAssets[i];
                            IndirectInstancedAsset currentAsset = m_registeredInstancedAssets[(int)currentInstance.x];
                            currentAsset.m_instanceData.m_positions[(int)currentInstance.y].w = InstancingUtilities.PackScaleVectorToFloat(Vector3.one);
                            currentAsset.AddDirtyScale((int)currentInstance.y);
                        }
                    }

                    if (m_currentEvent.type == EventType.MouseDown)
                    {
                        m_currentScale = Vector3.one;

                        Debug.Log("Rebuilding initial lists.");
                        //build a list of initial sizes of selected instances
                        m_selectedInitialInstances.Clear();
                        for (int i = 0; i < m_selectedInstancedAssets.Count; i++)
                        {
                            Vector2 currentInstance = m_selectedInstancedAssets[i];
                            float   scale           = m_registeredInstancedAssets[(int)currentInstance.x].m_instanceData.m_positions[(int)currentInstance.y].w;
                            m_selectedInitialInstances.Add(new Vector4(scale, 0, 0, 0));
                        }

                        //build a list of initial sizes of selected game objects
                        m_selectedInitialGameObjects.Clear();
                        for (int i = 0; i < selectedGameObjects.Length; i++)
                        {
                            Vector3 scale = selectedGameObjects[i].localScale;
                            m_selectedInitialGameObjects.Add(scale);
                        }
                    }

                    Vector3 newScale = Handles.ScaleHandle(m_currentScale, lastSelectedInstancePosition, lastSelectedInstanceRotation, handleSize);
                    if (EditorGUI.EndChangeCheck())
                    {
                        UndoStateInstance.m_instance.m_lastUsedTool = Tool.Scale;
                        UndoStateInstance.m_instance.SetUndoState(m_selectedInitialInstances, m_selectedInstancedAssets);

                        m_currentScale = newScale;
                        for (int i = 0; i < m_selectedInstancedAssets.Count; i++)
                        {
                            Vector2 currentInstance             = m_selectedInstancedAssets[i];
                            IndirectInstancedAsset currentAsset = m_registeredInstancedAssets[(int)currentInstance.x];

                            Undo.RegisterCompleteObjectUndo(UndoStateInstance.m_instance, "Undo instanced scaling");
                            UndoStateInstance.m_instance.IncrementModifiedCounter();

                            currentAsset.m_instanceData.ModifyScale((int)currentInstance.y, m_currentScale, m_selectedInitialInstances[i].x);

                            currentAsset.AddDirtyScale((int)currentInstance.y);
                        }

                        Undo.RecordObjects(selectedGameObjects, "Undo game object scaling");
                        for (int i = 0; i < selectedGameObjects.Length; i++)
                        {
                            Vector3 objectScale = InstancingUtilities.MultiplyVector3(m_selectedInitialGameObjects[i], m_currentScale);
                            selectedGameObjects[i].localScale = objectScale;
                        }
                    }

                    break;
                }
            }
        }