private void OnGUI()
    {
        VolumeRenderedObject volRend = FindObjectOfType <VolumeRenderedObject>();

        if (volRend == null)
        {
            return;
        }
        tf = volRend.transferFunction;

        Color oldColour = GUI.color;
        float bgWidth   = Mathf.Min(this.position.width - 20.0f, (this.position.height - 50.0f) * 2.0f);
        Rect  bgRect    = new Rect(0.0f, 0.0f, bgWidth, bgWidth * 0.5f);

        tf.GenerateTexture();

        histogramMaterial.SetTexture("_TFTex", tf.GetTexture());
        histogramMaterial.SetTexture("_HistTex", tf.histogramTexture);
        Graphics.DrawTexture(bgRect, tf.GetTexture(), histogramMaterial);

        Texture2D tfTexture = tf.GetTexture();

        colorBarMaterial.SetTexture("_TFTex", tf.GetTexture());
        Graphics.DrawTexture(new Rect(bgRect.x, bgRect.y + bgRect.height + 20, bgRect.width, 20.0f), tfTexture, colorBarMaterial);

        // Colour control points
        for (int iCol = 0; iCol < tf.colourControlPoints.Count; iCol++)
        {
            ControlPointColor colPoint = tf.colourControlPoints[iCol];
            Rect ctrlBox = new Rect(bgRect.x + bgRect.width * colPoint.dataValue, bgRect.y + bgRect.height + 20, 10, 20);
            GUI.color             = Color.red;
            GUI.skin.box.fontSize = 8;
            GUI.Box(ctrlBox, "|");
            if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && ctrlBox.Contains(new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y)))
            {
                movingColPointIndex   = iCol;
                selectedColPointIndex = iCol;
            }
            else if (movingColPointIndex == iCol)
            {
                colPoint.dataValue = Mathf.Clamp((Event.current.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f);
            }
            tf.colourControlPoints[iCol] = colPoint;
        }

        // Alpha control points
        for (int iAlpha = 0; iAlpha < tf.alphaControlPoints.Count; iAlpha++)
        {
            ControlPointAlpha alphaPoint = tf.alphaControlPoints[iAlpha];
            Rect ctrlBox = new Rect(bgRect.x + bgRect.width * alphaPoint.dataValue, bgRect.y + (1.0f - alphaPoint.alphaValue) * bgRect.height, 10, 10);
            GUI.color             = oldColour;
            GUI.skin.box.fontSize = 6;
            GUI.Box(ctrlBox, "a");
            if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && ctrlBox.Contains(new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y)))
            {
                movingAlphaPointIndex = iAlpha;
            }
            else if (movingAlphaPointIndex == iAlpha)
            {
                alphaPoint.dataValue  = Mathf.Clamp((Event.current.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f);
                alphaPoint.alphaValue = Mathf.Clamp(1.0f - (Event.current.mousePosition.y - bgRect.y) / bgRect.height, 0.0f, 1.0f);
            }
            tf.alphaControlPoints[iAlpha] = alphaPoint;
        }

        if (Event.current.type == EventType.MouseUp)
        {
            movingColPointIndex   = -1;
            movingAlphaPointIndex = -1;
        }

        if (Event.current.type == EventType.MouseDown && Event.current.button == 1)
        {
            if (bgRect.Contains(new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y)))
            {
                tf.alphaControlPoints.Add(
                    tf.CreateControlPointAlpha(
                        Mathf.Clamp((Event.current.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f),
                        Mathf.Clamp(1.0f - (Event.current.mousePosition.y - bgRect.y) / bgRect.height, 0.0f, 1.0f)
                        ));
            }
            else
            {
                tf.colourControlPoints.Add(tf.CreateControlPointColor(Mathf.Clamp((Event.current.mousePosition.x - bgRect.x) / bgRect.width, 0.0f, 1.0f), Random.ColorHSV()));
            }
            selectedColPointIndex = -1;
        }

        if (selectedColPointIndex != -1)
        {
            ControlPointColor colPoint = tf.colourControlPoints[selectedColPointIndex];
            colPoint.colourValue = EditorGUI.ColorField(new Rect(bgRect.x, bgRect.y + bgRect.height + 50, 100.0f, 40.0f), colPoint.colourValue);
            tf.colourControlPoints[selectedColPointIndex] = colPoint;
        }

        // TEST!!! TODO
        volRend.GetComponent <MeshRenderer>().sharedMaterial.SetTexture("_TFTex", tfTexture);
        volRend.GetComponent <MeshRenderer>().sharedMaterial.DisableKeyword("TF2D_ON");

        GUI.color = oldColour;
    }
    private void OnGUI()
    {
        VolumeRenderedObject volRend = FindObjectOfType <VolumeRenderedObject>();

        if (volRend == null)
        {
            return;
        }

        if (hist2DTex == null)
        {
            hist2DTex = HistogramTextureGenerator.Generate2DHistogramTexture(volRend.dataset);
        }

        TransferFunction2D tf2d = volRend.transferFunction2D;

        // Calculate GUI width (minimum of window width and window height * 2)
        float bgWidth = Mathf.Min(this.position.width - 20.0f, (this.position.height - 250.0f) * 2.0f);
        // Draw the histogram
        Rect histRect = new Rect(0.0f, 0.0f, bgWidth, bgWidth * 0.5f);

        Graphics.DrawTexture(histRect, hist2DTex);
        // Draw the TF texture (showing the rectangles)
        tfGUIMat.SetTexture("_TFTex", tf2d.GetTexture());
        Graphics.DrawTexture(histRect, tf2d.GetTexture(), tfGUIMat);

        // Handle mouse click in box
        for (int iBox = 0; iBox < tf2d.boxes.Count; iBox++)
        {
            TransferFunction2D.TF2DBox box = tf2d.boxes[iBox];
            Rect boxRect = new Rect(histRect.x + box.rect.x * histRect.width, histRect.y + (1.0f - box.rect.height - box.rect.y) * histRect.height, box.rect.width * histRect.width, box.rect.height * histRect.height);
            if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && boxRect.Contains(new Vector2(Event.current.mousePosition.x, Event.current.mousePosition.y)))
            {
                selectedBoxIndex = iBox;
            }
        }

        float startX = histRect.x;
        float startY = histRect.y + histRect.height + 10;

        // Show GUI for editing selected rectangle
        if (selectedBoxIndex != -1)
        {
            EditorGUI.BeginChangeCheck();
            TransferFunction2D.TF2DBox box = tf2d.boxes[selectedBoxIndex];
            float oldX = box.rect.x;
            float oldY = box.rect.y;
            box.rect.x      = EditorGUI.Slider(new Rect(startX, startY, 200.0f, 20.0f), "x", box.rect.x, 0.0f, 0.99f);
            box.rect.width  = EditorGUI.Slider(new Rect(startX + 220.0f, startY, 200.0f, 20.0f), "width", oldX + box.rect.width, box.rect.x + 0.01f, 1.0f) - box.rect.x;
            box.rect.y      = EditorGUI.Slider(new Rect(startX, startY + 50, 200.0f, 20.0f), "y", box.rect.y, 0.0f, 1.0f);
            box.rect.height = EditorGUI.Slider(new Rect(startX + 220.0f, startY + 50, 200.0f, 20.0f), "height", oldY + box.rect.height, box.rect.y + 0.01f, 1.0f) - box.rect.y;
            box.colour      = EditorGUI.ColorField(new Rect(startX + 450.0f, startY + 10, 100.0f, 20.0f), box.colour);
            box.minAlpha    = EditorGUI.Slider(new Rect(startX + 450.0f, startY + 30, 200.0f, 20.0f), "min alpha", box.minAlpha, 0.0f, 1.0f);
            box.alpha       = EditorGUI.Slider(new Rect(startX + 450.0f, startY + 60, 200.0f, 20.0f), "max alpha", box.alpha, 0.0f, 1.0f);

            tf2d.boxes[selectedBoxIndex] = box;
            needsRegenTexture           |= EditorGUI.EndChangeCheck();
        }
        else
        {
            EditorGUI.LabelField(new Rect(startX, startY, this.position.width - startX, 50.0f), "Select a rectangle in the above view, or add a new one.");
        }

        // Add new rectangle
        if (GUI.Button(new Rect(startX, startY + 100, 150.0f, 40.0f), "Add rectangle"))
        {
            tf2d.AddBox(0.1f, 0.1f, 0.8f, 0.8f, Color.white, 0.5f);
            needsRegenTexture = true;
        }
        // Remove selected shape
        if (selectedBoxIndex != -1)
        {
            if (GUI.Button(new Rect(startX, startY + 150, 150.0f, 40.0f), "Remove selected shape"))
            {
                tf2d.boxes.RemoveAt(selectedBoxIndex);
                needsRegenTexture = true;
            }
        }

        // TODO: regenerate on add/remove/modify (and do it async)
        if (needsRegenTexture)
        {
            tf2d.GenerateTexture();
            needsRegenTexture = false;
        }
        volRend.GetComponent <MeshRenderer>().sharedMaterial.SetTexture("_TFTex", tf2d.GetTexture());
        volRend.GetComponent <MeshRenderer>().sharedMaterial.EnableKeyword("TF2D_ON");

        return;
    }