예제 #1
0
        void cacheClayxelContainer()
        {
            this.clayxelContainerRef = null;
            GameObject parent = this.transform.parent.gameObject;

            ClayContainer clayxel = null;

            for (int i = 0; i < 100; ++i)
            {
                clayxel = parent.GetComponent <ClayContainer>();
                if (clayxel != null)
                {
                    break;
                }
                else
                {
                    parent = parent.transform.parent.gameObject;
                }
            }

            if (clayxel == null)
            {
                Debug.Log("failed to find parent clayxel container");
            }
            else
            {
                this.clayxelContainerRef = new WeakReference(clayxel);
                clayxel.scanSolidsHierarchy();
            }
        }
예제 #2
0
        void inspectMaterial(ClayContainer clayContainer)
        {
            EditorGUI.BeginChangeCheck();

            if (this.materialEditor != null)
            {
                DestroyImmediate(this.materialEditor);
                this.materialEditor = null;
            }

            this.materialEditor = (MaterialEditor)CreateEditor(clayContainer.getMaterial());

            if (this.materialEditor != null)
            {
                this.materialEditor.DrawHeader();
                this.materialEditor.OnInspectorGUI();
            }

            if (EditorGUI.EndChangeCheck())
            {
                clayContainer.updatedMaterialProperties();

                if (this.materialEditor != null)
                {
                    DestroyImmediate(this.materialEditor);
                    this.materialEditor = null;
                }
            }
        }
예제 #3
0
    public void Generate()
    {
        Clear();
        if (baseSprite == null)
        {
            return;
        }
        if (!baseSprite.isReadable)
        {
            Debug.LogError("Texture not set to Read/Write");
        }
        for (var w = 0; w < baseSprite.width; w++)
        {
            for (var h = 0; h < baseSprite.height; h++)
            {
                var pixelColor = baseSprite.GetPixel(w, h);
                if (pixelColor == Color.black)
                {
                    continue;
                }

                var clayPixel  = Instantiate(clayObjectPrefab, transform);
                var clayObject = clayPixel.GetComponent <ClayObject>();
                clayObject.color               = pixelColor;
                clayObject.blend               = blend;
                clayPixel.transform.position   = (new Vector3(w, h, 0) * positioningScale) + positioningOffset;
                clayPixel.transform.localScale = Vector3.one * objectSize;
            }
        }
        ClayContainer.reloadAll();
    }
예제 #4
0
        public void init()
        {
            this.solids.Clear();
            this.changeNumSolids(this.numSolids);
            this.transform.hasChanged = true;

            this.clayxelContainerRef = null;
            GameObject parent = this.transform.parent.gameObject;

            ClayContainer clayxel = null;

            for (int i = 0; i < 100; ++i)
            {
                clayxel = parent.GetComponent <ClayContainer>();
                if (clayxel != null)
                {
                    break;
                }
                else
                {
                    parent = parent.transform.parent.gameObject;
                }
            }

            if (clayxel == null)
            {
                Debug.Log("failed to find parent clayxel container");
            }
            else
            {
                this.clayxelContainerRef = new WeakReference(clayxel);
            }
        }
예제 #5
0
        void Update()
        {
            if (this.counter == 0)
            {
                // here we update the shader parameter that randomizes the finger prints
                ClayContainer clayContainer = this.GetComponent <ClayContainer>();
                Material      clayMaterial  = this.GetComponent <ClayContainer>().getMaterial();

                clayMaterial.SetFloat("_animate", UnityEngine.Random.Range(-100.0f, 100.0f));

                // from here we just move clayObjects around to make some fun anims
                int randomClayObj = UnityEngine.Random.Range(0, this.startPos.Count);
                this.transform.GetChild(randomClayObj).transform.localPosition = this.startPos[randomClayObj] +
                                                                                 new Vector3(UnityEngine.Random.Range(-0.5f, 0.5f),
                                                                                             UnityEngine.Random.Range(-0.1f, 0.1f),
                                                                                             UnityEngine.Random.Range(-0.1f, 0.1f));

                GameObject.Find("hairAnim").transform.localEulerAngles =
                    new Vector3(UnityEngine.Random.Range(0.0f, 360.0f), 2.2f, -7.2f);

                GameObject.Find("clayBoard").transform.localEulerAngles =
                    new Vector3(UnityEngine.Random.Range(-10.0f, 10.0f), 0.0f, 0.0f);

                GameObject.Find("waveAnim").transform.localEulerAngles = new Vector3(this.waveAnimValue, 2.2f, 2.3f);
                this.waveAnimValue -= 30.0f;
            }

            this.counter = (this.counter + 1) % 60;
        }
예제 #6
0
        void updateSingle()
        {
            if (this.solids.Count == 0)
            {
                return;
            }

            Solid solid = this.solids[0];

            ClayContainer container = this.getClayContainer();
            Matrix4x4     invMat    = container.transform.worldToLocalMatrix * this.transform.localToWorldMatrix;

            solid.position.x = invMat[0, 3];
            solid.position.y = invMat[1, 3];
            solid.position.z = invMat[2, 3];

            solid.rotation = invMat.rotation;

            solid.scale.x = Mathf.Abs((this.transform.lossyScale.x / container.transform.lossyScale.x) * 0.5f);
            solid.scale.y = Mathf.Abs((this.transform.lossyScale.y / container.transform.lossyScale.y) * 0.5f);
            solid.scale.z = Mathf.Abs((this.transform.lossyScale.z / container.transform.lossyScale.z) * 0.5f);

            solid.blend = this.blend;

            solid.color.x = this.color.r;
            solid.color.y = this.color.g;
            solid.color.z = this.color.b;

            solid.attrs = this.attrs;

            solid.primitiveType = this.primitiveType;
        }
예제 #7
0
        void inspectMaterial(ClayContainer clayContainer)
        {
            EditorGUI.BeginChangeCheck();

            if (this.materialEditor != null)
            {
                DestroyImmediate(this.materialEditor);
                this.materialEditor = null;
            }

            Material mat = clayContainer.getMaterial();

            if (mat != null)
            {
                this.materialEditor = (MaterialEditor)CreateEditor(mat);
            }

            if (this.materialEditor != null)
            {
                this.materialEditor.DrawHeader();
                this.materialEditor.OnInspectorGUI();
            }

            if (EditorGUI.EndChangeCheck())
            {
                if (!Application.isPlaying)
                {
                    EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                }
            }
        }
예제 #8
0
        static void renameToAnimate(MenuCommand command)
        {
            if (UnityEditor.Selection.gameObjects.Length > 0)
            {
                ClayObject clayObj = UnityEditor.Selection.gameObjects[0].GetComponent <ClayObject>();
                if (clayObj != null)
                {
                    ClayContainer container = clayObj.getClayContainer();
                    ClayContainer._skipHierarchyChanges = true;            // otherwise each rename will trigger onHierarchyChange

                    int numClayObjs = container.getNumClayObjects();

                    for (int i = 0; i < numClayObjs; ++i)
                    {
                        ClayObject currentClayObj = container.getClayObject(i);

                        if (currentClayObj.gameObject.name.StartsWith("clay_"))
                        {
                            container.autoRenameClayObject(currentClayObj);
                            currentClayObj.name = "(" + i + ")" + currentClayObj.gameObject.name;
                        }
                    }

                    ClayContainer._skipHierarchyChanges = false;
                }
            }
        }
예제 #9
0
        void Awake()
        {
            ClayContainer container = this.getClayContainer();

            if (container != null)
            {
                container.scheduleClayObjectsScan();
            }
        }
 void Update()
 {
     if (this.transform.hasChanged)
     {
         this.transform.hasChanged = false;
         ClayContainer clayxel = this.getClayxelContainer();
         clayxel.clayObjectUpdated(this);
     }
 }
예제 #11
0
    void OnLostFocus()
    {
        if (Application.isPlaying)
        {
            return;
        }

        ClayContainer.savePrefs(ClayxelsPrefsWindow.prefs);
        ClayContainer.reloadAll();
    }
예제 #12
0
        void OnDestroy()
        {
            this.invalidated = true;

            ClayContainer clayxel = this.getClayxelContainer();

            if (clayxel != null)
            {
                clayxel.scanSolidsHierarchy();
            }
        }
예제 #13
0
 void SetObjectProperties()
 {
     for (var i = transform.childCount - 1; i >= 0; i--)
     {
         var clayObject = transform.GetChild(i).GetComponent <ClayObject>();
         clayObject.blend = blend;
         clayObject.transform.localScale = Vector3.one * objectSize;
         clayObject.primitiveType        = primitiveType;
     }
     ClayContainer.reloadAll();
 }
예제 #14
0
        public void init()
        {
            this.solids.Clear();
            this.changeNumSolids(this.numSolids);
            this.transform.hasChanged = true;

            ClayContainer oldContainer = null;

            if (this.clayxelContainerRef != null)
            {
                oldContainer = (ClayContainer)this.clayxelContainerRef.Target;
            }

            this.clayxelContainerRef = null;
            if (this.transform.parent == null)
            {
                return;
            }

            GameObject parent = this.transform.parent.gameObject;

            ClayContainer clayxel = null;

            for (int i = 0; i < 100; ++i)
            {
                clayxel = parent.GetComponent <ClayContainer>();
                if (clayxel != null)
                {
                    break;
                }
                else
                {
                    parent = parent.transform.parent.gameObject;
                }
            }

            if (clayxel == null)
            {
                Debug.Log("failed to find parent clayxel container");
            }
            else
            {
                this.clayxelContainerRef = new WeakReference(clayxel);

                if (oldContainer != null && oldContainer != clayxel)
                {
                    clayxel.scheduleClayObjectsScan();
                }
            }

                        #if UNITY_EDITOR
            Undo.undoRedoPerformed += this.onUndoPerformed;
                        #endif
        }
예제 #15
0
    public static void Open()
    {
        if (Application.isPlaying)
        {
            return;
        }

        ClayxelsPrefsWindow.prefs = ClayContainer.loadPrefs();

        ClayxelsPrefsWindow window = (ClayxelsPrefsWindow)EditorWindow.GetWindow(typeof(ClayxelsPrefsWindow));

        window.Show();
    }
예제 #16
0
        void updateOffset()
        {
            ClayContainer container = this.getClayContainer();
            Matrix4x4     invMat    = container.transform.worldToLocalMatrix * this.transform.localToWorldMatrix;

            Vector3    offsetPos = new Vector3(invMat[0, 3], invMat[1, 3], invMat[2, 3]);
            Quaternion offsetRot = invMat.rotation;
            Vector3    offsetScale;

            offsetScale.x = (this.transform.lossyScale.x / container.transform.lossyScale.x) * 0.5f;
            offsetScale.y = (this.transform.lossyScale.y / container.transform.lossyScale.y) * 0.5f;
            offsetScale.z = (this.transform.lossyScale.z / container.transform.lossyScale.z) * 0.5f;

            Vector3 offsetterPos;

            for (int i = 0; i < this.solids.Count; ++i)
            {
                Solid solid = this.solids[i];

                solid.position = offsetPos;

                offsetterPos    = this.offsetter.transform.localPosition;
                offsetterPos.x *= this.offsetter.transform.lossyScale.x / container.transform.lossyScale.x;
                offsetterPos.y *= this.offsetter.transform.lossyScale.y / container.transform.lossyScale.y;
                offsetterPos.z *= this.offsetter.transform.lossyScale.z / container.transform.lossyScale.z;

                offsetPos += offsetRot * offsetterPos;

                solid.rotation = offsetRot;

                offsetRot = offsetRot * this.offsetter.transform.localRotation;

                solid.scale = offsetScale;

                offsetScale.x *= this.offsetter.transform.localScale.x;
                offsetScale.y *= this.offsetter.transform.localScale.y;
                offsetScale.z *= this.offsetter.transform.localScale.z;

                solid.blend = this.blend;

                solid.color.x = this.color.r;
                solid.color.y = this.color.g;
                solid.color.z = this.color.b;

                solid.attrs = this.attrs;

                solid.primitiveType = this.primitiveType;
            }
        }
예제 #17
0
        void Update()
        {
            this.updateSolids(true);

                        #if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                ClayContainer parentContainer = this.GetComponentInParent <ClayContainer>();
                if (parentContainer != this.getClayContainer())
                {
                    this.init();
                }
            }
                        #endif
        }
예제 #18
0
        void OnDestroy()
        {
            this.invalidated = true;

            ClayContainer clayxel = this.getClayContainer();

            if (clayxel != null)
            {
                clayxel.scheduleClayObjectsScan();

                                #if UNITY_EDITOR
                if (!Application.isPlaying)
                {
                    UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                }
                                #endif
            }
        }
예제 #19
0
        void Update()
        {
            if (steppedUpdate != 0)
            {
                updateTimer += Time.deltaTime;
            }

            if (this.transform.hasChanged)
            {
                if (steppedUpdate == 0 || (updateTimer > steppedUpdate))
                {
                    this.transform.hasChanged = false;
                    ClayContainer clayxel = this.getClayxelContainer();
                    clayxel.clayObjectUpdated(this);
                    updateTimer = 0;
                }
            }
        }
예제 #20
0
        void OnDestroy()
        {
            this.invalidated = true;
            this.enabled     = false;

            ClayContainer clayxel = this.getClayContainer();

            if (clayxel != null)
            {
                clayxel.scheduleClayObjectsScan();

                                #if UNITY_EDITOR
                if (!Application.isPlaying)
                {
                    UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                }
                                #endif
            }

                        #if UNITY_EDITOR
            Undo.undoRedoPerformed -= this.onUndoPerformed;
                        #endif
        }
예제 #21
0
    private void Awake()
    {
        if (instance != null)
        {
            Destroy(this);
            return;
        }

        instance = this;

        inEditContainer = FindObjectOfType <ClayContainer>();

        objectLayerMask = LayerMask.GetMask("ClayObject");
        if (objectLayerMask == 0)
        {
            Debug.LogError("ClayVR Error - There is no ClayObject layer, create it.");
        }

        containerLayerMask = LayerMask.GetMask("ClayContainer");
        if (objectLayerMask == 0)
        {
            Debug.LogError("ClayVR Error - There is no ClayContainer layer, create it.");
        }
    }
예제 #22
0
        public override void OnInspectorGUI()
        {
            Claymation claymation = (Claymation)this.target;

            if (claymation.instanceOf == null)
            {
                EditorGUI.BeginChangeCheck();

                TextAsset claymationFile = (TextAsset)EditorGUILayout.ObjectField(new GUIContent("claymation asset", ""), claymation.claymationFile, typeof(TextAsset), true);

                if (EditorGUI.EndChangeCheck())
                {
                    if (claymation.claymationFile != claymationFile)
                    {
                        claymation.claymationFile = claymationFile;
                        claymation.init();
                    }
                }

                if (GUILayout.Button(new GUIContent("reload file", "click this when your claymation file changes and you need to refresh this player")))
                {
                    claymation.init();
                }

                Material material = (Material)EditorGUILayout.ObjectField(new GUIContent("material", "Use the same materials you use on the clayContainers"), claymation.material, typeof(Material), true);
                claymation.material = material;

                if (claymation.getNumFrames() > 1)
                {
                    int frameRate = EditorGUILayout.IntField(new GUIContent("frame rate", "how fast will this claymation play"), claymation.frameRate);

                    claymation.frameRate = frameRate;

                    claymation.playAnim = EditorGUILayout.Toggle(new GUIContent("play anim", "Always play the anim in loop"), claymation.playAnim);

                    int currentFrame = EditorGUILayout.IntField(new GUIContent("frame", ""), claymation.getFrame());
                    if (currentFrame != claymation.getFrame())
                    {
                        claymation.loadFrame(currentFrame);
                    }
                }
            }

            EditorGUILayout.Space();

            Claymation instance = (Claymation)EditorGUILayout.ObjectField(new GUIContent("instance", "Set this to point at another Claymation in scene to make this into an instance and avoid duplicating memory."), claymation.instanceOf, typeof(Claymation), true);

            if (instance != claymation.instanceOf && instance != claymation)
            {
                claymation.instanceOf = instance;
                claymation.init();

                UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                ClayContainer.getSceneView().Repaint();

                if (!Application.isPlaying)
                {
                    EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                }
            }
        }
예제 #23
0
 static void MirrorDuplicate(MenuCommand command)
 {
     ClayContainer.shortcutMirrorDuplicate();
 }
예제 #24
0
        public override void OnInspectorGUI()
        {
            UnityEditor.EditorApplication.QueuePlayerLoopUpdate();

            ClayObject    clayObj = (ClayObject)this.targets[0];
            ClayContainer clayxel = clayObj.getClayContainer();

            if (clayxel == null)
            {
                return;
            }

            EditorGUI.BeginChangeCheck();

            string[] solidsLabels  = clayxel.getSolidsCatalogueLabels();
            int      primitiveType = EditorGUILayout.Popup("solidType", clayObj.primitiveType, solidsLabels);

            float blend = EditorGUILayout.Slider("blend", Mathf.Abs(clayObj.blend) * 100.0f, 0.0f, 100.0f);

            if (clayObj.blend < 0.0f)
            {
                if (blend < 0.001f)
                {
                    blend = 0.001f;
                }

                blend *= -1.0f;
            }

            blend *= 0.01f;
            if (blend > 1.0f)
            {
                blend = 1.0f;
            }
            else if (blend < -1.0f)
            {
                blend = -1.0f;
            }

            GUILayout.BeginHorizontal();

            Color defaultColor = GUI.backgroundColor;

            if (clayObj.blend >= 0.0f)
            {
                GUI.backgroundColor = Color.yellow;
            }

            if (GUILayout.Button(new GUIContent("add", "Additive blend")))
            {
                blend = Mathf.Abs(blend);
            }

            GUI.backgroundColor = defaultColor;

            if (clayObj.blend < 0.0f)
            {
                GUI.backgroundColor = Color.yellow;
            }

            if (GUILayout.Button(new GUIContent("sub", "Subtractive blend")))
            {
                if (blend == 0.0f)
                {
                    blend = 0.0001f;
                }

                blend = blend * -1.0f;
            }

            GUI.backgroundColor = defaultColor;

            GUILayout.EndHorizontal();

            Color color = EditorGUILayout.ColorField("color", clayObj.color);

            Dictionary <string, float> paramValues = new Dictionary <string, float>();

            paramValues["x"] = clayObj.attrs.x;
            paramValues["y"] = clayObj.attrs.y;
            paramValues["z"] = clayObj.attrs.z;
            paramValues["w"] = clayObj.attrs.w;

            List <string[]> parameters  = clayxel.getSolidsCatalogueParameters(primitiveType);
            List <string>   wMaskLabels = new List <string>();

            for (int paramIt = 0; paramIt < parameters.Count; ++paramIt)
            {
                string[] parameterValues = parameters[paramIt];
                string   attr            = parameterValues[0];
                string   label           = parameterValues[1];
                string   defaultValue    = parameterValues[2];

                if (primitiveType != clayObj.primitiveType)
                {
                    // reset to default params when changing primitive type
                    paramValues[attr] = float.Parse(defaultValue, CultureInfo.InvariantCulture);
                }

                if (attr.StartsWith("w"))
                {
                    wMaskLabels.Add(label);
                }
                else
                {
                    paramValues[attr] = EditorGUILayout.FloatField(label, paramValues[attr] * 100.0f) * 0.01f;
                }
            }

            if (wMaskLabels.Count > 0)
            {
                paramValues["w"] = (float)EditorGUILayout.MaskField("options", (int)clayObj.attrs.w, wMaskLabels.ToArray());
            }

            if (EditorGUI.EndChangeCheck())
            {
                ClayContainer._inspectorUpdate();
                ClayContainer._skipHierarchyChanges = true;

                Undo.RecordObjects(this.targets, "changed clayobject");

                for (int i = 1; i < this.targets.Length; ++i)
                {
                    bool       somethingChanged = false;
                    ClayObject currentClayObj   = (ClayObject)this.targets[i];
                    bool       shouldAutoRename = false;

                    if (Mathf.Abs(clayObj.blend - blend) > 0.001f || Mathf.Sign(clayObj.blend) != Mathf.Sign(blend))
                    {
                        currentClayObj.blend = blend;
                        somethingChanged     = true;
                        shouldAutoRename     = true;
                    }

                    if (clayObj.color != color)
                    {
                        currentClayObj.color = color;
                        somethingChanged     = true;
                    }

                    if (clayObj.primitiveType != primitiveType)
                    {
                        currentClayObj.primitiveType = primitiveType;
                        somethingChanged             = true;
                        shouldAutoRename             = true;
                    }

                    if (clayObj.attrs.x != paramValues["x"])
                    {
                        currentClayObj.attrs.x = paramValues["x"];
                        somethingChanged       = true;
                    }

                    if (clayObj.attrs.y != paramValues["y"])
                    {
                        currentClayObj.attrs.y = paramValues["y"];
                        somethingChanged       = true;
                    }

                    if (clayObj.attrs.z != paramValues["z"])
                    {
                        currentClayObj.attrs.z = paramValues["z"];
                        somethingChanged       = true;
                    }

                    if (clayObj.attrs.w != paramValues["w"])
                    {
                        currentClayObj.attrs.w = paramValues["w"];
                        somethingChanged       = true;
                        shouldAutoRename       = true;
                    }

                    if (somethingChanged)
                    {
                        currentClayObj.getClayContainer().clayObjectUpdated(currentClayObj);

                        if (shouldAutoRename)
                        {
                            if (currentClayObj.gameObject.name.StartsWith("clay_"))
                            {
                                clayxel.autoRenameClayObject(currentClayObj);
                            }
                        }
                    }

                    ClayContainer._skipHierarchyChanges = false;
                }

                clayObj.blend         = blend;
                clayObj.color         = color;
                clayObj.primitiveType = primitiveType;
                clayObj.attrs.x       = paramValues["x"];
                clayObj.attrs.y       = paramValues["y"];
                clayObj.attrs.z       = paramValues["z"];
                clayObj.attrs.w       = paramValues["w"];

                if (clayObj.gameObject.name.StartsWith("clay_"))
                {
                    clayxel.autoRenameClayObject(clayObj);
                }

                clayObj.forceUpdate();

                UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                ClayContainer.getSceneView().Repaint();

                if (!Application.isPlaying)
                {
                    EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                }
            }

            EditorGUILayout.Space();

            EditorGUI.BeginChangeCheck();

            ClayObject.ClayObjectMode mode = (ClayObject.ClayObjectMode)EditorGUILayout.EnumPopup("mode", clayObj.mode);

            if (EditorGUI.EndChangeCheck())
            {
                clayObj.setMode(mode);

                UnityEditor.EditorApplication.QueuePlayerLoopUpdate();

                if (!Application.isPlaying)
                {
                    EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                }
            }

            if (clayObj.mode == ClayObject.ClayObjectMode.offset)
            {
                this.drawOffsetMode(clayObj);
            }
            else if (clayObj.mode == ClayObject.ClayObjectMode.spline)
            {
                this.drawSplineMode(clayObj);
            }

            EditorGUILayout.Space();
            GUILayout.BeginHorizontal();
            GUI.enabled = !clayxel.isClayObjectsOrderLocked();
            int clayObjectId = EditorGUILayout.IntField("order", clayObj.clayObjectId);

            GUI.enabled = true;

            if (!clayxel.isClayObjectsOrderLocked())
            {
                if (clayObjectId != clayObj.clayObjectId)
                {
                    int idOffset = clayObjectId - clayObj.clayObjectId;
                    clayxel.reorderClayObject(clayObj.clayObjectId, idOffset);
                }
            }

            if (GUILayout.Button(new GUIContent("↑", "")))
            {
                clayxel.reorderClayObject(clayObj.clayObjectId, -1);
            }
            if (GUILayout.Button(new GUIContent("↓", "")))
            {
                clayxel.reorderClayObject(clayObj.clayObjectId, 1);
            }
            if (GUILayout.Button(new GUIContent("⋮", "")))
            {
                EditorUtility.DisplayPopupMenu(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 0, 0), "Component/Clayxels/ClayObject", null);
            }
            GUILayout.EndHorizontal();
        }
예제 #25
0
        public override void OnInspectorGUI()
        {
            Color defaultColor = GUI.backgroundColor;

            ClayContainer clayxel = (ClayContainer)this.target;

            EditorGUILayout.LabelField("Clayxels V1.31");

            EditorGUILayout.Space();

            string userWarn = clayxel._getUserWarning();

            if (userWarn != "")
            {
                GUIStyle s = new GUIStyle();
                s.wordWrap         = true;
                s.normal.textColor = Color.yellow;
                EditorGUILayout.LabelField(userWarn, s);
            }

            if (clayxel.getNumSolids() > clayxel.getMaxSolids())
            {
                GUIStyle s = new GUIStyle();
                s.wordWrap         = true;
                s.normal.textColor = Color.yellow;
                EditorGUILayout.LabelField("Max solid count exeeded, open Global Config to tweak settings.");
            }

            if (clayxel.instanceOf != null)
            {
                ClayContainer newInstance = (ClayContainer)EditorGUILayout.ObjectField(new GUIContent("instance", "Set this to point at another clayContainer in scene to make this into an instance and avoid having to compute the same thing twice."), clayxel.instanceOf, typeof(ClayContainer), true);

                if (newInstance != clayxel.instanceOf && newInstance != clayxel)
                {
                    clayxel.instanceOf = newInstance;
                    clayxel.init();

                    // UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                    // ClayContainer.getSceneView().Repaint();

                    if (!Application.isPlaying)
                    {
                        EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                    }
                }

                EditorGUILayout.Space();
                if (GUILayout.Button((new GUIContent("global config", ""))))
                {
                    ClayxelsPrefsWindow.Open();
                }

                return;
            }

            if (clayxel.isFrozen())
            {
                if (GUILayout.Button(new GUIContent("defrost clayxels", "Back to live clayxels.")))
                {
                    clayxel.defrostContainersHierarchy();
                    // UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                    // ClayContainer.getSceneView().Repaint();
                }

                EditorGUILayout.Space();
                if (GUILayout.Button((new GUIContent("global config", ""))))
                {
                    ClayxelsPrefsWindow.Open();
                }

                return;
            }

            EditorGUI.BeginChangeCheck();

            int clayxelDetail = EditorGUILayout.IntField(new GUIContent("clayxel detail", "How coarse or finely detailed is your sculpt. Enable Gizmos in your viewport to see the boundaries."), clayxel.getClayxelDetail());

            if (EditorGUI.EndChangeCheck())
            {
                ClayContainer._inspectorUpdate();

                clayxel.setClayxelDetail(clayxelDetail);

                if (!Application.isPlaying)
                {
                    EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                }

                return;
            }

            GUILayout.BeginHorizontal();

            GUI.backgroundColor = defaultColor;

            if (!clayxel.isAutoBoundsActive())
            {
                EditorGUI.BeginChangeCheck();
                Vector3Int boundsScale = EditorGUILayout.Vector3IntField(new GUIContent("bounds scale", "How much work area you have for your sculpt within this container. Enable Gizmos in your viewport to see the boundaries."), clayxel.getBoundsScale());

                if (EditorGUI.EndChangeCheck())
                {
                    ClayContainer._inspectorUpdate();

                    clayxel.setBoundsScale(boundsScale.x, boundsScale.y, boundsScale.z);

                    clayxel.init();
                    clayxel.needsUpdate = true;
                    // UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                    // ClayContainer.getSceneView().Repaint();

                    if (!Application.isPlaying)
                    {
                        EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                    }

                    return;
                }

                if (GUILayout.Button(new GUIContent("-", "")))
                {
                    ClayContainer._inspectorUpdate();

                    Vector3Int bounds = clayxel.getBoundsScale();
                    clayxel.setBoundsScale(bounds.x - 1, bounds.y - 1, bounds.z - 1);

                    clayxel.init();
                    clayxel.needsUpdate = true;
                    // UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                    // ClayContainer.getSceneView().Repaint();

                    if (!Application.isPlaying)
                    {
                        EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                    }

                    return;
                }

                if (GUILayout.Button(new GUIContent("+", "")))
                {
                    ClayContainer._inspectorUpdate();

                    Vector3Int bounds = clayxel.getBoundsScale();
                    clayxel.setBoundsScale(bounds.x + 1, bounds.y + 1, bounds.z + 1);

                    clayxel.init();
                    clayxel.needsUpdate = true;
                    // UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                    // ClayContainer.getSceneView().Repaint();

                    if (!Application.isPlaying)
                    {
                        EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                    }

                    return;
                }

                if (GUILayout.Button(new GUIContent("auto", "")))
                {
                    clayxel.setAutoBoundsActive(true);

                    // UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                    // ClayContainer.getSceneView().Repaint();

                    if (!Application.isPlaying)
                    {
                        EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                    }
                }
            }
            else
            {
                GUI.backgroundColor = Color.yellow;

                GUILayout.BeginHorizontal();

                EditorGUILayout.LabelField("bounds scale");

                if (GUILayout.Button(new GUIContent("auto", "")))
                {
                    clayxel.setAutoBoundsActive(false);
                }

                GUILayout.EndHorizontal();
            }

            GUI.backgroundColor = defaultColor;

            GUILayout.EndHorizontal();

            EditorGUILayout.Space();

            if (GUILayout.Button(new GUIContent("add clay", "lets get this party started")))
            {
                ClayObject clayObj = ((ClayContainer)this.target).addClayObject();

                Undo.RegisterCreatedObjectUndo(clayObj.gameObject, "added clayxel solid");
                UnityEditor.Selection.objects = new GameObject[] { clayObj.gameObject };

                clayxel.needsUpdate = true;
                // UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                // ClayContainer.getSceneView().Repaint();

                if (!Application.isPlaying)
                {
                    EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                }

                return;
            }

            if (GUILayout.Button(new GUIContent("pick clay (" + ClayContainer.pickingKey + ")", "Press p on your keyboard to mouse pick ClayObjects from the viewport. Pressing Shift will add to a previous selection.")))
            {
                ClayContainer.startScenePicking();
            }

            if (GUILayout.Button((new GUIContent("global config", ""))))
            {
                ClayxelsPrefsWindow.Open();
            }

            clayxel.forceUpdate = EditorGUILayout.Toggle(new GUIContent("animate (forceUpdate)", "Enable if you're animating/moving the container as well as the clayObjects inside it."), clayxel.forceUpdate);

            EditorGUILayout.Space();

            ClayxelInspector.extrasPanel = EditorGUILayout.Foldout(ClayxelInspector.extrasPanel, "extras", true);

            if (ClayxelInspector.extrasPanel)
            {
                ClayContainer instance = (ClayContainer)EditorGUILayout.ObjectField(new GUIContent("instance", "Set this to point at another clayContainer in scene to make this into an instance and avoid having to compute the same thing twice."), clayxel.instanceOf, typeof(ClayContainer), true);
                if (instance != clayxel.instanceOf && instance != clayxel)
                {
                    clayxel.instanceOf = instance;

                    // UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                    // ClayContainer.getSceneView().Repaint();

                    if (!Application.isPlaying)
                    {
                        EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                    }
                }

                EditorGUILayout.Space();

                if (clayxel.storeAssetPath == "")
                {
                    clayxel.storeAssetPath = clayxel.gameObject.name;
                }
                clayxel.storeAssetPath = EditorGUILayout.TextField(new GUIContent("frozen asset name", "Specify an asset name to store frozen mesh or claymation on disk. Files are saved relative to this project's Assets folder."), clayxel.storeAssetPath);
                string[] paths = clayxel.storeAssetPath.Split('.');
                if (paths.Length > 0)
                {
                    clayxel.storeAssetPath = paths[0];
                }

                EditorGUILayout.Space();

                                #if CLAYXELS_RETOPO
                clayxel.shouldRetopoMesh = EditorGUILayout.Toggle(new GUIContent("retopology", "Use this to generate meshes with a better topology."), clayxel.shouldRetopoMesh);
                if (clayxel.shouldRetopoMesh)
                {
                    clayxel.retopoMaxVerts = EditorGUILayout.IntField(new GUIContent("vertex count", "-1 will let the tool decide on the best number of vertices."), clayxel.retopoMaxVerts);
                }
                                #endif

                if (GUILayout.Button(new GUIContent("freeze mesh", "Switch between live clayxels and a frozen mesh.")))
                {
                    clayxel.freezeContainersHierarchyToMesh();

                                        #if CLAYXELS_RETOPO
                    if (clayxel.shouldRetopoMesh)
                    {
                        int targetVertCount = RetopoUtils.getRetopoTargetVertsCount(clayxel.gameObject, clayxel.retopoMaxVerts);
                        if (targetVertCount == 0)
                        {
                            return;
                        }

                        RetopoUtils.retopoMesh(clayxel.gameObject.GetComponent <MeshFilter>().sharedMesh, targetVertCount, -1);
                    }
                                        #endif

                    clayxel.transferMaterialPropertiesToMesh();

                    if (clayxel.storeAssetPath != "")
                    {
                        clayxel.storeMesh(clayxel.storeAssetPath);
                    }
                }

                EditorGUILayout.Space();

                AnimationClip claymationAnimClip = (AnimationClip)EditorGUILayout.ObjectField(new GUIContent("animClip (optional)", "Freeze an animation to disk using the claymation file format"), clayxel.claymationAnimClip, typeof(AnimationClip), true);
                if (claymationAnimClip != null && claymationAnimClip != clayxel.claymationAnimClip)
                {
                    clayxel.claymationStartFrame = 0;
                    clayxel.claymationEndFrame   = (int)(claymationAnimClip.length * claymationAnimClip.frameRate);
                }
                clayxel.claymationAnimClip = claymationAnimClip;

                if (clayxel.claymationAnimClip != null)
                {
                    clayxel.claymationStartFrame = EditorGUILayout.IntField(new GUIContent("start", ""), clayxel.claymationStartFrame);
                    clayxel.claymationEndFrame   = EditorGUILayout.IntField(new GUIContent("end", ""), clayxel.claymationEndFrame);
                }

                if (GUILayout.Button(new GUIContent("freeze claymation", "Freeze this container to a point-cloud file stored on disk and skip heavy computing.")))
                {
                    clayxel.freezeClaymation();
                }

                EditorGUI.BeginChangeCheck();

                EditorGUILayout.Space();

                bool castShadows = EditorGUILayout.Toggle("cast shadows", clayxel.getCastShadows());

                if (EditorGUI.EndChangeCheck())
                {
                    ClayContainer._inspectorUpdate();

                    clayxel.setCastShadows(castShadows);

                    if (!Application.isPlaying)
                    {
                        EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                    }
                }

                // end of extras
            }

            EditorGUI.BeginChangeCheck();

            EditorGUILayout.Space();

            Material customMaterial = (Material)EditorGUILayout.ObjectField(new GUIContent("customMaterial", "Custom materials need to use shaders specifically made for clayxels. Use the provided shaders and examples as reference. "), clayxel.customMaterial, typeof(Material), false);

            if (EditorGUI.EndChangeCheck())
            {
                ClayContainer._inspectorUpdate();

                Undo.RecordObject(this.target, "changed clayxel container");

                if (customMaterial != clayxel.customMaterial)
                {
                    clayxel.setCustomMaterial(customMaterial);

                    // clayxel.needsUpdate = true;
                    // clayxel.forceUpdateAllSolids();
                }

                // UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                // ClayContainer.getSceneView().Repaint();

                if (!Application.isPlaying)
                {
                    EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
                }
            }

            if (!clayxel.isFrozenToMesh())
            {
                this.inspectMaterial(clayxel);
            }
        }
예제 #26
0
 void Start()
 {
     ClayContainer.setUpdateFrameSkip(5);
     this.initRig();
 }
예제 #27
0
        public override void OnInspectorGUI()
        {
            ClayObject clayObj = (ClayObject)this.targets[0];

            EditorGUI.BeginChangeCheck();

            float blend = EditorGUILayout.FloatField("blend", clayObj.blend);

            if (blend > 1.0f)
            {
                blend = 1.0f;
            }
            else if (blend < -1.0f)
            {
                blend = -1.0f;
            }

            Color color = EditorGUILayout.ColorField("color", clayObj.color);

            ClayContainer clayxel = clayObj.getClayxelContainer();

            string[] solidsLabels  = clayxel.getSolidsCatalogueLabels();
            int      primitiveType = EditorGUILayout.Popup("solidType", clayObj.primitiveType, solidsLabels);

            Dictionary <string, float> paramValues = new Dictionary <string, float>();

            paramValues["x"] = clayObj.attrs.x;
            paramValues["y"] = clayObj.attrs.y;
            paramValues["z"] = clayObj.attrs.z;
            paramValues["w"] = clayObj.attrs.w;

            List <string[]> parameters  = clayxel.getSolidsCatalogueParameters(primitiveType);
            List <string>   wMaskLabels = new List <string>();

            for (int paramIt = 0; paramIt < parameters.Count; ++paramIt)
            {
                string[] parameterValues = parameters[paramIt];
                string   attr            = parameterValues[0];
                string   label           = parameterValues[1];
                string   defaultValue    = parameterValues[2];

                if (primitiveType != clayObj.primitiveType)
                {
                    // reset to default params when changing primitive type
                    paramValues[attr] = float.Parse(defaultValue);
                }

                if (attr.StartsWith("w"))
                {
                    wMaskLabels.Add(label);
                }
                else
                {
                    paramValues[attr] = EditorGUILayout.FloatField(label, paramValues[attr]);
                }
            }

            if (wMaskLabels.Count > 0)
            {
                paramValues["w"] = (float)EditorGUILayout.MaskField("options", (int)clayObj.attrs.w, wMaskLabels.ToArray());
            }

            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObjects(this.targets, "changed clayobject");

                for (int i = 1; i < this.targets.Length; ++i)
                {
                    bool       somethingChanged = false;
                    ClayObject currentClayObj   = (ClayObject)this.targets[i];

                    bool shouldAutoRename = false;

                    if (clayObj.blend != blend)
                    {
                        currentClayObj.blend = blend;
                        somethingChanged     = true;
                        shouldAutoRename     = true;
                    }

                    if (clayObj.color != color)
                    {
                        currentClayObj.color = color;
                        somethingChanged     = true;
                    }

                    if (clayObj.primitiveType != primitiveType)
                    {
                        currentClayObj.primitiveType = primitiveType;
                        somethingChanged             = true;
                        shouldAutoRename             = true;
                    }

                    if (clayObj.attrs.x != paramValues["x"])
                    {
                        currentClayObj.attrs.x = paramValues["x"];
                        somethingChanged       = true;
                    }

                    if (clayObj.attrs.y != paramValues["y"])
                    {
                        currentClayObj.attrs.y = paramValues["y"];
                        somethingChanged       = true;
                    }

                    if (clayObj.attrs.z != paramValues["z"])
                    {
                        currentClayObj.attrs.z = paramValues["z"];
                        somethingChanged       = true;
                    }

                    if (clayObj.attrs.w != paramValues["w"])
                    {
                        currentClayObj.attrs.w = paramValues["w"];
                        somethingChanged       = true;
                        shouldAutoRename       = true;
                    }

                    if (somethingChanged)
                    {
                        currentClayObj.getClayxelContainer().clayObjectUpdated(currentClayObj);

                        if (shouldAutoRename)
                        {
                            if (currentClayObj.gameObject.name.StartsWith("clay_"))
                            {
                                this.autoRename(currentClayObj, solidsLabels);
                            }
                        }
                    }
                }

                clayObj.blend         = blend;
                clayObj.color         = color;
                clayObj.primitiveType = primitiveType;
                clayObj.attrs.x       = paramValues["x"];
                clayObj.attrs.y       = paramValues["y"];
                clayObj.attrs.z       = paramValues["z"];
                clayObj.attrs.w       = paramValues["w"];

                if (clayObj.gameObject.name.StartsWith("clay_"))
                {
                    this.autoRename(clayObj, solidsLabels);
                }

                clayxel.clayObjectUpdated(clayObj);
                UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                ClayContainer.getSceneView().Repaint();
            }
        }
예제 #28
0
 public void setClayxelContainer(ClayContainer container)
 {
     this.clayxelContainerRef = new WeakReference(container);
 }
예제 #29
0
    void OnGUI()
    {
        if (Application.isPlaying)
        {
            return;
        }

        if (ClayxelsPrefsWindow.prefs == null)
        {
            ClayxelsPrefsWindow.prefs = ClayContainer.loadPrefs();
        }

        EditorGUI.BeginChangeCheck();

        Color boundsColor = new Color((float)ClayxelsPrefsWindow.prefs.boundsColor[0] / 255.0f, (float)ClayxelsPrefsWindow.prefs.boundsColor[1] / 255.0f, (float)ClayxelsPrefsWindow.prefs.boundsColor[2] / 255.0f, (float)ClayxelsPrefsWindow.prefs.boundsColor[3] / 255.0f);

        boundsColor = EditorGUILayout.ColorField(new GUIContent("boundsColor", "Color of the bounds indicator in the viewport, enable Gizmos in the viewport to see this."), boundsColor);
        ClayxelsPrefsWindow.prefs.boundsColor[0] = (byte)(boundsColor.r * 255);
        ClayxelsPrefsWindow.prefs.boundsColor[1] = (byte)(boundsColor.g * 255);
        ClayxelsPrefsWindow.prefs.boundsColor[2] = (byte)(boundsColor.b * 255);
        ClayxelsPrefsWindow.prefs.boundsColor[3] = (byte)(boundsColor.a * 255);

        ClayxelsPrefsWindow.prefs.pickingKey         = EditorGUILayout.TextField(new GUIContent("picking shortcut", "Press this shortcut to pick/select containers and clayObjects in scene."), ClayxelsPrefsWindow.prefs.pickingKey);
        ClayxelsPrefsWindow.prefs.mirrorDuplicateKey = EditorGUILayout.TextField(new GUIContent("mirrorDuplicate shortcut", "Press this shortcut to duplicate and mirror a clayObject on the X axis."), ClayxelsPrefsWindow.prefs.mirrorDuplicateKey);

        string[] pointCountPreset = new string[] { "low", "mid", "high" };
        ClayxelsPrefsWindow.prefs.maxPointCount = EditorGUILayout.Popup(new GUIContent("pointCloud memory", "Preset to allocate video ram to handle bigger point clouds."), ClayxelsPrefsWindow.prefs.maxPointCount, pointCountPreset);

        string[] solidsCountPreset = new string[] { "low", "mid", "high" };
        ClayxelsPrefsWindow.prefs.maxSolidsCount = EditorGUILayout.Popup(new GUIContent("clayObjects memory", "Preset to allocate video ram to handle more clayObjects per container."), ClayxelsPrefsWindow.prefs.maxSolidsCount, solidsCountPreset);

        string[] solidsPerVoxelPreset = new string[] { "best performance", "balanced", "max sculpt detail" };
        ClayxelsPrefsWindow.prefs.maxSolidsPerVoxel = EditorGUILayout.Popup(new GUIContent("clayObjects per voxel", "Preset to handle more clayObjects per voxel, it might fix some artifacts caused by having a lot of clayObjects all close to each other."), ClayxelsPrefsWindow.prefs.maxSolidsPerVoxel, solidsPerVoxelPreset);

        int frameSkip = EditorGUILayout.IntField(new GUIContent("frame skip", ""), ClayxelsPrefsWindow.prefs.frameSkip);

        if (frameSkip < 0)
        {
            frameSkip = 0;
        }
        else if (frameSkip > 100)
        {
            frameSkip = 100;
        }
        ClayxelsPrefsWindow.prefs.frameSkip = frameSkip;

        int maxBounds = EditorGUILayout.IntField(new GUIContent("max bounds size", "Smaller bounds use less video memory but give you less space to work with."), ClayxelsPrefsWindow.prefs.maxBounds);

        if (maxBounds < 1)
        {
            maxBounds = 1;
        }
        else if (maxBounds > 4)
        {
            maxBounds = 4;
        }
        ClayxelsPrefsWindow.prefs.maxBounds = maxBounds;

        ClayxelsPrefsWindow.prefs.vramLimitEnabled = EditorGUILayout.Toggle(new GUIContent("video ram limit enabled", "When this limit is enabled you won't be able to exceed your available vram when creating new container."), ClayxelsPrefsWindow.prefs.vramLimitEnabled);

        EditorGUILayout.Space();

        EditorGUILayout.MinMaxSlider(new GUIContent("LOD: " + Mathf.Round(ClayxelsPrefsWindow.prefs.lodNear) + " - " + Mathf.Round(ClayxelsPrefsWindow.prefs.lodFar), "Level Of Detail in scene unit, measures the distance from the camera to automatically reduce the amount of points rendered."),
                                     ref ClayxelsPrefsWindow.prefs.lodNear, ref ClayxelsPrefsWindow.prefs.lodFar, 0.0f, 1000.0f);

        if (EditorGUI.EndChangeCheck())
        {
            ClayContainer.savePrefs(ClayxelsPrefsWindow.prefs);
            ClayContainer.reloadAll();
        }

        EditorGUILayout.Space();

        int[] memStats = ClayContainer.getMemoryStats();
        EditorGUILayout.LabelField("- vram rough usage -");
        EditorGUILayout.LabelField("upfront vram allocated: " + memStats[0] + "MB");
        EditorGUILayout.LabelField("containers in scene: " + memStats[1] + "MB");

        EditorGUILayout.Space();

        if (GUILayout.Button((new GUIContent("reload all", "This is necessary after you make changes to the shaders or to the claySDF file."))))
        {
            ClayContainer.reloadAll();
        }
    }
예제 #30
0
        public override void OnInspectorGUI()
        {
            ClayContainer clayxel = (ClayContainer)this.target;

            EditorGUILayout.LabelField("Clayxels, V0.51 beta");
            EditorGUILayout.LabelField("clayObjects: " + clayxel.getNumClayObjects());

                        #if !CLAYXELS_FULL
            EditorGUILayout.LabelField("free version limit is 64");
                        #else
            EditorGUILayout.LabelField("limit is " + clayxel.getMaxSolids());
                        #endif

            EditorGUILayout.Space();

            EditorGUI.BeginChangeCheck();
            int        gridResolution = EditorGUILayout.IntField("resolution", clayxel.gridResolution);
            Vector3Int gridSize       = EditorGUILayout.Vector3IntField("containerSize", new Vector3Int(clayxel.gridSizeX, clayxel.gridSizeY, clayxel.gridSizeZ));

            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(this.target, "changed clayxel grid");

                clayxel.gridResolution = gridResolution;
                clayxel.gridSizeX      = gridSize.x;
                clayxel.gridSizeY      = gridSize.y;
                clayxel.gridSizeZ      = gridSize.z;

                clayxel.init();
                clayxel.needsUpdate = true;
                UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                ClayContainer.getSceneView().Repaint();

                return;
            }

            EditorGUI.BeginChangeCheck();

            EditorGUILayout.Space();

            Material customMaterial = (Material)EditorGUILayout.ObjectField("customMaterial", clayxel.customMaterial, typeof(Material), false);

            float     materialSmoothness        = 0.0f;
            float     materialMetallic          = 0.0f;
            Color     materialEmission          = new Color();
            float     materialEmissionIntensity = 0.0f;
            float     splatSizeMultiplier       = 1.0f;
            float     normalOrientedSplat       = 1.0f;
            Texture2D splatTexture = null;

            if (customMaterial == null)
            {
                materialSmoothness        = EditorGUILayout.FloatField("smoothness", clayxel.materialSmoothness);
                materialMetallic          = EditorGUILayout.FloatField("metallic", clayxel.materialMetallic);
                materialEmission          = EditorGUILayout.ColorField("emission", clayxel.materialEmission);
                materialEmissionIntensity = EditorGUILayout.FloatField("emissionIntensity", clayxel.materialEmissionIntensity);
                splatSizeMultiplier       = EditorGUILayout.FloatField("clayxelsSize", clayxel.splatSizeMultiplier);
                normalOrientedSplat       = EditorGUILayout.FloatField("normal oritented", clayxel.normalOrientedSplat);
                splatTexture = (Texture2D)EditorGUILayout.ObjectField("texture", clayxel.splatTexture, typeof(Texture2D), false);
            }

            if (EditorGUI.EndChangeCheck())
            {
                Undo.RecordObject(this.target, "changed clayxel container");

                if (customMaterial == null)
                {
                    clayxel.materialSmoothness        = materialSmoothness;
                    clayxel.materialMetallic          = materialMetallic;
                    clayxel.materialEmission          = materialEmission;
                    clayxel.materialEmissionIntensity = materialEmissionIntensity;
                    clayxel.splatSizeMultiplier       = splatSizeMultiplier;
                    clayxel.normalOrientedSplat       = normalOrientedSplat;
                    clayxel.splatTexture = splatTexture;
                }

                if (clayxel.normalOrientedSplat < 0.0f)
                {
                    clayxel.normalOrientedSplat = 0.0f;
                }
                else if (clayxel.normalOrientedSplat > 1.0f)
                {
                    clayxel.normalOrientedSplat = 1.0f;
                }

                clayxel.updateSplatLook();

                if (customMaterial != clayxel.customMaterial)
                {
                    clayxel.customMaterial = customMaterial;
                    clayxel.init();
                }

                clayxel.needsUpdate = true;
                clayxel.forceUpdateAllChunks();
                UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                ClayContainer.getSceneView().Repaint();

                return;
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("reload all"))
            {
                ClayContainer.reloadAll();
            }

            if (GUILayout.Button("pick solid (p)"))
            {
                ClayContainer.startPicking();
            }

            if (GUILayout.Button("add solid"))
            {
                ClayObject clayObj = ((ClayContainer)this.target).addSolid();

                Undo.RegisterCreatedObjectUndo(clayObj.gameObject, "added clayxel solid");
                UnityEditor.Selection.objects = new GameObject[] { clayObj.gameObject };

                clayxel.needsUpdate = true;
                UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                ClayContainer.getSceneView().Repaint();

                return;
            }

            EditorGUILayout.Space();

                        #if CLAYXELS_FULL
            clayxel.exportRetopoFBX = EditorGUILayout.Toggle("retopology", clayxel.exportRetopoFBX);
            if (clayxel.exportRetopoFBX)
            {
                clayxel.retopoMaxVerts = EditorGUILayout.IntField("max verts", clayxel.retopoMaxVerts);

                clayxel.retopoFbxFile = EditorGUILayout.TextField("export fbx", clayxel.retopoFbxFile);
            }
                        #endif

            if (!clayxel.hasCachedMesh())
            {
                if (GUILayout.Button("freeze to mesh"))
                {
                    if (clayxel.exportRetopoFBX)
                    {
                        clayxel.retopoMesh();
                    }
                    else
                    {
                        clayxel.generateMesh();
                    }
                }
            }
            else
            {
                if (GUILayout.Button("defrost clayxels"))
                {
                    clayxel.disableMesh();
                    UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
                    ClayContainer.getSceneView().Repaint();
                }
            }
        }