12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075 |
- /*
- Copyright (c) 2020 Omar Duarte
- Unauthorized copying of this file, via any medium is strictly prohibited.
- Writen by Omar Duarte, 2020.
- 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 System.Linq;
- using UnityEngine;
- namespace PluginMaster
- {
- [UnityEditor.InitializeOnLoad]
- public static partial class PWBIO
- {
- #region PWB WINDOWS
- public static void CloseAllWindows(bool closeToolbar = true)
- {
- BrushProperties.CloseWindow();
- ToolProperties.CloseWindow();
- PrefabPalette.CloseWindow();
- if (closeToolbar) PWBToolbar.CloseWindow();
- }
- #endregion
- #region SELECTION
- public static void UpdateSelection()
- {
- if (SelectionManager.topLevelSelection.Length == 0)
- {
- if (tool == ToolManager.PaintTool.EXTRUDE)
- {
- _initialExtrudePosition = _extrudeHandlePosition = _selectionSize = Vector3.zero;
- _extrudeDirection = Vector3Int.zero;
- }
- return;
- }
- if (tool == ToolManager.PaintTool.EXTRUDE)
- {
- var selectionBounds = ExtrudeManager.settings.space == Space.World
- ? BoundsUtils.GetSelectionBounds(SelectionManager.topLevelSelection)
- : BoundsUtils.GetSelectionBounds(SelectionManager.topLevelSelection,
- ExtrudeManager.settings.rotationAccordingTo == ExtrudeSettings.RotationAccordingTo.FRIST_SELECTED
- ? SelectionManager.topLevelSelection.First().transform.rotation
- : SelectionManager.topLevelSelection.Last().transform.rotation);
- _initialExtrudePosition = _extrudeHandlePosition = selectionBounds.center;
- _selectionSize = selectionBounds.size;
- _extrudeDirection = Vector3Int.zero;
- }
- else if (tool == ToolManager.PaintTool.SELECTION)
- {
- _selectedBoxPointIdx = 10;
- _selectionRotation = Quaternion.identity;
- _selectionChanged = true;
- _editingSelectionHandlePosition = false;
- var rotation = GetSelectionRotation();
- _selectionBounds = BoundsUtils.GetSelectionBounds(SelectionManager.topLevelSelection, rotation);
- _selectionRotation = rotation;
- }
- }
- #endregion
- #region UNSAVED CHANGES
- private const string UNSAVED_CHANGES_TITLE = "Unsaved Changes";
- private const string UNSAVED_CHANGES_MESSAGE = "There are unsaved changes.\nWhat would you like to do?";
- private const string UNSAVED_CHANGES_OK = "Save";
- private const string UNSAVED_CHANGES_CANCEL = "Don't Save";
- private static void DisplaySaveDialog(System.Action Save)
- {
- if (UnityEditor.EditorUtility.DisplayDialog(UNSAVED_CHANGES_TITLE,
- UNSAVED_CHANGES_MESSAGE, UNSAVED_CHANGES_OK, UNSAVED_CHANGES_CANCEL)) Save();
- else repaint = true;
- }
- private static void AskIfWantToSave(ToolManager.ToolState state, System.Action Save)
- {
- switch (PWBCore.staticData.unsavedChangesAction)
- {
- case PWBData.UnsavedChangesAction.ASK:
- if (state == ToolManager.ToolState.EDIT) DisplaySaveDialog(Save);
- break;
- case PWBData.UnsavedChangesAction.SAVE:
- if (state == ToolManager.ToolState.EDIT) Save();
- BrushstrokeManager.ClearBrushstroke();
- break;
- case PWBData.UnsavedChangesAction.DISCARD:
- repaint = true;
- return;
- }
- }
- #endregion
- #region COMMON
- private const float TAU = Mathf.PI * 2;
- private static int _controlId;
- public static int controlId { set => _controlId = value; }
- private static ToolManager.PaintTool tool => ToolManager.tool;
- private static UnityEditor.Tool _unityCurrentTool = UnityEditor.Tool.None;
- private static Camera _sceneViewCamera = null;
- public static bool repaint { get; set; }
- static PWBIO()
- {
- LineData.SetNextId();
- SelectionManager.selectionChanged += UpdateSelection;
- UnityEditor.Undo.undoRedoPerformed += OnUndoPerformed;
- UnityEditor.SceneView.duringSceneGui += DuringSceneGUI;
- PaletteManager.OnPaletteChanged += OnPaletteChanged;
- PaletteManager.OnBrushSelectionChanged += OnBrushSelectionChanged;
- ToolManager.OnToolModeChanged += OnEditModeChanged;
- LineInitializeOnLoad();
- ShapeInitializeOnLoad();
- TilingInitializeOnLoad();
- FloorInitializeOnLoad();
- WallInitializeOnLoad();
- }
- private static void OnPaletteChanged()
- {
- ApplySelectionFilters();
- switch (ToolManager.tool)
- {
- case ToolManager.PaintTool.ERASER:
- if (EraserManager.settings.command == ModifierToolSettings.Command.SELECT_PALETTE_PREFABS)
- UpdateOctree();
- break;
- case ToolManager.PaintTool.REPLACER:
- if (ReplacerManager.settings.command == ModifierToolSettings.Command.SELECT_PALETTE_PREFABS)
- UpdateOctree();
- BrushstrokeManager.ClearReplacerDictionary();
- break;
- case ToolManager.PaintTool.CIRCLE_SELECT:
- if (CircleSelectManager.settings.command == ModifierToolSettings.Command.SELECT_PALETTE_PREFABS)
- UpdateOctree();
- break;
- }
- }
- private static void OnBrushSelectionChanged()
- {
- switch (ToolManager.tool)
- {
- case ToolManager.PaintTool.GRAVITY:
- InitializeGravityHeight();
- break;
- case ToolManager.PaintTool.LINE:
- ClearLineStroke();
- break;
- case ToolManager.PaintTool.SHAPE:
- ClearShapeStroke();
- break;
- case ToolManager.PaintTool.TILING:
- ClearTilingStroke();
- break;
- case ToolManager.PaintTool.SELECTION:
- ApplySelectionFilters();
- break;
- case ToolManager.PaintTool.ERASER:
- if (EraserManager.settings.command == ModifierToolSettings.Command.SELECT_BRUSH_PREFABS)
- UpdateOctree();
- break;
- case ToolManager.PaintTool.REPLACER:
- if (ReplacerManager.settings.command == ModifierToolSettings.Command.SELECT_BRUSH_PREFABS)
- UpdateOctree();
- BrushstrokeManager.ClearReplacerDictionary();
- break;
- case ToolManager.PaintTool.CIRCLE_SELECT:
- if (CircleSelectManager.settings.command == ModifierToolSettings.Command.SELECT_BRUSH_PREFABS)
- UpdateOctree();
- break;
- case ToolManager.PaintTool.FLOOR:
- UpdateFloorSettingsOnBrushChanged();
- break;
- case ToolManager.PaintTool.WALL:
- UpdateWallSettingsOnBrushChanged();
- break;
- }
- }
- public static void SaveUnityCurrentTool() => _unityCurrentTool = UnityEditor.Tools.current;
- public static bool _wasPickingBrushes = false;
- public static void DuringSceneGUI(UnityEditor.SceneView sceneView)
- {
- if (updateStroke) UnityEditor.SceneView.RepaintAll();
- if (sceneView.in2DMode)
- {
- SnapManager.settings.gridOnZ = true;
- PWBToolbar.RepaintWindow();
- }
- if (repaint)
- {
- if (tool == ToolManager.PaintTool.SHAPE) BrushstrokeManager.UpdateShapeBrushstroke();
- sceneView.Repaint();
- repaint = false;
- }
- GizmosInput();
- PaletteInput(sceneView);
- _sceneViewCamera = sceneView.camera;
- if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape
- && (tool == ToolManager.PaintTool.PIN || tool == ToolManager.PaintTool.BRUSH
- || tool == ToolManager.PaintTool.GRAVITY || tool == ToolManager.PaintTool.ERASER
- || tool == ToolManager.PaintTool.REPLACER || tool == ToolManager.PaintTool.CIRCLE_SELECT
- || tool == ToolManager.PaintTool.FLOOR || tool == ToolManager.PaintTool.WALL))
- ToolManager.DeselectTool();
- var repaintScene = _wasPickingBrushes == PaletteManager.pickingBrushes;
- _wasPickingBrushes = PaletteManager.pickingBrushes;
- if (PaletteManager.pickingBrushes)
- {
- UnityEditor.HandleUtility.AddDefaultControl(_controlId);
- if (repaintScene) UnityEditor.SceneView.RepaintAll();
- if (Event.current.button == 0 && Event.current.type == EventType.MouseDown) Event.current.Use();
- return;
- }
- if (ToolManager.tool != ToolManager.PaintTool.NONE)
- {
- if (PWBSettings.shortcuts.editModeToggle.Check())
- {
- switch (tool)
- {
- case ToolManager.PaintTool.LINE:
- case ToolManager.PaintTool.SHAPE:
- case ToolManager.PaintTool.TILING:
- ToolManager.editMode = !ToolManager.editMode;
- _persistentItemWasEdited = false;
- ToolProperties.RepainWindow();
- break;
- default: break;
- }
- }
- if (PaletteManager.selectedBrushIdx == -1 && (tool == ToolManager.PaintTool.PIN
- || tool == ToolManager.PaintTool.BRUSH || tool == ToolManager.PaintTool.GRAVITY
- || ((tool == ToolManager.PaintTool.LINE || tool == ToolManager.PaintTool.SHAPE
- || tool == ToolManager.PaintTool.TILING)
- && !ToolManager.editMode)))
- {
- if (tool == ToolManager.PaintTool.LINE && _lineData != null && _lineData.state != ToolManager.ToolState.NONE)
- ResetLineState();
- else if (tool == ToolManager.PaintTool.SHAPE
- && _shapeData != null && _shapeData.state != ToolManager.ToolState.NONE)
- ResetShapeState();
- else if (tool == ToolManager.PaintTool.TILING
- && _tilingData != null && _tilingData.state != ToolManager.ToolState.NONE)
- ResetTilingState();
- }
- if (Event.current.type == EventType.MouseEnterWindow) _pinned = false;
- if (Event.current.type == EventType.MouseMove || Event.current.type == EventType.MouseDrag)
- {
- sceneView.Focus();
- }
- else if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.V)
- _snapToVertex = true;
- else if (Event.current.type == EventType.KeyUp && Event.current.keyCode == KeyCode.V)
- _snapToVertex = false;
- if (tool == ToolManager.PaintTool.BRUSH || tool == ToolManager.PaintTool.GRAVITY
- || tool == ToolManager.PaintTool.ERASER || tool == ToolManager.PaintTool.REPLACER
- || tool == ToolManager.PaintTool.CIRCLE_SELECT)
- {
- var settings = ToolManager.GetSettingsFromTool(tool);
- BrushRadiusShortcuts(settings as CircleToolBase);
- }
- if (PWBCore.staticData.tempCollidersAction == PWBData.TempCollidersAction.CREATE_WITHIN_FRUSTRUM)
- PWBCore.CreateTempCollidersWithinFrustum(sceneView.camera);
- switch (tool)
- {
- case ToolManager.PaintTool.PIN:
- PinDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.BRUSH:
- BrushDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.GRAVITY:
- GravityToolDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.LINE:
- LineDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.SHAPE:
- ShapeDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.TILING:
- TilingDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.ERASER:
- EraserDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.REPLACER:
- ReplacerDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.SELECTION:
- SelectionDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.CIRCLE_SELECT:
- CircleSelectDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.EXTRUDE:
- ExtrudeDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.MIRROR:
- MirrorDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.FLOOR:
- FloorToolDuringSceneGUI(sceneView);
- break;
- case ToolManager.PaintTool.WALL:
- WallToolDuringSceneGUI(sceneView);
- break;
- }
- if ((tool != ToolManager.PaintTool.EXTRUDE && tool != ToolManager.PaintTool.SELECTION
- && tool != ToolManager.PaintTool.MIRROR) && Event.current.type == EventType.Layout
- && !ToolManager.editMode)
- {
- UnityEditor.Tools.current = UnityEditor.Tool.None;
- UnityEditor.HandleUtility.AddDefaultControl(_controlId);
- }
- }
- GridDuringSceneGui(sceneView);
- }
- private static float UpdateRadius(float radius)
- => Mathf.Max(radius * (1f + Mathf.Sign(Event.current.delta.y) * 0.05f), 0.05f);
- private static Vector3 TangentSpaceToWorld(Vector3 tangent, Vector3 bitangent, Vector2 tangentSpacePos)
- => (tangent * tangentSpacePos.x + bitangent * tangentSpacePos.y);
- private static void UpdateStrokeDirection(Vector3 hitPoint)
- {
- var dir = hitPoint - _prevMousePos;
- if (dir.sqrMagnitude > 0.3f)
- {
- _strokeDirection = hitPoint - _prevMousePos;
- _prevMousePos = hitPoint;
- }
- }
- public static void ResetUnityCurrentTool() => UnityEditor.Tools.current = _unityCurrentTool;
- private static bool MouseDot(out Vector3 point, out Vector3 normal,
- PaintOnSurfaceToolSettingsBase.PaintMode mode, bool in2DMode,
- bool paintOnPalettePrefabs, bool castOnMeshesWithoutCollider, bool snapOnGrid)
- {
- point = Vector3.zero;
- normal = Vector3.up;
- var mousePos = Event.current.mousePosition;
- if (mousePos.x < 0 || mousePos.x >= Screen.width || mousePos.y < 0 || mousePos.y >= Screen.height) return false;
- var mouseRay = UnityEditor.HandleUtility.GUIPointToWorldRay(mousePos);
- Vector3 SnapPoint(Vector3 hitPoint, ref Vector3 snapNormal)
- {
- if (_snapToVertex)
- {
- if (SnapToVertex(mouseRay, out RaycastHit snappedHit, in2DMode))
- {
- _snappedToVertex = true;
- hitPoint = snappedHit.point;
- snapNormal = snappedHit.normal;
- }
- }
- else if (SnapManager.settings.snappingEnabled)
- {
- hitPoint = SnapPosition(hitPoint, snapOnGrid, true);
- mouseRay.origin = hitPoint - mouseRay.direction;
- if (Physics.Raycast(mouseRay, out RaycastHit hitInfo)) snapNormal = hitInfo.normal;
- else if (MeshUtils.Raycast(mouseRay, out RaycastHit meshHitInfo, out GameObject c,
- octree.GetNearby(mouseRay, 1).Where(o => o != null).ToArray(),
- float.MaxValue)) snapNormal = meshHitInfo.normal;
- }
- return hitPoint;
- }
- RaycastHit surfaceHit;
- bool surfaceFound = MouseRaycast(mouseRay, out surfaceHit, out GameObject collider,
- float.MaxValue, -1, paintOnPalettePrefabs, castOnMeshesWithoutCollider);
- if (mode != PaintOnSurfaceToolSettingsBase.PaintMode.ON_SHAPE && surfaceFound)
- {
- normal = surfaceHit.normal;
- point = SnapPoint(surfaceHit.point, ref normal);
- return true;
- }
- if (mode != PaintOnSurfaceToolSettingsBase.PaintMode.ON_SURFACE)
- {
- if (surfaceFound)
- {
- point = SnapPoint(surfaceHit.point, ref normal);
- var direction = SnapManager.settings.rotation * Vector3.down;
- var ray = new Ray(point - direction, direction);
- if (MouseRaycast(ray, out RaycastHit hitInfo, out collider, float.MaxValue, -1,
- paintOnPalettePrefabs, castOnMeshesWithoutCollider)) point = hitInfo.point;
- UpdateGridOrigin(point);
- return true;
- }
- if (GridRaycast(mouseRay, out RaycastHit gridHit))
- {
- point = SnapPoint(gridHit.point, ref normal);
- return true;
- }
- }
- return false;
- }
- private static bool _updateStroke = false;
- public static bool updateStroke { get => _updateStroke; set => _updateStroke = value; }
- public static void UpdateStroke() => updateStroke = true;
- public static void UpdateSelectedPersistentObject()
- {
- BrushstrokeManager.UpdateBrushstroke(false);
- switch (tool)
- {
- case ToolManager.PaintTool.LINE:
- if (_selectedPersistentLineData != null) _editingPersistentLine = true;
- break;
- case ToolManager.PaintTool.SHAPE:
- if (_selectedPersistentShapeData != null) _editingPersistentShape = true;
- break;
- case ToolManager.PaintTool.TILING:
- if (_selectedPersistentTilingData != null) _editingPersistentTiling = true;
- break;
- }
- repaint = true;
- }
- public static int selectedPointIdx
- {
- get
- {
- switch (ToolManager.tool)
- {
- case ToolManager.PaintTool.TILING:
- if (ToolManager.editMode)
- {
- if (_selectedPersistentTilingData == null) return -1;
- return _selectedPersistentTilingData.selectedPointIdx;
- }
- else if (_tilingData.state == ToolManager.ToolState.EDIT) return _tilingData.selectedPointIdx;
- break;
- case ToolManager.PaintTool.LINE:
- if (ToolManager.editMode)
- {
- if (_selectedPersistentLineData == null) return -1;
- return _selectedPersistentLineData.selectedPointIdx;
- }
- else if (_lineData.state == ToolManager.ToolState.EDIT) return _lineData.selectedPointIdx;
- break;
- case ToolManager.PaintTool.SHAPE:
- if (ToolManager.editMode)
- {
- if (_selectedPersistentShapeData == null) return -1;
- return _selectedPersistentShapeData.selectedPointIdx;
- }
- else if (_shapeData.state == ToolManager.ToolState.EDIT) return _shapeData.selectedPointIdx;
- break;
- }
- return -1;
- }
- }
- private static bool _updateHandlePosition = false;
- private static Vector3 _handlePosition;
- public static void UpdateHandlePosition()
- {
- _updateHandlePosition = true;
- if (tool == ToolManager.PaintTool.TILING && tilingData != null) ApplyTilingHandlePosition(tilingData);
- BrushstrokeManager.UpdateBrushstroke(false);
- }
- public static Vector3 handlePosition { get => _handlePosition; set => _handlePosition = value; }
- private static bool _updateHandleRotation = false;
- private static Quaternion _handleRotation;
- public static void UpdateHandleRotation()
- {
- _updateHandleRotation = true;
- BrushstrokeManager.UpdateBrushstroke(false);
- }
- public static Quaternion handleRotation { get => _handleRotation; set => _handleRotation = value; }
- private static void DrawCircleTool(Vector3 center, Camera camera, Color color, float radius)
- {
- const float polygonSideSize = 0.3f;
- const int minPolygonSides = 8;
- const int maxPolygonSides = 60;
- var polygonSides = Mathf.Clamp((int)(TAU * radius / polygonSideSize),
- minPolygonSides, maxPolygonSides);
- var periPoints = new System.Collections.Generic.List<Vector3>();
- for (int i = 0; i < polygonSides; ++i)
- {
- var radians = TAU * i / (polygonSides - 1f);
- var tangentDir = new Vector2(Mathf.Cos(radians), Mathf.Sin(radians));
- var worldDir = TangentSpaceToWorld(camera.transform.right, camera.transform.up, tangentDir);
- periPoints.Add(center + (worldDir * radius));
- }
- UnityEditor.Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;
- UnityEditor.Handles.color = new Color(1f, 1f, 1f, 1f);
- UnityEditor.Handles.DrawAAPolyLine(5, periPoints.ToArray());
- UnityEditor.Handles.color = color;
- UnityEditor.Handles.DrawAAPolyLine(5, periPoints.ToArray());
- }
- private static void GetCircleToolTargets(Ray mouseRay, Camera camera, ISelectionBrushTool selectionBrushTool,
- float radius, System.Collections.Generic.HashSet<GameObject> targets)
- {
- var nearbyObjects = octree.GetNearby(mouseRay, radius).Where(o => o != null);
- targets.Clear();
- if (selectionBrushTool.outermostPrefabFilter)
- {
- foreach (var nearby in nearbyObjects)
- {
- if (nearby == null) continue;
- var outermost = UnityEditor.PrefabUtility.GetOutermostPrefabInstanceRoot(nearby);
- if (outermost == null) targets.Add(nearby);
- else if (!targets.Contains(outermost)) targets.Add(outermost);
- }
- }
- else targets.UnionWith(nearbyObjects);
- var toSelect = targets.ToArray();
- targets.Clear();
- var closestDistSqr = float.MaxValue;
- for (int i = 0; i < toSelect.Length; ++i)
- {
- var obj = toSelect[i];
- if (obj == null) continue;
- var magnitude = BoundsUtils.GetAverageMagnitude(obj.transform);
- if (radius < magnitude / 2) continue;
- if (selectionBrushTool.onlyTheClosest)
- {
- var pos = obj.transform.position;
- var distSqr = (pos - camera.transform.position).sqrMagnitude;
- if (distSqr < closestDistSqr)
- {
- closestDistSqr = distSqr;
- targets.Clear();
- targets.Add(obj);
- }
- continue;
- }
- targets.Add(obj);
- }
- }
- #endregion
- #region PERSISTENT OBJECTS
- public static void OnUndoPerformed()
- {
- _octree = null;
- _boundsOctree = null;
- if (tool == ToolManager.PaintTool.LINE && UnityEditor.Undo.GetCurrentGroupName() == LineData.COMMAND_NAME)
- {
- OnUndoLine();
- UpdateStroke();
- }
- else if (tool == ToolManager.PaintTool.SHAPE && UnityEditor.Undo.GetCurrentGroupName() == ShapeData.COMMAND_NAME)
- {
- OnUndoShape();
- UpdateStroke();
- }
- else if (tool == ToolManager.PaintTool.TILING && UnityEditor.Undo.GetCurrentGroupName() == TilingData.COMMAND_NAME)
- {
- OnUndoTiling();
- UpdateStroke();
- }
- if (ToolManager.tool == ToolManager.PaintTool.LINE
- || ToolManager.tool == ToolManager.PaintTool.SHAPE
- || ToolManager.tool == ToolManager.PaintTool.TILING)
- PWBCore.staticData.SaveAndUpdateVersion();
- else
- {
- if (ToolManager.tool == ToolManager.PaintTool.REPLACER) BrushstrokeManager.ClearReplacerDictionary();
- BrushstrokeManager.UpdateBrushstroke();
- }
- UnityEditor.SceneView.RepaintAll();
- }
- public static void OnToolChange(ToolManager.PaintTool prevTool)
- {
- switch (prevTool)
- {
- case ToolManager.PaintTool.LINE:
- ResetLineState();
- break;
- case ToolManager.PaintTool.SHAPE:
- ResetShapeState();
- break;
- case ToolManager.PaintTool.TILING:
- ResetTilingState();
- break;
- case ToolManager.PaintTool.EXTRUDE:
- ResetExtrudeState();
- break;
- case ToolManager.PaintTool.MIRROR:
- ResetMirrorState();
- break;
- default: break;
- }
- _meshesAndRenderers.Clear();
- UnityEditor.SceneView.RepaintAll();
- }
- private static void OnEditModeChanged()
- {
- switch (tool)
- {
- case ToolManager.PaintTool.LINE:
- OnLineToolModeChanged();
- break;
- case ToolManager.PaintTool.SHAPE:
- OnShapeToolModeChanged();
- break;
- case ToolManager.PaintTool.TILING:
- OnTilingToolModeChanged();
- break;
- default: break;
- }
- }
- private static void DeleteDisabledObjects()
- {
- if (_disabledObjects == null) return;
- foreach (var obj in _disabledObjects)
- {
- if (obj == null) continue;
- obj.SetActive(true);
- UnityEditor.Undo.DestroyObjectImmediate(obj);
- }
- }
- private static void ResetSelectedPersistentObject<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA>
- (PersistentToolManagerBase<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA> manager,
- ref bool editingPersistentObject, TOOL_DATA initialPersistentData)
- where TOOL_NAME : IToolName, new()
- where TOOL_SETTINGS : IToolSettings, new()
- where CONTROL_POINT : ControlPoint, new()
- where TOOL_DATA : PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT>, new()
- where SCENE_DATA : SceneData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA>, new()
- {
- editingPersistentObject = false;
- if (initialPersistentData == null) return;
- var selectedItem = manager.GetItem(initialPersistentData.id);
- if (selectedItem == null) return;
- selectedItem.ResetPoses(initialPersistentData);
- selectedItem.ClearSelection();
- }
- private static void DeselectPersistentItems<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA>
- (PersistentToolManagerBase<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA> manager)
- where TOOL_NAME : IToolName, new()
- where TOOL_SETTINGS : IToolSettings, new()
- where CONTROL_POINT : ControlPoint, new()
- where TOOL_DATA : PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT>, new()
- where SCENE_DATA : SceneData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA>, new()
- {
- var persitentTilings = manager.GetPersistentItems();
- foreach (var i in persitentTilings) i.ClearSelection();
- }
- private static bool ApplySelectedPersistentObject<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA>
- (bool deselectPoint, ref bool editingPersistentObject, ref TOOL_DATA initialPersistentData,
- ref TOOL_DATA selectedPersistentData,
- PersistentToolManagerBase<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA, SCENE_DATA> manager)
- where TOOL_NAME : IToolName, new()
- where TOOL_SETTINGS : IToolSettings, new()
- where CONTROL_POINT : ControlPoint, new()
- where TOOL_DATA : PersistentData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT>, new()
- where SCENE_DATA : SceneData<TOOL_NAME, TOOL_SETTINGS, CONTROL_POINT, TOOL_DATA>, new()
- {
- editingPersistentObject = false;
- if (initialPersistentData == null) return false;
- var selected = manager.GetItem(initialPersistentData.id);
- if (selected == null)
- {
- initialPersistentData = null;
- selectedPersistentData = null;
- return false;
- }
- selected.UpdatePoses();
- if (_paintStroke.Count > 0)
- {
- var objDic = Paint(selected.settings as IPaintToolSettings, PAINT_CMD, true, true);
- foreach (var paintedItem in objDic)
- {
- var persistentItem = manager.GetItem(paintedItem.Key);
- if (persistentItem == null) continue;
- persistentItem.AddObjects(paintedItem.Value.ToArray());
- }
- }
- if (deselectPoint)
- {
- DeselectPersistentItems(manager);
- }
- DeleteDisabledObjects();
- _persistentPreviewData.Clear();
- PWBCore.staticData.SaveAndUpdateVersion();
- if (!deselectPoint) return true;
- var persistentObjects = manager.GetPersistentItems();
- foreach (var item in persistentObjects) item.ClearSelection();
- return true;
- }
- static bool _persistentItemWasEdited = false;
- public static void DuplicateItem(long itemId)
- {
- var toolMan = ToolManager.GetCurrentPersistentToolManager();
- var clone = toolMan.Duplicate(itemId);
- ToolManager.editMode = true;
- clone.isSelected = true;
- var allItems = toolMan.GetItems();
- foreach (var item in allItems)
- {
- if (item == clone) continue;
- item.isSelected = false;
- item.ClearSelection();
- }
- var bounds = clone.GetBounds(1.1f);
- UnityEditor.SceneView.lastActiveSceneView.Frame(bounds, false);
- if (ToolManager.tool == ToolManager.PaintTool.LINE)
- {
- LineManager.editModeType = LineManager.EditModeType.LINE_POSE;
- PWBIO.SelectLine(clone as LineData);
- }
- else if (ToolManager.tool == ToolManager.PaintTool.SHAPE) PWBIO.SelectShape(clone as ShapeData);
- else if (ToolManager.tool == ToolManager.PaintTool.TILING) PWBIO.SelectTiling(clone as TilingData);
- }
- public static void PersistentItemContextMenu(UnityEditor.GenericMenu menu,
- IPersistentData data, Vector2 mousePosition)
- {
- void DeleteItem(bool deleteObjects)
- {
- var toolMan = ToolManager.GetCurrentPersistentToolManager();
- toolMan.DeletePersistentItem(data.id, deleteObjects);
- UnityEditor.SceneView.RepaintAll();
- }
- menu.AddItem(new GUIContent("Select parent object ... "
- + PWBSettings.shortcuts.editModeSelectParent.combination.ToString()), on: false, () =>
- {
- var parent = data.GetParent();
- if (parent != null) UnityEditor.Selection.activeGameObject = parent;
- });
- menu.AddItem(new GUIContent("Duplicate ... "
- + PWBSettings.shortcuts.editModeDuplicate.combination.ToString()), on: false, () => DuplicateItem(data.id));
- menu.AddItem(new GUIContent("Delete item and its children ... "
- + PWBSettings.shortcuts.editModeDeleteItemAndItsChildren.combination.ToString()),
- on: false, () => DeleteItem(deleteObjects: true));
- menu.AddItem(new GUIContent("Delete item but not its children ... "
- + PWBSettings.shortcuts.editModeDeleteItemButNotItsChildren.combination.ToString()), on: false,
- () => DeleteItem(deleteObjects: false));
- menu.AddSeparator(string.Empty);
- menu.AddItem(new GUIContent(data.toolName + " properties..."), on: false,
- () => ItemPropertiesWindow.ShowItemProperties(data, mousePosition));
- }
- #endregion
- #region OCTREE
- private const float MIN_OCTREE_NODE_SIZE = 0.5f;
- private static PointOctree<GameObject> _octree = new PointOctree<GameObject>(10, Vector3.zero, MIN_OCTREE_NODE_SIZE);
- private static BoundsOctree<GameObject> _boundsOctree = new BoundsOctree<GameObject>(initialWorldSize: 10,
- initialWorldPos: Vector3.zero, MIN_OCTREE_NODE_SIZE, MIN_OCTREE_NODE_SIZE);
- private static System.Collections.Generic.HashSet<GameObject> _paintedObjects
- = new System.Collections.Generic.HashSet<GameObject>();
- public static PointOctree<GameObject> octree
- {
- get
- {
- if (_octree == null) UpdateOctree();
- return _octree;
- }
- }
- public static BoundsOctree<GameObject> boundsOctree
- {
- get
- {
- if (_boundsOctree == null) UpdateOctree();
- return _boundsOctree;
- }
- }
- public static void UpdateOctree()
- {
- _octree = new PointOctree<GameObject>(10, Vector3.zero, MIN_OCTREE_NODE_SIZE);
- _boundsOctree = new BoundsOctree<GameObject>(initialWorldSize: 10,
- initialWorldPos: Vector3.zero, MIN_OCTREE_NODE_SIZE, MIN_OCTREE_NODE_SIZE);
- if (PaletteManager.paletteCount == 0) return;
- if ((tool == ToolManager.PaintTool.PIN || tool == ToolManager.PaintTool.BRUSH
- || tool == ToolManager.PaintTool.GRAVITY) && PaletteManager.selectedBrushIdx < 0) return;
- #if UNITY_2022_2_OR_NEWER
- var allObjects = GameObject.FindObjectsByType<GameObject>(FindObjectsSortMode.None);
- #else
- var allObjects = GameObject.FindObjectsOfType<GameObject>();
- #endif
- _paintedObjects.Clear();
- var allPrefabsPaths = new System.Collections.Generic.HashSet<string>();
- bool AddPrefabPath(MultibrushItemSettings item)
- {
- if (item.prefab == null) return false;
- var path = UnityEditor.AssetDatabase.GetAssetPath(item.prefab);
- if (allPrefabsPaths.Contains(path)) return false;
- allPrefabsPaths.Add(path);
- return true;
- }
- if (tool == ToolManager.PaintTool.ERASER || tool == ToolManager.PaintTool.REPLACER
- || tool == ToolManager.PaintTool.CIRCLE_SELECT)
- {
- ISelectionBrushTool SelectionBrushSettings = EraserManager.settings;
- if (tool == ToolManager.PaintTool.REPLACER) SelectionBrushSettings = ReplacerManager.settings;
- else if (tool == ToolManager.PaintTool.CIRCLE_SELECT) SelectionBrushSettings = CircleSelectManager.settings;
- if (SelectionBrushSettings.command == SelectionBrushToolSettings.Command.SELECT_PALETTE_PREFABS)
- foreach (var brush in PaletteManager.selectedPalette.brushes)
- foreach (var item in brush.items) AddPrefabPath(item);
- else if (PaletteManager.selectedBrush != null
- && SelectionBrushSettings.command == SelectionBrushToolSettings.Command.SELECT_BRUSH_PREFABS)
- foreach (var item in PaletteManager.selectedBrush.items) AddPrefabPath(item);
- SelectionManager.UpdateSelection();
- bool modifyAll = SelectionBrushSettings.command == SelectionBrushToolSettings.Command.SELECT_ALL;
- bool modifyAllButSelected = false;
- if (tool == ToolManager.PaintTool.ERASER || tool == ToolManager.PaintTool.REPLACER)
- {
- IModifierTool modifierSettings = tool == ToolManager.PaintTool.ERASER
- ? EraserManager.settings as IModifierTool : ReplacerManager.settings;
- modifyAllButSelected = modifierSettings.modifyAllButSelected;
- }
- foreach (var obj in allObjects)
- {
- if (!obj.activeInHierarchy) continue;
- if (!modifyAll && !UnityEditor.PrefabUtility.IsAnyPrefabInstanceRoot(obj)) continue;
- var prefabPath = UnityEditor.PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(obj);
- bool isBrush = allPrefabsPaths.Contains(prefabPath);
- if (!isBrush && !modifyAll) continue;
- if (modifyAllButSelected && SelectionManager.selection.Contains(obj)) continue;
- AddPaintedObject(obj);
- }
- }
- else
- {
- foreach (var brush in PaletteManager.selectedPalette.brushes)
- foreach (var item in brush.items) AddPrefabPath(item);
- foreach (var obj in allObjects)
- {
- if (!obj.activeInHierarchy) continue;
- if (!UnityEditor.PrefabUtility.IsAnyPrefabInstanceRoot(obj)) continue;
- var prefabPath = UnityEditor.PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(obj);
- bool isBrush = allPrefabsPaths.Contains(prefabPath);
- if (isBrush) AddPaintedObject(obj);
- }
- }
- }
- public static void AddPaintedObject(GameObject obj)
- {
- if (_octree == null) _octree = new PointOctree<GameObject>(10, obj.transform.position, MIN_OCTREE_NODE_SIZE);
- _octree.Add(obj, obj.transform.position);
- if (_boundsOctree == null) _boundsOctree = new BoundsOctree<GameObject>(initialWorldSize: 10,
- initialWorldPos: Vector3.zero, MIN_OCTREE_NODE_SIZE, MIN_OCTREE_NODE_SIZE);
- Bounds bounds;
- if (ToolManager.tool == ToolManager.PaintTool.FLOOR)
- bounds = BoundsUtils.GetBoundsRecursive(obj.transform, SnapManager.settings.rotation);
- else bounds = BoundsUtils.GetBoundsRecursive(obj.transform);
- _boundsOctree.Add(obj, bounds);
- _paintedObjects.Add(obj);
- }
- public static bool OctreeContains(int objId) => octree.Contains(objId);
- #endregion
- #region STROKE & PAINT
- private const string PWB_OBJ_NAME = "Prefab World Builder";
- private static Vector3 _prevMousePos = Vector3.zero;
- private static Vector3 _strokeDirection = Vector3.forward;
- private static Transform _autoParent = null;
- private static System.Collections.Generic.Dictionary<string, Transform> _subParents
- = new System.Collections.Generic.Dictionary<string, Transform>();
- private static Mesh quadMesh;
- private class PaintStrokeItem
- {
- public readonly GameObject prefab = null;
- public readonly Vector3 position = Vector3.zero;
- public readonly Quaternion rotation = Quaternion.identity;
- public readonly Vector3 scale = Vector3.one;
- public readonly int layer = 0;
- public readonly bool flipX = false;
- public readonly bool flipY = false;
- public readonly int index = 0;
- private Transform _parent = null;
- private string _persistentParentId = string.Empty;
- private Transform _surface = null;
- public Transform parent { get => _parent; set => _parent = value; }
- public string persistentParentId { get => _persistentParentId; set => _persistentParentId = value; }
- public Transform surface { get => _surface; set => _surface = value; }
- public PaintStrokeItem(GameObject prefab, Vector3 position, Quaternion rotation,
- Vector3 scale, int layer, Transform parent, Transform surface, bool flipX, bool flipY, int index = -1)
- {
- this.prefab = prefab;
- this.position = position;
- this.rotation = rotation;
- this.scale = scale;
- this.layer = layer;
- this.flipX = flipX;
- this.flipY = flipY;
- this.index = index;
- _parent = parent;
- _surface = surface;
- }
- }
- private static System.Collections.Generic.List<PaintStrokeItem> _paintStroke
- = new System.Collections.Generic.List<PaintStrokeItem>();
- private static void BrushRadiusShortcuts(CircleToolBase settings)
- {
- if (PWBSettings.shortcuts.brushRadius.Check())
- {
- var combi = PWBSettings.shortcuts.brushRadius.combination;
- var delta = Mathf.Sign(combi.delta);
- settings.radius = Mathf.Max(settings.radius * (1f + delta * 0.03f), 0.05f);
- if (settings is BrushToolSettings)
- {
- if (BrushManager.settings.heightType == BrushToolSettings.HeightType.RADIUS)
- BrushManager.settings.maxHeightFromCenter = BrushManager.settings.radius;
- }
- ToolProperties.RepainWindow();
- }
- }
- private static void BrushstrokeMouseEvents(BrushToolBase settings)
- {
- if (PaletteManager.selectedBrush == null) return;
- if (Event.current.button == 0 && !Event.current.alt && Event.current.type == EventType.MouseUp
- && PaletteManager.selectedBrush.patternMachine != null
- && PaletteManager.selectedBrush.restartPatternForEachStroke)
- {
- PaletteManager.selectedBrush.patternMachine.Reset();
- BrushstrokeManager.UpdateBrushstroke();
- }
- else if (PWBSettings.shortcuts.brushUpdatebrushstroke.Check())
- {
- BrushstrokeManager.UpdateBrushstroke();
- repaint = true;
- }
- else if (PWBSettings.shortcuts.brushResetRotation.Check()) _brushAngle = 0;
- else if (PWBSettings.shortcuts.brushDensity.Check()
- && settings.brushShape != BrushToolBase.BrushShape.POINT)
- {
- settings.density += (int)Mathf.Sign(PWBSettings.shortcuts.brushDensity.combination.delta);
- ToolProperties.RepainWindow();
- }
- else if (PWBSettings.shortcuts.brushRotate.Check())
- _brushAngle -= PWBSettings.shortcuts.brushRotate.combination.delta * 1.8f; //180deg/100px
- 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 && !Event.current.control && !Event.current.shift)
- _pinned = false;
- }
- if ((Event.current.keyCode == KeyCode.LeftControl || Event.current.keyCode == KeyCode.RightControl
- || Event.current.keyCode == KeyCode.RightShift || Event.current.keyCode == KeyCode.LeftShift)
- && Event.current.type == EventType.KeyUp) _pinned = false;
- }
- private struct MeshAndRenderer
- {
- public Mesh mesh;
- public Renderer renderer;
- public MeshAndRenderer(Mesh mesh, Renderer renderer)
- {
- this.mesh = mesh;
- this.renderer = renderer;
- }
- }
- private static System.Collections.Generic.Dictionary<int, MeshAndRenderer[]> _meshesAndRenderers
- = new System.Collections.Generic.Dictionary<int, MeshAndRenderer[]>();
- private static void PreviewBrushItem(GameObject prefab, Matrix4x4 rootToWorld, int layer,
- Camera camera, bool redMaterial, bool reverseTriangles, bool flipX, bool flipY)
- {
- var id = prefab.GetInstanceID();
- if (!_meshesAndRenderers.ContainsKey(id))
- {
- var meshesAndRenderers = new System.Collections.Generic.List<MeshAndRenderer>();
- var filters = prefab.GetComponentsInChildren<MeshFilter>();
- foreach (var filter in filters)
- {
- var mesh = filter.sharedMesh;
- if (mesh == null) continue;
- var renderer = filter.GetComponent<MeshRenderer>();
- if (renderer == null) continue;
- meshesAndRenderers.Add(new MeshAndRenderer(mesh, renderer));
- }
- var skinedMeshRenderers = prefab.GetComponentsInChildren<SkinnedMeshRenderer>();
- foreach (var renderer in skinedMeshRenderers)
- {
- var mesh = renderer.sharedMesh;
- if (mesh == null) continue;
- meshesAndRenderers.Add(new MeshAndRenderer(mesh, renderer));
- }
- _meshesAndRenderers.Add(id, meshesAndRenderers.ToArray());
- }
- foreach (var item in _meshesAndRenderers[id])
- {
- var mesh = item.mesh;
- var childToWorld = rootToWorld * item.renderer.transform.localToWorldMatrix;
- var matrices = new Matrix4x4[] { childToWorld };
- if (!redMaterial)
- {
- if (item.renderer is SkinnedMeshRenderer)
- {
- var smr = (SkinnedMeshRenderer)item.renderer;
- var rootBone = smr.rootBone;
- if (rootBone != null)
- {
- while (rootBone.parent != null && rootBone.parent != prefab.transform) rootBone = rootBone.parent;
- var rotation = rootBone.rotation;
- var position = rootBone.position;
- position.y = 0f;
- var scale = rootBone.localScale;
- childToWorld = rootToWorld * Matrix4x4.TRS(position, rotation, scale);
- }
- }
- var materials = item.renderer.sharedMaterials;
- if (materials == null && materials.Length > 0 && materials.Length >= mesh.subMeshCount) continue;
- for (int subMeshIdx = 0; subMeshIdx < Mathf.Min(mesh.subMeshCount, materials.Length); ++subMeshIdx)
- {
- var material = materials[subMeshIdx];
- if (reverseTriangles)
- {
- var tempMesh = (Mesh)GameObject.Instantiate(mesh);
- tempMesh.SetTriangles(mesh.triangles.Reverse().ToArray(), subMeshIdx);
- tempMesh.subMeshCount = mesh.subMeshCount;
- int vCount = 0;
- for (int i = 0; i < mesh.subMeshCount; ++i)
- {
- var desc = mesh.GetSubMesh(mesh.subMeshCount - i - 1);
- desc.indexStart = vCount;
- tempMesh.SetSubMesh(i, desc);
- vCount += desc.indexCount;
- }
- material = materials[mesh.subMeshCount - subMeshIdx - 1];
- Graphics.DrawMesh(tempMesh, childToWorld, material, layer, camera, subMeshIdx);
- tempMesh = null;
- }
- else Graphics.DrawMesh(mesh, childToWorld, material, layer, camera, subMeshIdx);
- }
- }
- else
- {
- for (int subMeshIdx = 0; subMeshIdx < mesh.subMeshCount; ++subMeshIdx)
- Graphics.DrawMesh(mesh, childToWorld, transparentRedMaterial, layer, camera, subMeshIdx);
- }
- }
- var SpriteRenderers = prefab.GetComponentsInChildren<SpriteRenderer>()
- .Where(r => r.enabled && r.sprite != null && r.gameObject.activeSelf).ToArray();
- if (SpriteRenderers.Length > 0)
- {
- var bounds = BoundsUtils.GetBoundsRecursive(prefab.transform);
- foreach (var spriteRenderer in SpriteRenderers)
- DrawSprite(spriteRenderer, rootToWorld, camera, bounds, flipX, flipY);
- }
- }
- private static void DrawSprite(SpriteRenderer renderer, Matrix4x4 matrix,
- Camera camera, Bounds objectBounds, bool flipX, bool flipY)
- {
- if (quadMesh == null)
- {
- quadMesh = new Mesh
- {
- vertices = new[] { new Vector3(-.5f, .5f, 0), new Vector3(.5f, .5f, 0),
- new Vector3(-.5f, -.5f, 0), new Vector3(.5f, -.5f, 0) },
- normals = new[] { Vector3.forward, Vector3.forward, Vector3.forward, Vector3.forward },
- triangles = new[] { 0, 2, 3, 3, 1, 0 }
- };
- }
- var minUV = new Vector2(float.MaxValue, float.MaxValue);
- var maxUV = new Vector2(float.MinValue, float.MinValue);
- foreach (var uv in renderer.sprite.uv)
- {
- minUV = Vector2.Min(minUV, uv);
- maxUV = Vector2.Max(maxUV, uv);
- }
- var uvs = new Vector2[] { new Vector2(minUV.x, maxUV.y), new Vector2(maxUV.x, maxUV.y),
- new Vector2(minUV.x, minUV.y), new Vector2(maxUV.x, minUV.y)};
- void ToggleFlip(ref bool flip) => flip = !flip;
- if (renderer.flipX) ToggleFlip(ref flipX);
- if (renderer.flipY) ToggleFlip(ref flipY);
- if (flipX)
- {
- uvs[0].x = maxUV.x;
- uvs[1].x = minUV.x;
- uvs[2].x = maxUV.x;
- uvs[3].x = minUV.x;
- }
- if (flipY)
- {
- uvs[0].y = minUV.y;
- uvs[1].y = minUV.y;
- uvs[2].y = maxUV.y;
- uvs[3].y = maxUV.y;
- }
- quadMesh.uv = uvs;
- var pivotToCenter = (renderer.sprite.rect.size / 2 - renderer.sprite.pivot) / renderer.sprite.pixelsPerUnit;
- if (renderer.flipX) pivotToCenter.x = -pivotToCenter.x;
- if (renderer.flipY) pivotToCenter.y = -pivotToCenter.y;
- var mpb = new MaterialPropertyBlock();
- mpb.SetTexture("_MainTex", renderer.sprite.texture);
- mpb.SetColor("_Color", renderer.color);
- matrix *= Matrix4x4.Translate(pivotToCenter);
- matrix *= renderer.transform.localToWorldMatrix;
- matrix *= Matrix4x4.Scale(new Vector3(
- renderer.sprite.textureRect.width / renderer.sprite.pixelsPerUnit,
- renderer.sprite.textureRect.height / renderer.sprite.pixelsPerUnit, 1));
- Graphics.DrawMesh(quadMesh, matrix, renderer.sharedMaterial, 0, camera, 0, mpb);
- }
- public static bool painting { get; set; }
- private const string PAINT_CMD = "Paint";
- private static System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<(GameObject, int)>>
- Paint(IPaintToolSettings settings, string commandName = PAINT_CMD,
- bool addTempCollider = true, bool persistent = false, string toolObjectId = "")
- {
- painting = true;
- var paintedObjects = new System.Collections.Generic.Dictionary<string,
- System.Collections.Generic.List<(GameObject, int)>>();
- if (_paintStroke.Count == 0)
- {
- if (BrushstrokeManager.brushstroke.Length == 0) BrushstrokeManager.UpdateBrushstroke();
- return paintedObjects;
- }
- foreach (var item in _paintStroke)
- {
- if (item.prefab == null) continue;
- var persistentParentId = persistent ? item.persistentParentId : toolObjectId;
- 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);
- item.parent = GetParent(settings, item.prefab.name, true, item.surface, persistentParentId);
- if (addTempCollider) PWBCore.AddTempCollider(obj);
- if (!paintedObjects.ContainsKey(persistentParentId))
- paintedObjects.Add(persistentParentId, new System.Collections.Generic.List<(GameObject, int)>());
- paintedObjects[persistentParentId].Add((obj, item.index));
- var spriteRenderers = obj.GetComponentsInChildren<SpriteRenderer>();
- foreach (var spriteRenderer in spriteRenderers)
- {
- var flipX = spriteRenderer.flipX;
- var flipY = spriteRenderer.flipY;
- if (item.flipX) flipX = !flipX;
- if (item.flipY) flipY = !flipY;
- spriteRenderer.flipX = flipX;
- spriteRenderer.flipY = flipY;
- var center = BoundsUtils.GetBoundsRecursive(spriteRenderer.transform,
- spriteRenderer.transform.rotation).center;
- var pivotToCenter = center - spriteRenderer.transform.position;
- var delta = Vector3.zero;
- if (item.flipX) delta.x = pivotToCenter.x * -2;
- if (item.flipY) delta.y = pivotToCenter.y * -2;
- spriteRenderer.transform.position += delta;
- }
- AddPaintedObject(obj);
- UnityEditor.Undo.RegisterCreatedObjectUndo(obj, commandName);
- if (root != null) UnityEditor.Undo.SetTransformParent(root.transform, item.parent, commandName);
- else UnityEditor.Undo.SetTransformParent(obj.transform, item.parent, commandName);
- }
- if (_paintStroke.Count > 0) BrushstrokeManager.UpdateBrushstroke();
- _paintStroke.Clear();
- return paintedObjects;
- }
- public static void ResetAutoParent() => _autoParent = null;
- private const string NO_PALETTE_NAME = "<#PALETTE@>";
- private const string NO_TOOL_NAME = "<#TOOL@>";
- private const string NO_OBJ_ID = "<#ID@>";
- private const string NO_BRUSH_NAME = "<#BRUSH@>";
- private const string NO_PREFAB_NAME = "<#PREFAB@>";
- private const string PARENT_KEY_SEPARATOR = "<#@>";
- public static Transform GetParent(IPaintToolSettings settings, string prefabName,
- bool create, Transform surface, string toolObjectId = "")
- {
- if (!create) return settings.parent;
- if (settings.autoCreateParent)
- {
- var pwbObj = GameObject.Find(PWB_OBJ_NAME);
- if (pwbObj == null) _autoParent = new GameObject(PWB_OBJ_NAME).transform;
- else _autoParent = pwbObj.transform;
- }
- else _autoParent = settings.setSurfaceAsParent ? surface : settings.parent;
- if (!settings.createSubparentPerPalette && !settings.createSubparentPerTool
- && !settings.createSubparentPerBrush && !settings.createSubparentPerPrefab) return _autoParent;
- var _autoParentId = _autoParent == null ? -1 : _autoParent.gameObject.GetInstanceID();
- string GetSubParentKey(int parentId = -1, string palette = NO_PALETTE_NAME,
- string tool = NO_TOOL_NAME, string id = NO_OBJ_ID,
- string brush = NO_BRUSH_NAME, string prefab = NO_PREFAB_NAME)
- => parentId + PARENT_KEY_SEPARATOR + palette + PARENT_KEY_SEPARATOR
- + tool + PARENT_KEY_SEPARATOR + id + PARENT_KEY_SEPARATOR + brush
- + PARENT_KEY_SEPARATOR + prefab;
- string subParentKey = GetSubParentKey(_autoParentId,
- settings.createSubparentPerPalette ? PaletteManager.selectedPalette.name : NO_PALETTE_NAME,
- settings.createSubparentPerTool ? ToolManager.GetToolFromSettings(settings).ToString() : NO_TOOL_NAME,
- string.IsNullOrEmpty(toolObjectId) ? NO_OBJ_ID : toolObjectId,
- settings.createSubparentPerBrush ? PaletteManager.selectedBrush.name : NO_BRUSH_NAME,
- settings.createSubparentPerPrefab ? prefabName : NO_PREFAB_NAME);
- create = !(_subParents.ContainsKey(subParentKey));
- if (!create && _subParents[subParentKey] == null) create = true;
- if (!create) return _subParents[subParentKey];
- Transform CreateSubParent(string key, string name, Transform transformParent)
- {
- Transform subParentTransform = null;
- var subParentIsEmpty = true;
- if (transformParent != null)
- {
- subParentTransform = transformParent.Find(name);
- if (subParentTransform != null)
- subParentIsEmpty = subParentTransform.GetComponents<Component>().Length == 1;
- }
- if (subParentTransform == null || !subParentIsEmpty)
- {
- var obj = new GameObject(name);
- var subParent = obj.transform;
- subParent.SetParent(transformParent);
- subParent.localPosition = Vector3.zero;
- subParent.localRotation = Quaternion.identity;
- subParent.localScale = Vector3.one;
- if (_subParents.ContainsKey(key)) _subParents[key] = subParent;
- else _subParents.Add(key, subParent);
- return subParent;
- }
- return subParentTransform;
- }
- var parent = _autoParent;
- void CreateSubParentIfDoesntExist(string name, string palette = NO_PALETTE_NAME,
- string tool = NO_TOOL_NAME, string id = NO_OBJ_ID, string brush = NO_BRUSH_NAME,
- string prefab = NO_PREFAB_NAME)
- {
- var key = GetSubParentKey(_autoParentId, palette, tool, id, brush, prefab);
- var keyExist = _subParents.ContainsKey(key);
- var subParent = keyExist ? _subParents[key] : null;
- if (subParent != null) parent = subParent;
- if (!keyExist || subParent == null) parent = CreateSubParent(key, name, parent);
- }
- var keySplitted = subParentKey.Split(new string[] { PARENT_KEY_SEPARATOR },
- System.StringSplitOptions.None);
- var keyPlaletteName = keySplitted[1];
- var keyToolName = keySplitted[2];
- var keyToolObjId = keySplitted[3];
- var keyBrushName = keySplitted[4];
- var keyPrefabName = keySplitted[5];
- if (keyPlaletteName != NO_PALETTE_NAME)
- CreateSubParentIfDoesntExist(keyPlaletteName, keyPlaletteName);
- if (keyToolName != NO_TOOL_NAME)
- {
- CreateSubParentIfDoesntExist(keyToolName, keyPlaletteName, keyToolName);
- if (keyToolObjId != NO_OBJ_ID)
- CreateSubParentIfDoesntExist(keyToolObjId, keyPlaletteName, keyToolName, keyToolObjId);
- }
- if (keyBrushName != NO_BRUSH_NAME)
- CreateSubParentIfDoesntExist(keyBrushName, keyPlaletteName, keyToolName,
- keyToolObjId, keyBrushName);
- if (keyPrefabName != NO_PREFAB_NAME)
- CreateSubParentIfDoesntExist(keyPrefabName, keyPlaletteName,
- keyToolName, keyToolObjId, keyBrushName, keyPrefabName);
- return parent;
- }
- private static bool IsVisible(ref GameObject obj)
- {
- if (obj == null) return false;
- var parentRenderer = obj.GetComponentInParent<Renderer>();
- var parentTerrain = obj.GetComponentInParent<Terrain>();
- if (parentRenderer != null) obj = parentRenderer.gameObject;
- else if (parentTerrain != null) obj = parentTerrain.gameObject;
- else
- {
- var parent = obj.transform.parent;
- if (parent != null)
- {
- var siblingRenderer = parent.GetComponentInChildren<Renderer>();
- var siblingTerrain = parent.GetComponentInChildren<Terrain>();
- if (siblingRenderer != null) obj = parent.gameObject;
- else if (siblingTerrain != null) obj = parent.gameObject;
- }
- }
- var renderers = obj.GetComponentsInChildren<Renderer>();
- if (renderers.Length > 0)
- {
- foreach (var renderer in renderers)
- if (renderer.enabled) return true;
- }
- var terrains = obj.GetComponentsInChildren<Terrain>();
- if (terrains.Length > 0)
- {
- foreach (var terrain in terrains)
- if (terrain.enabled) return true;
- }
- return false;
- }
- private static bool IsVisible(GameObject obj)
- {
- obj = PWBCore.GetGameObjectFromTempCollider(obj);
- return IsVisible(ref obj);
- }
- private struct TerrainDataSimple
- {
- public float[,,] alphamaps;
- public Vector3 size;
- public TerrainLayer[] layers;
- public TerrainDataSimple(float[,,] alphamaps, Vector3 size, TerrainLayer[] layers)
- => (this.alphamaps, this.size, this.layers) = (alphamaps, size, layers);
- }
- private static System.Collections.Generic.Dictionary<int, TerrainDataSimple> _terrainAlphamaps
- = new System.Collections.Generic.Dictionary<int, TerrainDataSimple>();
- public static bool MouseRaycast(Ray mouseRay, out RaycastHit mouseHit,
- out GameObject collider, float maxDistance, LayerMask layerMask,
- bool paintOnPalettePrefabs, bool castOnMeshesWithoutCollider, string[] tags = null,
- TerrainLayer[] terrainLayers = null, System.Collections.Generic.HashSet<GameObject> exceptions = null,
- bool sameOriginAsRay = true, Vector3 origin = new Vector3())
- {
- bool IsTempCollider(GameObject obj)
- {
- var hitParent = obj.transform.parent;
- return hitParent != null && hitParent.gameObject.GetInstanceID() == PWBCore.parentColliderId;
- }
- GameObject GetOriginalCollider(GameObject obj)
- {
- if (IsTempCollider(obj)) return PWBCore.GetGameObjectFromTempColliderId(obj.GetInstanceID());
- return obj;
- }
- bool TagFilterPassed(GameObject obj)
- {
- if (tags == null) return true;
- if (tags.Length == 0) return true;
- if (obj.tag == "untagged") return true;
- return tags.Contains(obj.tag);
- }
- bool ExceptionFilterPassed(GameObject obj)
- {
- if (exceptions == null) return true;
- if (exceptions.Count == 0) return true;
- return !exceptions.Contains(obj);
- }
- bool PaletteFilterPassed(GameObject obj)
- {
- if (paintOnPalettePrefabs) return true;
- return !PaletteManager.selectedPalette.ContainsSceneObject(obj);
- }
- bool TerrainFilterPassed(GameObject obj, Vector3 mouseHitPoint)
- {
- if (terrainLayers == null) return true;
- if (terrainLayers.Length == 0) return true;
- var terrain = obj.GetComponent<Terrain>();
- if (terrain == null) return true;
- var instanceId = terrain.GetInstanceID();
- int alphamapW = 0;
- int alphamapH = 0;
- float[,,] alphamaps;
- Vector3 terrainSize;
- TerrainLayer[] layers;
- if (_terrainAlphamaps.ContainsKey(instanceId))
- {
- alphamaps = _terrainAlphamaps[instanceId].alphamaps;
- alphamapW = alphamaps.GetLength(1);
- alphamapH = alphamaps.GetLength(0);
- terrainSize = _terrainAlphamaps[instanceId].size;
- layers = _terrainAlphamaps[instanceId].layers;
- }
- else
- {
- var terrainData = terrain.terrainData;
- if (terrainData == null) return false;
- alphamapW = terrainData.alphamapWidth;
- alphamapH = terrainData.alphamapHeight;
- alphamaps = terrainData.GetAlphamaps(0, 0, alphamapW, alphamapH);
- terrainSize = terrainData.size;
- layers = terrainData.terrainLayers;
- _terrainAlphamaps.Add(instanceId, new TerrainDataSimple(alphamaps, terrainSize, layers));
- }
- var numLayers = alphamaps.GetLength(2);
- var localHit = terrain.transform.InverseTransformPoint(mouseHitPoint);
- var alphaHitX = Mathf.Clamp(Mathf.RoundToInt(localHit.x / terrainSize.x * alphamapW), 0, alphamapW - 1);
- var alphaHitZ = Mathf.Clamp(Mathf.RoundToInt(localHit.z / terrainSize.z * alphamapH), 0, alphamapH - 1);
- int layerUnderCursorIdx = 0;
- for (int k = 1; k < numLayers; k++)
- {
- if (alphamaps[alphaHitZ, alphaHitX, k] > 0.5)
- {
- layerUnderCursorIdx = k;
- break;
- }
- }
- var layerUnderCursor = layers[layerUnderCursorIdx];
- return terrainLayers.Contains(layerUnderCursor);
- }
- bool AllFiltersPassed(ref GameObject obj, Vector3 mouseHitPoint)
- {
- if (obj == null) return false;
- if (!IsVisible(ref obj)) return false;
- if (!TagFilterPassed(obj)) return false;
- if (!ExceptionFilterPassed(obj)) return false;
- if (!PaletteFilterPassed(obj)) return false;
- if (!TerrainFilterPassed(obj, mouseHitPoint)) return false;
- return true;
- }
- mouseHit = new RaycastHit();
- collider = null;
- bool physicsValidHit = Physics.Raycast(mouseRay, out mouseHit,
- maxDistance, layerMask, QueryTriggerInteraction.Ignore);
- if (physicsValidHit && mouseHit.collider != null) collider = mouseHit.collider.gameObject;
- GameObject[] nearbyObjects = null;
- var meshValidHit = false;
- if (castOnMeshesWithoutCollider && octree != null)
- {
- nearbyObjects = octree.GetNearby(mouseRay, 1f);
- if (nearbyObjects.Length > 0)
- {
- nearbyObjects = nearbyObjects.Where(o => o != null).ToArray();
- }
- if (MeshUtils.Raycast(mouseRay, out RaycastHit meshHit, out GameObject meshCollider,
- nearbyObjects, maxDistance, sameOriginAsRay, origin))
- {
- var meshHitDistance = sameOriginAsRay ? meshHit.distance : (meshHit.point - origin).magnitude;
- var mouseHitDistance = sameOriginAsRay ? mouseHit.distance : (mouseHit.point - origin).magnitude;
- if (!physicsValidHit || meshHitDistance < mouseHitDistance)
- {
- mouseHit = meshHit;
- collider = meshCollider;
- meshValidHit = true;
- }
- }
- }
- var hitDictionary = new System.Collections.Generic.Dictionary<GameObject, RaycastHit>();
- if (physicsValidHit)
- {
- var hits = Physics.RaycastAll(mouseRay, maxDistance, layerMask, QueryTriggerInteraction.Ignore);
- if (collider != null && hits.Length == 1)
- {
- var obj = GetOriginalCollider(collider);
- if (AllFiltersPassed(ref obj, mouseHit.point))
- {
- collider = obj;
- return true;
- }
- }
- foreach (var hit in hits)
- {
- var obj = hit.collider.gameObject;
- if (!hitDictionary.ContainsKey(obj)) hitDictionary.Add(obj, hit);
- else
- {
- var hitDistance = sameOriginAsRay ? hit.distance : (hit.point - origin).magnitude;
- var dicDistance = sameOriginAsRay ? hitDictionary[obj].distance
- : (hitDictionary[obj].point - origin).magnitude;
- if (hitDistance < dicDistance) hitDictionary[obj] = hit;
- }
- }
- }
- if (castOnMeshesWithoutCollider && meshValidHit)
- {
- if (MeshUtils.RaycastAll(mouseRay, out RaycastHit[] hitArray, out GameObject[] colliders,
- nearbyObjects, maxDistance))
- {
- for (int i = 0; i < hitArray.Length; ++i)
- {
- var obj = colliders[i];
- var hit = hitArray[i];
- if (!hitDictionary.ContainsKey(obj)) hitDictionary.Add(obj, hit);
- else
- {
- var hitDistance = sameOriginAsRay ? hit.distance : (hit.point - origin).magnitude;
- var dicDistance = sameOriginAsRay ? hitDictionary[obj].distance
- : (hitDictionary[obj].point - origin).magnitude;
- if (hitDistance < dicDistance) hitDictionary[obj] = hit;
- }
- }
- }
- }
- var minDistance = float.MaxValue;
- collider = null;
- var validHit = false;
- foreach (var hitPair in hitDictionary)
- {
- var hitDistance = sameOriginAsRay ? hitPair.Value.distance : (hitPair.Value.point - origin).magnitude;
- var hitCollider = GetOriginalCollider(hitPair.Key);
- if (!AllFiltersPassed(ref hitCollider, mouseHit.point)) continue;
- if (hitDistance < minDistance)
- {
- minDistance = hitDistance;
- mouseHit = hitPair.Value;
- collider = hitCollider;
- validHit = true;
- }
- }
- return validHit;
- }
- public static float GetDistanceToSurface(Vector3[] vertices, Matrix4x4 TRS, Vector3 direction, float magnitude,
- bool paintOnPalettePrefabs, bool castOnMeshesWithoutCollider, out Transform surface, GameObject prefab,
- System.Collections.Generic.HashSet<GameObject> exceptions = null)
- {
- surface = null;
- var positiveDistance = float.MinValue;
- var negativeDistance = float.MaxValue;
- bool noSurfaceFound = true;
- void GetDistance(float height, Vector3 direction, out GameObject collider)
- {
- collider = null;
- foreach (var vertex in vertices)
- {
- var origin = TRS.MultiplyPoint(vertex);
- var ray = new Ray(origin - (direction * height), direction);
- if (MouseRaycast(ray, out RaycastHit hitInfo, out GameObject rayCollider,
- float.MaxValue, -1, paintOnPalettePrefabs, castOnMeshesWithoutCollider,
- tags: null, terrainLayers: null, exceptions, sameOriginAsRay: false, origin))
- {
- var prevPosDistance = positiveDistance;
- var prevNegDistance = negativeDistance;
- var distance = hitInfo.distance - height;
- if (hitInfo.distance >= height) positiveDistance = Mathf.Max(distance, positiveDistance);
- else negativeDistance = Mathf.Min(distance, negativeDistance);
- if (collider == null || prevPosDistance != positiveDistance || prevNegDistance != negativeDistance)
- collider = rayCollider;
- noSurfaceFound = false;
- }
- }
- }
- var scale = TRS.lossyScale;
- var scaleMult = Mathf.Max(scale.x + scale.y + scale.z, 1) * 9;
- float hMult = magnitude * scaleMult;
- GameObject surfaceCollider = null;
- GetDistance(Mathf.Max(magnitude * hMult, hMult), direction, out surfaceCollider);
- if (noSurfaceFound) return 0f;
- surface = surfaceCollider.transform;
- var distance = (positiveDistance >= 0 || Mathf.Approximately(positiveDistance, 0))
- ? positiveDistance : negativeDistance;
- if (Mathf.Approximately(distance, float.MinValue) || Mathf.Approximately(distance, float.MaxValue)) distance = 0;
- return distance;
- }
- public static float GetBottomDistanceToSurface(Vector3[] bottomVertices, Matrix4x4 TRS,
- float bottomMagnitude, bool paintOnPalettePrefabs, bool castOnMeshesWithoutCollider,
- out Transform surface, System.Collections.Generic.HashSet<GameObject> exceptions = null)
- {
- surface = null;
- var positiveDistance = float.MaxValue;
- var negativeDistance = float.MinValue;
- var down = (TRS.rotation * Vector3.down).normalized;
- bool noSurfaceFound = true;
- void GetDistance(float height, Vector3 direction, out GameObject collider)
- {
- collider = null;
- foreach (var vertex in bottomVertices)
- {
- var origin = TRS.MultiplyPoint(vertex);
- var ray = new Ray(origin - (direction * height), direction);
- if (MouseRaycast(ray, out RaycastHit hitInfo, out GameObject rayCollider,
- float.MaxValue, -1, paintOnPalettePrefabs, castOnMeshesWithoutCollider,
- tags: null, terrainLayers: null, exceptions, sameOriginAsRay: false, origin))
- {
- var prevPosDistance = positiveDistance;
- var prevNegDistance = negativeDistance;
- if (hitInfo.distance >= height)
- positiveDistance = Mathf.Min(hitInfo.distance - height, positiveDistance);
- else negativeDistance = Mathf.Max(height - hitInfo.distance, negativeDistance);
- if (prevPosDistance != positiveDistance || prevNegDistance != negativeDistance)
- collider = rayCollider;
- noSurfaceFound = false;
- }
- }
- }
- float hMult = 100f;
- GameObject surfaceCollider = null;
- GetDistance(Mathf.Max(bottomMagnitude * hMult, hMult), down, out surfaceCollider);
- if (noSurfaceFound) return 0f;
- surface = surfaceCollider.transform;
- if (positiveDistance == float.MaxValue) positiveDistance = 0f;
- if (negativeDistance == float.MinValue) negativeDistance = 0f;
- var distance = positiveDistance >= negativeDistance ? positiveDistance : -negativeDistance;
- return distance;
- }
- public static float GetBottomDistanceToSurfaceSigned(Vector3[] bottomVertices, Matrix4x4 TRS,
- float maxDistance, bool paintOnPalettePrefabs, bool castOnMeshesWithoutCollider)
- {
- float distance = 0f;
- var down = Vector3.down;
- foreach (var vertex in bottomVertices)
- {
- var origin = TRS.MultiplyPoint(vertex);
- var ray = new Ray(origin - down * maxDistance, down);
- if (MouseRaycast(ray, out RaycastHit hitInfo, out GameObject collider,
- float.MaxValue, -1, paintOnPalettePrefabs, castOnMeshesWithoutCollider))
- {
- var d = hitInfo.distance - maxDistance;
- if (Mathf.Abs(d) > Mathf.Abs(distance)) distance = d;
- }
- }
- return distance;
- }
- public static float GetPivotDistanceToSurfaceSigned(Vector3 pivot,
- float maxDistance, bool paintOnPalettePrefabs, bool castOnMeshesWithoutCollider)
- {
- var ray = new Ray(pivot + Vector3.up * maxDistance, Vector3.down);
- if (MouseRaycast(ray, out RaycastHit hitInfo, out GameObject collider,
- float.MaxValue, -1, paintOnPalettePrefabs, castOnMeshesWithoutCollider))
- return hitInfo.distance - maxDistance;
- return 0;
- }
- private static BrushstrokeItem[] _brushstroke = null;
- private struct PreviewData
- {
- public readonly GameObject prefab;
- public readonly Matrix4x4 rootToWorld;
- public readonly int layer;
- public readonly bool flipX;
- public readonly bool flipY;
- public PreviewData(GameObject prefab, Matrix4x4 rootToWorld, int layer, bool flipX, bool flipY)
- {
- this.prefab = prefab;
- this.rootToWorld = rootToWorld;
- this.layer = layer;
- this.flipX = flipX;
- this.flipY = flipY;
- }
- }
- private static System.Collections.Generic.List<PreviewData> _previewData
- = new System.Collections.Generic.List<PreviewData>();
- private static bool PreviewIfBrushtrokestaysTheSame(out BrushstrokeItem[] brushstroke,
- Camera camera, bool forceUpdate)
- {
- brushstroke = BrushstrokeManager.brushstroke;
- if (!forceUpdate && _brushstroke != null && BrushstrokeManager.BrushstrokeEqual(brushstroke, _brushstroke))
- {
- foreach (var previewItemData in _previewData)
- PreviewBrushItem(previewItemData.prefab, previewItemData.rootToWorld,
- previewItemData.layer, camera, false, false, previewItemData.flipX, previewItemData.flipY);
- return true;
- }
- _brushstroke = BrushstrokeManager.brushstrokeClone;
- _previewData.Clear();
- return false;
- }
- private static System.Collections.Generic.Dictionary<long, PreviewData[]> _persistentPreviewData
- = new System.Collections.Generic.Dictionary<long, PreviewData[]>();
- private static System.Collections.Generic.Dictionary<long, BrushstrokeItem[]> _persistentLineBrushstrokes
- = new System.Collections.Generic.Dictionary<long, BrushstrokeItem[]>();
- private static void PreviewPersistent(Camera camera)
- {
- foreach (var previewDataArray in _persistentPreviewData.Values)
- foreach (var previewItemData in previewDataArray)
- PreviewBrushItem(previewItemData.prefab, previewItemData.rootToWorld,
- previewItemData.layer, camera, false, false, previewItemData.flipX, previewItemData.flipY);
- }
- #endregion
- #region BRUSH SHAPE INDICATOR
- private static void DrawCricleIndicator(Vector3 hitPoint, Vector3 hitNormal,
- float radius, float height, Vector3 tangent, Vector3 bitangent,
- Vector3 normal, bool paintOnPalettePrefabs, bool castOnMeshesWithoutCollider,
- int layerMask = -1, string[] tags = null, bool drawDropArea = false)
- {
- UnityEditor.Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;
- const float normalOffset = 0.01f;
- const float polygonSideSize = 0.3f;
- const int minPolygonSides = 12;
- const int maxPolygonSides = 36;
- var polygonSides = Mathf.Clamp((int)(TAU * radius / polygonSideSize), minPolygonSides, maxPolygonSides);
- UnityEditor.Handles.color = new Color(0f, 0f, 0f, 0.5f);
- var periPoints = new System.Collections.Generic.List<Vector3>();
- var periPointsShadow = new System.Collections.Generic.List<Vector3>();
- var dropAreaPeriPoints = new System.Collections.Generic.List<Vector3>();
- for (int i = 0; i < polygonSides; ++i)
- {
- var radians = TAU * i / (polygonSides - 1f);
- var tangentDir = new Vector2(Mathf.Cos(radians), Mathf.Sin(radians));
- var worldDir = TangentSpaceToWorld(tangent, bitangent, tangentDir);
- var periPoint = hitPoint + (worldDir * (radius));
- if (drawDropArea) dropAreaPeriPoints.Add(periPoint + Vector3.up * height);
- var periRay = new Ray(periPoint + normal * height, -normal);
- if (MouseRaycast(periRay, out RaycastHit periHit, out GameObject collider,
- height * 2, layerMask, paintOnPalettePrefabs, castOnMeshesWithoutCollider, tags))
- {
- var periHitPoint = periHit.point + hitNormal * normalOffset;
- var shadowPoint = periHitPoint + worldDir * 0.2f;
- periPoints.Add(periHitPoint);
- periPointsShadow.Add(shadowPoint);
- }
- else
- {
- if (periPoints.Count > 0 && i == polygonSides - 1)
- {
- periPoints.Add(periPoints[0]);
- periPointsShadow.Add(periPointsShadow[0]);
- }
- else
- {
- float binSearchRadius = radius;
- float delta = -binSearchRadius / 2;
- for (int j = 0; j < 8; ++j)
- {
- binSearchRadius += delta;
- periPoint = hitPoint + (worldDir * binSearchRadius);
- periRay = new Ray(periPoint + normal * height, -normal);
- if (MouseRaycast(periRay, out RaycastHit binSearchPeriHit,
- out GameObject binSearchCollider, height * 2, layerMask,
- paintOnPalettePrefabs, castOnMeshesWithoutCollider, tags))
- {
- delta = Mathf.Abs(delta) / 2;
- periHit = binSearchPeriHit;
- }
- else delta = -Mathf.Abs(delta) / 2;
- if (Mathf.Abs(delta) < 0.01) break;
- }
- if (periHit.point == Vector3.zero) continue;
- var periHitPoint = periHit.point + hitNormal * normalOffset;
- var shadowPoint = periHitPoint + worldDir * 0.2f;
- periPoints.Add(periHitPoint);
- periPointsShadow.Add(shadowPoint);
- }
- }
- }
- if (periPoints.Count > 0)
- {
- UnityEditor.Handles.color = new Color(1f, 1f, 1f, 0.5f);
- UnityEditor.Handles.DrawAAPolyLine(3, periPoints.ToArray());
- UnityEditor.Handles.color = new Color(0f, 0f, 0f, 0.5f);
- UnityEditor.Handles.DrawAAPolyLine(6, periPointsShadow.ToArray());
- }
- else
- {
- UnityEditor.Handles.color = new Color(1f, 1f, 1f, 0.5f);
- UnityEditor.Handles.DrawWireDisc(hitPoint + hitNormal * normalOffset, hitNormal, radius);
- UnityEditor.Handles.color = new Color(0f, 0f, 0f, 0.5f);
- UnityEditor.Handles.DrawWireDisc(hitPoint + hitNormal * normalOffset, hitNormal, radius + 0.2f);
- }
- if (drawDropArea && dropAreaPeriPoints.Count > 0)
- {
- UnityEditor.Handles.color = new Color(1f, 1f, 1f, 0.5f);
- UnityEditor.Handles.DrawAAPolyLine(3, dropAreaPeriPoints.ToArray());
- }
- }
- private static void DrawSquareIndicator(Vector3 hitPoint, Vector3 hitNormal,
- float radius, float height, Vector3 tangent, Vector3 bitangent,
- Vector3 normal, bool paintOnPalettePrefabs, bool castOnMeshesWithoutCollider,
- int layerMask = -1, string[] tags = null, bool drawDropArea = false)
- {
- UnityEditor.Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;
- const float normalOffset = 0.01f;
- const int minSideSegments = 4;
- const int maxSideSegments = 15;
- var segmentsPerSide = Mathf.Clamp((int)(radius * 2 / 0.3f), minSideSegments, maxSideSegments);
- var segmentCount = segmentsPerSide * 4;
- float segmentSize = radius * 2f / segmentsPerSide;
- float SQRT2 = Mathf.Sqrt(2f);
- UnityEditor.Handles.color = new Color(0f, 0f, 0f, 0.5f);
- var periPoints = new System.Collections.Generic.List<Vector3>();
- var dropAreaPeriPoints = new System.Collections.Generic.List<Vector3>();
- for (int i = 0; i < segmentCount; ++i)
- {
- int sideIdx = i / segmentsPerSide;
- int segmentIdx = i % segmentsPerSide;
- var periPoint = hitPoint;
- if (sideIdx == 0) periPoint += tangent * (segmentSize * segmentIdx - radius) + bitangent * radius;
- else if (sideIdx == 1) periPoint += bitangent * (radius - segmentSize * segmentIdx) + tangent * radius;
- else if (sideIdx == 2) periPoint += tangent * (radius - segmentSize * segmentIdx) - bitangent * radius;
- else periPoint += bitangent * (segmentSize * segmentIdx - radius) - tangent * radius;
- if (drawDropArea) dropAreaPeriPoints.Add(periPoint + Vector3.up * height);
- var worldDir = (periPoint - hitPoint).normalized;
- var periRay = new Ray(periPoint + normal * height, -normal);
- if (MouseRaycast(periRay, out RaycastHit periHit, out GameObject collider,
- height * 2, layerMask, paintOnPalettePrefabs, castOnMeshesWithoutCollider, tags))
- {
- var periHitPoint = periHit.point + hitNormal * normalOffset;
- periPoints.Add(periHitPoint);
- }
- else
- {
- float binSearchRadius = radius * SQRT2;
- float delta = -binSearchRadius / 2;
- for (int j = 0; j < 8; ++j)
- {
- binSearchRadius += delta;
- periPoint = hitPoint + (worldDir * binSearchRadius);
- periRay = new Ray(periPoint + normal * height, -normal);
- if (MouseRaycast(periRay, out RaycastHit binSearchPeriHit,
- out GameObject binSearchCollider, height * 2, layerMask,
- paintOnPalettePrefabs, castOnMeshesWithoutCollider, tags))
- {
- delta = Mathf.Abs(delta) / 2;
- periHit = binSearchPeriHit;
- }
- else delta = -Mathf.Abs(delta) / 2;
- if (Mathf.Abs(delta) < 0.01) break;
- }
- if (periHit.point == Vector3.zero)
- continue;
- var periHitPoint = periHit.point + hitNormal * normalOffset;
- var shadowPoint = periHitPoint + worldDir * 0.2f;
- periPoints.Add(periHitPoint);
- }
- }
- if (periPoints.Count > 0)
- {
- periPoints.Add(periPoints[0]);
- UnityEditor.Handles.color = new Color(0f, 0f, 0f, 0.7f);
- UnityEditor.Handles.DrawAAPolyLine(8, periPoints.ToArray());
- UnityEditor.Handles.color = new Color(1f, 1f, 1f, 0.7f);
- UnityEditor.Handles.DrawAAPolyLine(4, periPoints.ToArray());
- }
- if (drawDropArea && dropAreaPeriPoints.Count > 0)
- {
- dropAreaPeriPoints.Add(dropAreaPeriPoints[0]);
- UnityEditor.Handles.color = new Color(1f, 1f, 1f, 0.5f);
- UnityEditor.Handles.DrawAAPolyLine(3, dropAreaPeriPoints.ToArray());
- }
- }
- #endregion
- #region HANDLES
- private static float _blinkingDelta = 0.05f;
- private static float _blinkingValue = 1f;
- private static void DrawDotHandleCap(Vector3 point, float alpha = 1f,
- float scale = 1f, bool selected = false, bool isPivot = false)
- {
- UnityEditor.Handles.color = new Color(0f, 0f, 0f, 0.7f * alpha);
- var handleSize = UnityEditor.HandleUtility.GetHandleSize(point);
- var sizeDelta = handleSize * 0.0125f;
- UnityEditor.Handles.DotHandleCap(0, point, Quaternion.identity,
- handleSize * 0.0325f * scale * PWBCore.staticData.controPointSize, EventType.Repaint);
- var fillColor = selected ? PWBCore.staticData.selectedContolPointColor
- : (isPivot ? Color.green : UnityEditor.Handles.preselectionColor);
- fillColor.a *= alpha;
- if (selected && PWBCore.staticData.selectedControlPointBlink)
- {
- fillColor.a *= _blinkingValue;
- if (_blinkingValue >= 1) _blinkingDelta = -Mathf.Abs(_blinkingDelta);
- else if (_blinkingValue <= 0) _blinkingDelta = Mathf.Abs(_blinkingDelta);
- _blinkingValue += _blinkingDelta;
- }
- UnityEditor.Handles.color = fillColor;
- UnityEditor.Handles.DotHandleCap(0, point, Quaternion.identity,
- (handleSize * 0.0325f * scale - sizeDelta) * PWBCore.staticData.controPointSize, EventType.Repaint);
- }
- #endregion
- #region DRAG AND DROP
- public class SceneDragReceiver : ISceneDragReceiver
- {
- private int _brushID = -1;
- public int brushId { get => _brushID; set => _brushID = value; }
- public void PerformDrag(Event evt) { }
- public void StartDrag() { }
- public void StopDrag() { }
- public UnityEditor.DragAndDropVisualMode UpdateDrag(Event evt, EventType eventType)
- {
- PrefabPalette.instance.DeselectAllButThis(_brushID);
- ToolManager.tool = ToolManager.PaintTool.PIN;
- return UnityEditor.DragAndDropVisualMode.Generic;
- }
- }
- private static SceneDragReceiver _sceneDragReceiver = new SceneDragReceiver();
- public static SceneDragReceiver sceneDragReceiver => _sceneDragReceiver;
- #endregion
- #region PALETTE
- public static void ReplaceSelected()
- {
- var replacerSettings = new ReplacerSettings();
- _paintStroke.Clear();
- SelectionManager.UpdateSelection();
- var targets = SelectionManager.topLevelSelection;
- BrushstrokeManager.UpdateReplacerBrushstroke(clearDictionary: true, targets);
- ReplacePreview(UnityEditor.SceneView.lastActiveSceneView.camera, replacerSettings, targets);
- var newObjects = Replace();
- if (newObjects != null)
- if (newObjects.Length > 0) UnityEditor.Selection.objects = newObjects;
- }
- private static void PaletteInput(UnityEditor.SceneView sceneView)
- {
- void Repaint()
- {
- PrefabPalette.RepainWindow();
- sceneView.Repaint();
- repaint = true;
- AsyncRepaint();
- }
- if (PWBSettings.shortcuts.palettePreviousBrush.Check())
- {
- PaletteManager.SelectPreviousBrush();
- Repaint();
- }
- else if (PWBSettings.shortcuts.paletteNextBrush.Check())
- {
- PaletteManager.SelectNextBrush();
- Repaint();
- }
- if (PWBSettings.shortcuts.paletteNextBrushScroll.Check())
- {
- Event.current.Use();
- if (PWBSettings.shortcuts.paletteNextBrushScroll.combination.delta > 0) PaletteManager.SelectNextBrush();
- else PaletteManager.SelectPreviousBrush();
- Repaint();
- }
- if (PWBSettings.shortcuts.paletteNextPaletteScroll.Check())
- {
- Event.current.Use();
- if (Event.current.delta.y > 0) PaletteManager.SelectNextPalette();
- else PaletteManager.SelectPreviousPalette();
- Repaint();
- }
- if (PWBSettings.shortcuts.palettePreviousPalette.Check())
- {
- PaletteManager.SelectPreviousPalette();
- Repaint();
- }
- else if (PWBSettings.shortcuts.paletteNextPalette.Check())
- {
- PaletteManager.SelectNextPalette();
- Repaint();
- }
- if (PWBSettings.shortcuts.paletteReplaceSceneSelection.Check())
- {
- ReplaceSelected();
- }
- var pickShortcutOn = PWBSettings.shortcuts.palettePickBrush.Check();
- var pickBrush = PaletteManager.pickingBrushes && Event.current.button == 0
- && Event.current.type == EventType.MouseDown;
- if (pickShortcutOn || pickBrush)
- {
- var mouseRay = UnityEditor.HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
- if (MouseRaycast(mouseRay, out RaycastHit mouseHit, out GameObject collider,
- float.MaxValue, -1, true, true))
- {
- var target = collider.gameObject;
- var outermostPrefab = UnityEditor.PrefabUtility.GetOutermostPrefabInstanceRoot(target);
- if (outermostPrefab != null) target = outermostPrefab;
- var brushIdx = PaletteManager.selectedPalette.FindBrushIdx(target);
- if (brushIdx >= 0) PaletteManager.SelectBrush(brushIdx);
- else if (outermostPrefab != null)
- {
- var prefabAsset = UnityEditor.PrefabUtility.GetCorrespondingObjectFromSource(outermostPrefab);
- PrefabPalette.instance.CreateBrushFromSelection(prefabAsset);
- }
- }
- Event.current.Use();
- if (!pickShortcutOn && pickBrush) PaletteManager.pickingBrushes = false;
- }
- if (PWBSettings.shortcuts.palettePickBrush.holdKeysAndClickCombination.holdingChanged)
- PaletteManager.pickingBrushes = PWBSettings.shortcuts.palettePickBrush.holdKeysAndClickCombination.holdingKeys;
- }
- async static void AsyncRepaint()
- {
- await System.Threading.Tasks.Task.Delay(500);
- repaint = true;
- }
- #endregion
- #region TOOLBAR
- public static void ToogleTool(ToolManager.PaintTool tool)
- {
- #if UNITY_2021_2_OR_NEWER
- #else
- if (PWBToolbar.instance == null) PWBToolbar.ShowWindow();
- #endif
- ToolManager.tool = ToolManager.tool == tool ? ToolManager.PaintTool.NONE : tool;
- PWBToolbar.RepaintWindow();
- }
- #endregion
- #region MODULAR
- private static bool _modularDeleteMode = false;
- private static Mesh _cubeMesh = null;
- private static Mesh cubeMesh
- {
- get
- {
- if (_cubeMesh == null) _cubeMesh = Resources.GetBuiltinResource<Mesh>("Cube.fbx");
- return _cubeMesh;
- }
- }
- #endregion
- #region GIZMOS
- private static void GizmosInput()
- {
- if (PWBSettings.shortcuts.gizmosToggleInfotext.Check())
- {
- PWBCore.staticData.ToggleInfoText();
- }
- }
- #endregion
- }
- }
|