123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- /*
- Copyright (c) 2021 Omar Duarte
- Unauthorized copying of this file, via any medium is strictly prohibited.
- Writen by Omar Duarte, 2021.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- using UnityEngine;
- using System.Linq;
- namespace PluginMaster
- {
- #region DATA & SETTINGS
- [System.Serializable]
- public class ReplacerSettings : CircleToolBase, ISelectionBrushTool, IModifierTool, IPaintToolSettings
- {
- [SerializeField] private bool _keepTargetSize = false;
- [SerializeField] private bool _maintainProportions = false;
- public enum PositionMode { CENTER, PIVOT, ON_SURFACE }
- [SerializeField] private PositionMode _positionMode = PositionMode.CENTER;
- [SerializeField] private bool _sameParentasTarget = true;
- public bool keepTargetSize
- {
- get => _keepTargetSize;
- set
- {
- if (_keepTargetSize == value) return;
- _keepTargetSize = value;
- DataChanged();
- }
- }
- public bool maintainProportions
- {
- get => _maintainProportions;
- set
- {
- if (_maintainProportions == value) return;
- _maintainProportions = value;
- DataChanged();
- }
- }
- public PositionMode positionMode
- {
- get => _positionMode;
- set
- {
- if (_positionMode == value) return;
- _positionMode = value;
- DataChanged();
- }
- }
- public bool sameParentAsTarget
- {
- get => _sameParentasTarget;
- set
- {
- if (_sameParentasTarget == value) return;
- _sameParentasTarget = value;
- DataChanged();
- }
- }
- #region MODIFIER TOOL
- [SerializeField] private ModifierToolSettings _modifierTool = new ModifierToolSettings();
- public ReplacerSettings() => _modifierTool.OnDataChanged += DataChanged;
- public ModifierToolSettings.Command command { get => _modifierTool.command; set => _modifierTool.command = value; }
- public bool modifyAllButSelected
- {
- get => _modifierTool.modifyAllButSelected;
- set => _modifierTool.modifyAllButSelected = value;
- }
- public bool onlyTheClosest
- {
- get => _modifierTool.onlyTheClosest;
- set => _modifierTool.onlyTheClosest = value;
- }
- public bool outermostPrefabFilter
- {
- get => _modifierTool.outermostPrefabFilter;
- set => _modifierTool.outermostPrefabFilter = value;
- }
- #endregion
- #region PAINT TOOL
- [SerializeField] private PaintToolSettings _paintTool = new PaintToolSettings();
- public Transform parent { get => _paintTool.parent; set => _paintTool.parent = value; }
- public bool overwritePrefabLayer
- {
- get => _paintTool.overwritePrefabLayer;
- set => _paintTool.overwritePrefabLayer = value;
- }
- public int layer { get => _paintTool.layer; set => _paintTool.layer = value; }
- public bool autoCreateParent { get => _paintTool.autoCreateParent; set => _paintTool.autoCreateParent = value; }
- public bool setSurfaceAsParent { get => _paintTool.setSurfaceAsParent; set => _paintTool.setSurfaceAsParent = value; }
- public bool createSubparentPerPalette
- {
- get => _paintTool.createSubparentPerPalette;
- set => _paintTool.createSubparentPerPalette = value;
- }
- public bool createSubparentPerTool
- {
- get => _paintTool.createSubparentPerTool;
- set => _paintTool.createSubparentPerTool = value;
- }
- public bool createSubparentPerBrush
- {
- get => _paintTool.createSubparentPerBrush;
- set => _paintTool.createSubparentPerBrush = value;
- }
- public bool createSubparentPerPrefab
- {
- get => _paintTool.createSubparentPerPrefab;
- set => _paintTool.createSubparentPerPrefab = value;
- }
- public bool overwriteBrushProperties
- {
- get => _paintTool.overwriteBrushProperties;
- set => _paintTool.overwriteBrushProperties = value;
- }
- public BrushSettings brushSettings => _paintTool.brushSettings;
- #endregion
- public override void Copy(IToolSettings other)
- {
- var otherReplacerSettings = other as ReplacerSettings;
- if (otherReplacerSettings == null) return;
- base.Copy(other);
- _modifierTool.Copy(otherReplacerSettings);
- _paintTool.Copy(otherReplacerSettings._paintTool);
- _keepTargetSize = otherReplacerSettings._keepTargetSize;
- _maintainProportions = otherReplacerSettings._maintainProportions;
- _positionMode = otherReplacerSettings._positionMode;
- _sameParentasTarget = otherReplacerSettings._sameParentasTarget;
- }
- public override void DataChanged()
- {
- base.DataChanged();
- BrushstrokeManager.ClearReplacerDictionary();
- BrushstrokeManager.UpdateBrushstroke();
- }
- }
- [System.Serializable]
- public class ReplacerManager : ToolManagerBase<ReplacerSettings> { }
- #endregion
- #region PWBIO
- public static partial class PWBIO
- {
- private class ReplacerPaintStrokeItem : PaintStrokeItem
- {
- public Transform target = null;
- public ReplacerPaintStrokeItem(Transform target, GameObject prefab, Vector3 position, Quaternion rotation,
- Vector3 scale, int layer, Transform parent, Transform surface, bool flipX, bool flipY,
- int index = -1) : base(prefab, position, rotation, scale, layer, parent, surface, flipX, flipY, index)
- {
- this.target = target;
- }
- }
- private static System.Collections.Generic.List<Renderer> _replaceRenderers
- = new System.Collections.Generic.List<Renderer>();
- private static bool _replaceAllSelected = false;
- private static void ReplacerMouseEvents()
- {
- var settings = ReplacerManager.settings;
- if (Event.current.button == 0 && !Event.current.alt
- && (Event.current.type == EventType.MouseDown || Event.current.type == EventType.MouseDrag))
- {
- Replace();
- Event.current.Use();
- }
- if (Event.current.button == 1)
- {
- if (Event.current.type == EventType.MouseDown && (Event.current.control || Event.current.shift))
- {
- _pinned = true;
- _pinMouse = Event.current.mousePosition;
- Event.current.Use();
- }
- else if (Event.current.type == EventType.MouseUp) _pinned = false;
- }
- }
- private static void ReplacerDuringSceneGUI(UnityEditor.SceneView sceneView)
- {
- if (PaletteManager.selectedBrushIdx < 0) return;
- if (_replaceAllSelected)
- {
- var targets = SelectionManager.topLevelSelection;
- BrushstrokeManager.UpdateReplacerBrushstroke(clearDictionary: true, targets);
- _paintStroke.Clear();
- _replaceAllSelected = false;
- ReplacePreview(sceneView.camera, ReplacerManager.settings, targets);
- Replace();
- return;
- }
- ReplacerMouseEvents();
- var mousePos = Event.current.mousePosition;
- if (_pinned) mousePos = _pinMouse;
- var mouseRay = UnityEditor.HandleUtility.GUIPointToWorldRay(mousePos);
- var center = mouseRay.GetPoint(_lastHitDistance);
- if (MouseRaycast(mouseRay, out RaycastHit mouseHit, out GameObject collider,
- float.MaxValue, -1, true, true))
- {
- _lastHitDistance = mouseHit.distance;
- center = mouseHit.point;
- PWBCore.UpdateTempCollidersIfHierarchyChanged();
- }
- DrawCircleTool(center, sceneView.camera, new Color(0f, 0f, 0, 1f), ReplacerManager.settings.radius);
- DrawPreview(center, mouseRay, sceneView.camera);
- }
- public static void ResetReplacer()
- {
- foreach (var renderer in _replaceRenderers)
- {
- if (renderer == null) continue;
- renderer.enabled = true;
- }
- _replaceRenderers.Clear();
- _paintStroke.Clear();
- BrushstrokeManager.ClearReplacerDictionary();
- }
- private static Transform _replaceSurface = null;
- private static void ReplacePreview(Camera camera, ReplacerSettings settings, GameObject[] targets)
- {
- BrushstrokeManager.UpdateReplacerBrushstroke(false, targets);
- var brushstroke = BrushstrokeManager.brushstroke;
- foreach (var strokeItem in brushstroke)
- {
- var target = BrushstrokeManager.GetReplacerTargetFromStrokeItem(strokeItem);
- if (target == null) continue;
- var prefab = strokeItem.settings.prefab;
- var itemPosition = strokeItem.tangentPosition;
- var itemRotation = Quaternion.Euler(strokeItem.additionalAngle);
- var scaleMult = strokeItem.scaleMultiplier;
- var itemScale = Vector3.Scale(prefab.transform.localScale, scaleMult);
-
- var layer = settings.overwritePrefabLayer ? settings.layer : target.gameObject.layer;
- Transform parentTransform = target.parent;
- if (!settings.sameParentAsTarget)
- parentTransform = GetParent(settings, prefab.name, create: false, _replaceSurface);
- _paintStroke.Add(new ReplacerPaintStrokeItem(target, prefab, itemPosition,
- itemRotation * prefab.transform.rotation,
- itemScale, layer, parentTransform, null, false, false));
- var rootToWorld = Matrix4x4.TRS(itemPosition, itemRotation, scaleMult)
- * Matrix4x4.Translate(-prefab.transform.position);
- PreviewBrushItem(prefab, rootToWorld, layer, camera, false, false, strokeItem.flipX, strokeItem.flipY);
- }
- }
- private static GameObject[] Replace()
- {
- const string COMMAND_NAME = "Replace";
- foreach (var renderer in _replaceRenderers) renderer.enabled = true;
- _replaceRenderers.Clear();
- var settings = ReplacerManager.settings;
- var newObjects = new System.Collections.Generic.HashSet<GameObject>();
- foreach (ReplacerPaintStrokeItem item in _paintStroke)
- {
- if (item.prefab == null) continue;
- var target = item.target.gameObject;
- if (target == null) continue;
- if (settings.outermostPrefabFilter)
- {
- var nearestRoot = UnityEditor.PrefabUtility.GetNearestPrefabInstanceRoot(target);
- if (nearestRoot != null) target = nearestRoot;
- }
- else
- {
- var parent = target.transform.parent.gameObject;
- if (parent != null)
- {
- GameObject outermost = null;
- do
- {
- outermost = UnityEditor.PrefabUtility.GetOutermostPrefabInstanceRoot(target);
- if (outermost == null) break;
- if (outermost == target) break;
- UnityEditor.PrefabUtility.UnpackPrefabInstance(outermost,
- UnityEditor.PrefabUnpackMode.OutermostRoot, UnityEditor.InteractionMode.UserAction);
- } while (outermost != parent);
- }
- }
- var type = UnityEditor.PrefabUtility.GetPrefabAssetType(item.prefab);
- GameObject obj = type == UnityEditor.PrefabAssetType.NotAPrefab ? GameObject.Instantiate(item.prefab)
- : (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab
- (UnityEditor.PrefabUtility.IsPartOfPrefabAsset(item.prefab)
- ? item.prefab : UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(item.prefab));
- if (settings.overwritePrefabLayer) obj.layer = settings.layer;
- obj.transform.SetPositionAndRotation(item.position, item.rotation);
- obj.transform.localScale = item.scale;
- var root = UnityEditor.PrefabUtility.GetOutermostPrefabInstanceRoot(obj);
- PWBCore.AddTempCollider(obj);
- AddPaintedObject(obj);
- newObjects.Add(obj);
- if (!LineManager.instance.ReplaceObject(target, obj))
- if (!ShapeManager.instance.ReplaceObject(target, obj))
- TilingManager.instance.ReplaceObject(target, obj);
- var tempColliders = PWBCore.GetTempColliders(target);
- if (tempColliders != null)
- foreach (var tempCollider in tempColliders) UnityEditor.Undo.DestroyObjectImmediate(tempCollider);
- UnityEditor.Undo.DestroyObjectImmediate(target);
- UnityEditor.Undo.RegisterCreatedObjectUndo(obj, COMMAND_NAME);
- Transform parentTransform = item.parent;
- if (settings.sameParentAsTarget)
- {
- if (root != null) UnityEditor.Undo.SetTransformParent(root.transform, parentTransform, COMMAND_NAME);
- else UnityEditor.Undo.SetTransformParent(obj.transform, parentTransform, COMMAND_NAME);
- }
- else
- {
- parentTransform = GetParent(settings, item.prefab.name, create: true, _replaceSurface);
- UnityEditor.Undo.SetTransformParent(obj.transform, parentTransform, COMMAND_NAME);
- }
- }
- _paintStroke.Clear();
- BrushstrokeManager.ClearReplacerDictionary();
- return newObjects.ToArray();
- }
- public static void ReplaceAllSelected() => _replaceAllSelected = true;
- private static GameObject[] GetReplacerTargets(Vector3 center, Ray mouseRay, Camera camera)
- {
- var targetsSet = new System.Collections.Generic.HashSet<GameObject>();
- GetCircleToolTargets(mouseRay, camera, ReplacerManager.settings, ReplacerManager.settings.radius, targetsSet);
- var toReplace = targetsSet.ToArray();
- _paintStroke.Clear();
- var result = new System.Collections.Generic.HashSet<GameObject>();
- for (int i = 0; i < toReplace.Length; ++i)
- {
- var obj = toReplace[i];
- var isChild = false;
- foreach (var listed in toReplace)
- {
- if (obj.transform.IsChildOf(listed.transform) && listed != obj)
- {
- isChild = true;
- break;
- }
- }
- if (isChild) continue;
- result.Add(obj);
- }
- return result.ToArray();
- }
- private static void DrawPreview(Vector3 center, Ray mouseRay, Camera camera)
- {
- foreach (var renderer in _replaceRenderers)
- {
- if (renderer == null) continue;
- renderer.enabled = true;
- }
-
- var targets = GetReplacerTargets(center, mouseRay, camera);
- _replaceRenderers.Clear();
- foreach ( var obj in targets)
- _replaceRenderers.AddRange(obj.GetComponentsInChildren<Renderer>().Where(r => r.enabled == true));
- ReplacePreview(camera, ReplacerManager.settings, targets);
- foreach (var renderer in _replaceRenderers) renderer.enabled = false;
- }
- }
- #endregion
- }
|