Example #1
0
        void OnDisable()
        {
            Selection.selectionChanged -= OnSelectionChanged;
#if UNITY_2019_1_OR_NEWER
            SceneView.duringSceneGui -= OnSceneGUI;
#else
            SceneView.onSceneGUIDelegate -= OnSceneGUI;
#endif
            Undo.undoRedoPerformed -= UndoRedoPerformed;
            //EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyWindowItemChanged;

#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.ProBuilderExists())
            {
                ProBuilderBridge.UnsubscribeToSelectModeChanged(OnProBuilderSelectModeChanged);
            }
#endif


            // store local changes to brushSettings
            if (brushSettings != null)
            {
                var js = JsonUtility.ToJson(brushSettings, true);
                EditorPrefs.SetString(k_BrushSettingsPref, js);
            }

            // don't iterate here!  FinalizeAndReset does that
            OnBrushExit(m_LastHoveredGameObject);
            FinalizeAndResetHovering();

            PreviewsDatabase.UnloadCache();
        }
Example #2
0
        internal override void RegisterUndo(BrushTarget brushTarget)
        {
#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.IsValidProBuilderMesh(brushTarget.gameObject))
            {
                UnityEngine.Object pbMesh = ProBuilderBridge.GetProBuilderComponent(brushTarget.gameObject);
                if (pbMesh != null)
                {
                    Undo.RegisterCompleteObjectUndo(pbMesh, UndoMessage);
                    modifiedPbMeshes.Add(brushTarget.gameObject);
                }
                else
                {
                    Undo.RegisterCompleteObjectUndo(brushTarget.editableObject.polybrushMesh, UndoMessage);
                    modifiedMeshes.Add(brushTarget.editableObject.polybrushMesh.polyMesh);
                }
            }
            else
#endif
            {
                Undo.RegisterCompleteObjectUndo(brushTarget.editableObject.polybrushMesh, UndoMessage);
                modifiedMeshes.Add(brushTarget.editableObject.polybrushMesh.polyMesh);
            }

            brushTarget.editableObject.isDirty = true;
        }
Example #3
0
        /// <summary>
        /// Update the current state of the mesh preview.
        /// As AssetPreview API is asynchronous, we need to keep requesting the asset preview
        /// until we have it. Once texture is loaded, current state of the instance moves
        /// to Status.Loaded.
        /// </summary>
        internal void UpdatePreview()
        {
            switch (m_previewState)
            {
            case State.Loading:
                if (ProBuilderBridge.ProBuilderExists() && ProBuilderInterface.IsProBuilderObject(m_Asset as GameObject))
                {
                    m_PreviewTexture = GenerateProBuilderPreview();
                }
                else if (PolyEditorUtility.IsPolybrushObject(m_Asset as GameObject))
                {
                    m_PreviewTexture = GeneratePreview();
                }
                else
                {
                    m_PreviewTexture = AssetPreview.GetAssetPreview(m_Asset);
                }

                if (previewTexture != null)
                {
                    SetState(State.Loaded);
                }

                break;

            case State.Loaded:
                // Failsafe as AssetPreview can return white textures while loading
                // and erase that texture from memory once the right texture is available.
                if (m_PreviewTexture == null)
                {
                    SetState(State.Loading);
                }
                break;
            }
        }
Example #4
0
        void OnDestroy()
        {
            SetTool(BrushTool.None);

#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.ProBuilderExists())
            {
                ProBuilderBridge.SetSelectMode(ProBuilderBridge.SelectMode.Object);
            }
#endif

            foreach (BrushMode m in modes)
            {
                GameObject.DestroyImmediate(m);
            }

            if (brushSettings != null)
            {
                GameObject.DestroyImmediate(brushSettings);
            }

            if (m_BrushEditor != null)
            {
                GameObject.DestroyImmediate(m_BrushEditor);
            }
        }
        static bool MeshInstanceMatchesGameObject(Mesh mesh, GameObject go)
        {
            if (ProBuilderBridge.IsValidProBuilderMesh(go))
            {
                return(true);
            }

            int gameObjectId = go.GetInstanceID();
            int meshId       = GetMeshId(mesh);

            // If the mesh id doesn't parse to an ID it's definitely not an instance
            if (meshId == -1)
            {
                return(false);
            }

            // If the mesh id matches the instance id, it's already a scene instance owned by this object. If doesn't match,
            // next check that the mesh id gameObject does not exist. If it does exist, that means this mesh was duplicated
            // and already belongs to another object in the scene. If it doesn't exist, then it just means that the GameObject
            // id was changed as a normal part of the GameObject lifecycle.
            if (meshId == gameObjectId)
            {
                return(true);
            }

            // If it is an instance, and the IDs don't match but no existing GameObject claims this mesh, claim it.
            if (EditorUtility.InstanceIDToObject(meshId) == null)
            {
                mesh.name = k_MeshInstancePrefix + go.GetInstanceID();
                return(true);
            }

            // The mesh did not match the gameObject id, and the mesh id points to an already existing object in the scene.
            return(false);
        }
 /// <summary>
 /// Tests if a GameObject is a ProBuilder mesh or not.
 /// </summary>
 /// <param name="gameObject"></param>
 /// <returns></returns>
 internal static bool IsProBuilderObject(GameObject gameObject)
 {
     if (ProBuilderBridge.ProBuilderExists())
     {
         return(ProBuilderBridge.IsValidProBuilderMesh(gameObject));
     }
     return(false);
 }
Example #7
0
        /// <summary>
        /// Tests if a GameObject is a ProBuilder mesh or not.
        /// </summary>
        /// <param name="gameObject"></param>
        /// <returns></returns>
        internal static bool IsProBuilderObject(GameObject gameObject)
        {
#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.ProBuilderExists())
            {
                return(ProBuilderBridge.IsValidProBuilderMesh(gameObject));
            }
            return(false);
#endif
        }
        internal override void OnBrushApply(BrushTarget brushTarget, BrushSettings brushSettings)
        {
            // false means no ToMesh or Refresh, true does.  Optional addl bool runs pb_Object.Optimize()
            brushTarget.editableObject.Apply(true);

            if (ProBuilderBridge.ProBuilderExists() && brushTarget.editableObject.isProBuilderObject)
            {
                ProBuilderBridge.Refresh(brushTarget.gameObject);
            }

            UpdateTempComponent(brushTarget, brushSettings);
        }
        /// <summary>
        /// Switch Polybrush to the given tool.
        /// </summary>
        /// <param name="brushTool">Tool to show in Polybrush window.</param>
        /// <param name="enableTool">If true, will activate the given tool automatically. Default: true.</param>
        internal void SetTool(BrushTool brushTool, bool enableTool = true)
        {
            if (brushTool == tool && mode != null)
            {
                return;
            }

#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.ProBuilderExists())
            {
                ProBuilderBridge.SetSelectMode(ProBuilderBridge.SelectMode.Object);
            }
#endif

            if (mode != null)
            {
                // Exiting edit mode
                if (m_LastHoveredGameObject != null)
                {
                    OnBrushExit(m_LastHoveredGameObject);
                    FinalizeAndResetHovering();
                }

                mode.OnDisable();
            }

            m_LastHoveredGameObject = null;

            System.Type modeType = brushTool.GetModeType();

            if (modeType != null)
            {
                mode = modes.FirstOrDefault(x => x != null && x.GetType() == modeType);

                if (mode == null)
                {
                    mode = (BrushMode)ScriptableObject.CreateInstance(modeType);
                }
            }

            // Handle tool auto activation/deactivation.
            tool = enableTool? brushTool : BrushTool.None;

            if (tool != BrushTool.None)
            {
                Tools.current = Tool.None;
                mode.OnEnable();
            }

            EnsureBrushSettingsListIsValid();
            DoRepaint();
        }
        void OnEnable()
        {
            if (!PrefUtility.VersionCheck())
            {
                PrefUtility.ClearPrefs();
            }

            PolybrushEditor.s_Instance = this;

            // Editor window setup
            titleContent   = new GUIContent("Polybrush");
            wantsMouseMove = true;
            minSize        = k_EditorWindowMinimumSize;

            m_BrushMirrorEditor = new MirrorSettingsEditor();

#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.ProBuilderExists())
            {
                ProBuilderBridge.SubscribeToSelectModeChanged(OnProBuilderSelectModeChanged);
            }
#endif

            m_GCToolmodeIcons = new GUIContent[]
            {
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/Sculpt"), "Sculpt on meshes"),
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/Smooth"), "Smooth mesh geometry"),
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/PaintVertexColors"), "Paint vertex colors on meshes"),
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/PaintPrefabs"), "Scatter Prefabs on meshes"),
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/PaintTextures"), "Paint textures on meshes"),
            };

#if UNITY_2019_1_OR_NEWER
            SceneView.duringSceneGui += OnSceneGUI;
#else
            SceneView.onSceneGUIDelegate += OnSceneGUI;
#endif
            Undo.undoRedoPerformed += UndoRedoPerformed;

            // force update the preview
            m_LastHoveredGameObject = null;

            EnsureBrushSettingsListIsValid();
            PopulateAvailableBrushList();

            SetTool(BrushTool.RaiseLower, false);

            Selection.selectionChanged -= OnSelectionChanged;
            Selection.selectionChanged += OnSelectionChanged;
        }
        /// <summary>
        /// Generate a static preview for a ProBuilderMesh.
        /// </summary>
        /// <returns>Static preview of the given ProBuilderMesh.</returns>
        internal Texture2D GenerateProBuilderPreview()
        {
            GameObject copy = GameObject.Instantiate <GameObject>(m_Asset as GameObject);

            copy.hideFlags = HideFlags.HideAndDontSave;

            ProBuilderBridge.ToMesh(copy);
            ProBuilderBridge.Refresh(copy);

            MeshFilter mf = copy.GetComponent <MeshFilter>();

            Editor meshEditor = Editor.CreateEditor(mf.sharedMesh);

            Texture2D preview = meshEditor.RenderStaticPreview(null, null, k_PreviewSize.x, k_PreviewSize.y);

            ScriptableObject.DestroyImmediate(meshEditor);
            ScriptableObject.DestroyImmediate(copy);

            return(preview);
        }
        protected void UpdateWireframe(BrushTarget target, BrushSettings settings)
        {
            if (!Util.IsValid(target))
            {
                return;
            }

            if (m_EditableObjectsData.TryGetValue(target.editableObject, out EditableObjectData data))
            {
                if (data.TempComponent != null)
                {
                    data.TempComponent.OnVerticesMoved(target.editableObject.editMesh);
                }

                //Might be costly to do that on every wireframe update
                if (ProBuilderBridge.ProBuilderExists() && target.editableObject.isProBuilderObject)
                {
                    ProBuilderBridge.RefreshEditor(false);
                }
            }
        }
Example #13
0
        void FinalizeAndResetHovering()
        {
            foreach (var kvp in m_Hovering)
            {
                BrushTarget target = kvp.Value;

                if (!Util.IsValid(target))
                {
                    continue;
                }

                // if mesh hasn't been modified, revert it back
                // to the original mesh so that unnecessary assets
                // aren't allocated.  if it has been modified, let
                // the editableObject apply those changes to the
                // pb_Object if necessary.
                if (!target.editableObject.isDirty)
                {
                    target.editableObject.Revert();
                }
                else
                {
                    target.editableObject.Apply(true, true);
                }
            }

            m_Hovering.Clear();
            brushTarget             = null;
            m_LastHoveredGameObject = null;

#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.ProBuilderExists())
            {
                ProBuilderBridge.RefreshEditor(false);
            }
#endif
            Repaint();
        }
Example #14
0
        internal override void UndoRedoPerformed(List <GameObject> modified)
        {
            modifiedMeshes = new HashSet <PolyMesh>(modifiedMeshes.Where(x => x != null));

#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.ProBuilderExists())
            {
                // delete & undo causes cases where object is not null but the reference to it's pb_Object is
                HashSet <GameObject> remove = new HashSet <GameObject>();

                foreach (GameObject pb in modifiedPbMeshes)
                {
                    try
                    {
                        ProBuilderBridge.ToMesh(pb);
                        ProBuilderBridge.Refresh(pb);
                        ProBuilderBridge.Optimize(pb);
                    }
                    catch
                    {
                        remove.Add(pb);
                    }
                }

                if (remove.Count() > 0)
                {
                    modifiedPbMeshes.SymmetricExceptWith(remove);
                }
            }
#endif

            foreach (PolyMesh m in modifiedMeshes)
            {
                m.UpdateMeshFromData();
            }

            base.UndoRedoPerformed(modified);
        }
        /// <summary>
        /// Applies mesh changes back to the pb_Object (if necessary).  Optionally does a
        /// mesh rebuild.
        /// </summary>
        /// <param name="rebuildMesh">Only applies to ProBuilder meshes.</param>
        /// <param name="optimize">Determines if the mesh collisions are rebuilt (if that option is enabled) or if
        /// the mehs is a probuilder object, the mesh is optimized (condensed to share verts, other
        /// otpimziations etc) </param>
        internal void Apply(bool rebuildMesh, bool optimize = false)
        {
            if (m_PolybrushMesh.mode == PolybrushMesh.Mode.AdditionalVertexStream)
            {
                if (PolyEditor.instance.tool == BrushTool.RaiseLower ||
                    PolyEditor.instance.tool == BrushTool.Smooth)
                {
                    if (s_RebuildNormals.value && (modifiedChannels & MeshChannel.Position) > 0)
                    {
                        PolyMeshUtility.RecalculateNormals(editMesh);
                    }

                    if (optimize)
                    {
                        graphicsMesh.RecalculateBounds();
                        UpdateMeshCollider();
                    }
                }

                editMesh.ApplyAttributesToUnityMesh(graphicsMesh, modifiedChannels);
                graphicsMesh.UploadMeshData(false);
                EditorUtility.SetDirty(gameObjectAttached.GetComponent <Renderer>());

                if (m_PolybrushMesh.componentsCache.MeshFilter)
                {
                    Undo.RecordObject(m_PolybrushMesh.componentsCache.MeshFilter, "Assign Polymesh to MeshFilter");
                }

                if (m_PolybrushMesh)
                {
                    m_PolybrushMesh.SynchronizeWithMeshRenderer();
                }
            }


#if PROBUILDER_4_0_OR_NEWER
            // if it's a probuilder object rebuild the mesh without optimization
            if (isProBuilderObject)
            {
                ProBuilderBridge.SetPositions(gameObjectAttached, editMesh.vertices);
                ProBuilderBridge.SetTangents(gameObjectAttached, editMesh.tangents);

                if (editMesh.colors != null && editMesh.colors.Length == editMesh.vertexCount)
                {
                    Color[] colors = System.Array.ConvertAll(editMesh.colors, x => (Color)x);
                    ProBuilderBridge.SetColors(gameObjectAttached, colors);
                }

                if (rebuildMesh)
                {
                    ProBuilderBridge.ToMesh(gameObjectAttached);
                    ProBuilderBridge.Refresh(gameObjectAttached,
                                             optimize
                            ? ProBuilderBridge.RefreshMask.All
                            : (ProBuilderBridge.RefreshMask.Colors
                               | ProBuilderBridge.RefreshMask.Normals
                               | ProBuilderBridge.RefreshMask.Tangents));
                }
            }
#endif

            if (m_PolybrushMesh.mode == PolybrushMesh.Mode.AdditionalVertexStream)
            {
                modifiedChannels = MeshChannel.Null;
                return;
            }

            if (PolyEditor.instance.tool == BrushTool.RaiseLower ||
                PolyEditor.instance.tool == BrushTool.Smooth)
            {
                if (s_RebuildNormals.value)// && (modifiedChannels & MeshChannel.Position) > 0)
                {
                    PolyMeshUtility.RecalculateNormals(editMesh);
                }

                if (optimize)
                {
                    UpdateMeshCollider();
                    graphicsMesh.RecalculateBounds();
                }
            }

            editMesh.ApplyAttributesToUnityMesh(graphicsMesh, modifiedChannels);

            if (m_PolybrushMesh.componentsCache.MeshFilter)
            {
                Undo.RecordObject(m_PolybrushMesh.componentsCache.MeshFilter, "Assign Polymesh to MeshFilter");
            }

            m_PolybrushMesh.SynchronizeWithMeshRenderer();

            modifiedChannels = MeshChannel.Null;
        }
        private void Initialize(GameObject go)
        {
            CheckBackwardCompatiblity(go);

            gameObjectAttached = go;
            isProBuilderObject = false;

#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.ProBuilderExists())
            {
                isProBuilderObject = ProBuilderBridge.IsValidProBuilderMesh(gameObjectAttached);
            }
#endif
            Mesh         mesh         = null;
            MeshRenderer meshRenderer = gameObjectAttached.GetComponent <MeshRenderer>();
            meshFilter        = gameObjectAttached.GetComponent <MeshFilter>();
            _skinMeshRenderer = gameObjectAttached.GetComponent <SkinnedMeshRenderer>();

            originalMesh = go.GetMesh();

            if (originalMesh == null && _skinMeshRenderer != null)
            {
                originalMesh = _skinMeshRenderer.sharedMesh;
            }

            m_PolybrushMesh = gameObjectAttached.GetComponent <PolybrushMesh>();

            if (m_PolybrushMesh == null)
            {
                m_PolybrushMesh = Undo.AddComponent <PolybrushMesh>(gameObjectAttached);
                m_PolybrushMesh.Initialize();
                m_PolybrushMesh.mode = (s_UseAdditionalVertexStreams) ? PolybrushMesh.Mode.AdditionalVertexStream : PolybrushMesh.Mode.Mesh;
            }

            //attach the skinmesh ref to the polybrushmesh
            //it will be used when making a prefab containing a skin mesh. The limitation here is that the skin mesh must comes from an asset (which is 99.9999% of the time)
            if (_skinMeshRenderer != null)
            {
                Mesh sharedMesh = _skinMeshRenderer.sharedMesh;
                if (AssetDatabase.Contains(sharedMesh))
                {
                    m_PolybrushMesh.skinMeshRef = sharedMesh;
                }
            }

#if PROBUILDER_4_0_OR_NEWER
            // if it's a probuilder object rebuild the mesh without optimization
            if (isProBuilderObject)
            {
                if (ProBuilderBridge.IsValidProBuilderMesh(gameObjectAttached))
                {
                    ProBuilderBridge.ToMesh(gameObjectAttached);
                    ProBuilderBridge.Refresh(gameObjectAttached);
                }
            }
#endif

            if (meshRenderer != null || _skinMeshRenderer != null)
            {
                mesh = m_PolybrushMesh.storedMesh;

                if (mesh == null)
                {
                    mesh             = PolyMeshUtility.DeepCopy(originalMesh);
                    hadVertexStreams = false;
                }
                else
                {
                    //prevents leak
                    if (!MeshInstanceMatchesGameObject(mesh, gameObjectAttached))
                    {
                        mesh = PolyMeshUtility.DeepCopy(mesh);
                    }
                }

                mesh.name = k_MeshInstancePrefix + gameObjectAttached.GetInstanceID();
            }

            polybrushMesh.SetMesh(mesh);
            PrefabUtility.RecordPrefabInstancePropertyModifications(polybrushMesh);
            _graphicsMesh = m_PolybrushMesh.storedMesh;

            source = polybrushMesh.mode == PolybrushMesh.Mode.AdditionalVertexStream? ModelSource.AdditionalVertexStreams : PolyEditorUtility.GetMeshGUID(originalMesh);

            GenerateCompositeMesh();
        }
Example #17
0
        void OnEnable()
        {
            if (!PrefUtility.VersionCheck())
            {
                PrefUtility.ClearPrefs();
            }

            PolyEditor.s_Instance = this;

            // Editor window setup
            titleContent   = new GUIContent("Polybrush");
            wantsMouseMove = true;
            minSize        = k_EditorWindowMinimumSize;

            m_BrushMirrorEditor = new MirrorSettingsEditor();

#if PROBUILDER_4_0_OR_NEWER
            if (ProBuilderBridge.ProBuilderExists())
            {
                ProBuilderBridge.SubscribeToSelectModeChanged(OnProBuilderSelectModeChanged);
            }
#endif

            m_GCToolmodeIcons = new GUIContent[]
            {
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/Sculpt"), "Sculpt on meshes"),
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/Smooth"), "Smooth mesh geometry"),
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/PaintVertexColors"), "Paint vertex colors on meshes"),
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/PaintPrefabs"), "Scatter Prefabs on meshes"),
                EditorGUIUtility.TrIconContent(IconUtility.GetIcon("Toolbar/PaintTextures"), "Paint textures on meshes"),
            };

#if UNITY_2019_1_OR_NEWER
            SceneView.duringSceneGui += OnSceneGUI;
#else
            SceneView.onSceneGUIDelegate += OnSceneGUI;
#endif
            Undo.undoRedoPerformed += UndoRedoPerformed;

            // force update the preview
            m_LastHoveredGameObject = null;

            if (brushSettings == null)
            {
                if (brushSettingsAsset == null)
                {
                    brushSettingsAsset = AssetDatabase.LoadAssetAtPath <BrushSettings>(AssetDatabase.GUIDToAssetPath(EditorPrefs.GetString(k_BrushSettingsAssetPref, "")));
                }

                if (EditorPrefs.HasKey(k_BrushSettingsPref))
                {
                    brushSettings = ScriptableObject.CreateInstance <BrushSettings>();
                    JsonUtility.FromJsonOverwrite(EditorPrefs.GetString(k_BrushSettingsPref), brushSettings);
                    if (EditorPrefs.HasKey(k_BrushSettingsName))
                    {
                        brushSettings.name = EditorPrefs.GetString(k_BrushSettingsName);
                    }
                }
                else
                {
                    SetBrushSettings(brushSettingsAsset != null ? brushSettingsAsset : PolyEditorUtility.GetFirstOrNew <BrushSettings>());
                }
            }

            RefreshAvailableBrushes();

            SetTool(BrushTool.RaiseLower, false);

            Selection.selectionChanged -= OnSelectionChanged;
            Selection.selectionChanged += OnSelectionChanged;
        }