protected override void OnSettingsGUI() { GUILayout.Label("Mirror Settings", EditorStyles.boldLabel); EditorGUILayout.HelpBox("Mirror objects on the selected axes.\n\nIf Duplicate is toggled a new object will be instantiated from the selection and mirrored, or if disabled the selection will be moved.", MessageType.Info); MirrorSettings scale = m_MirrorAxes; bool x = (scale & MirrorSettings.X) != 0 ? true : false; bool y = (scale & MirrorSettings.Y) != 0 ? true : false; bool z = (scale & MirrorSettings.Z) != 0 ? true : false; bool d = (scale & MirrorSettings.Duplicate) != 0 ? true : false; EditorGUI.BeginChangeCheck(); x = EditorGUILayout.Toggle("X", x); y = EditorGUILayout.Toggle("Y", y); z = EditorGUILayout.Toggle("Z", z); d = EditorGUILayout.Toggle("Duplicate", d); if (EditorGUI.EndChangeCheck()) { m_MirrorAxes.SetValue((MirrorSettings) (x ? MirrorSettings.X : 0) | (y ? MirrorSettings.Y : 0) | (z ? MirrorSettings.Z : 0) | (d ? MirrorSettings.Duplicate : 0)); } GUILayout.FlexibleSpace(); if (GUILayout.Button("Mirror")) { EditorUtility.ShowNotification(DoAction().notification); } }
/// <summary> /// Calculate the weights for this ray. /// </summary> /// <param name="mouseRay">The ray used to calculate weights</param> /// <param name="target">The object on which to calculate the weights</param> /// <returns>true if mouseRay hits the target, false otherwise</returns> bool DoMeshRaycast(Ray mouseRay, BrushTarget target, MirrorSettings mirrorSettings) { if (!Util.IsValid(target)) { return(false); } target.ClearRaycasts(); EditableObject editable = target.editableObject; s_Rays.Clear(); s_Rays.Add(mouseRay); if (mirrorSettings.Axes != BrushMirror.None) { for (int i = 0; i < 3; i++) { if (((uint)mirrorSettings.Axes & (1u << i)) < 1) { continue; } int len = s_Rays.Count; for (int n = 0; n < len; n++) { Vector3 flipVec = ((BrushMirror)(1u << i)).ToVector3(); if (mirrorSettings.Space == MirrorCoordinateSpace.World) { Vector3 cen = editable.gameObjectAttached.GetComponent <Renderer>().bounds.center; s_Rays.Add(new Ray(Vector3.Scale(s_Rays[n].origin - cen, flipVec) + cen, Vector3.Scale(s_Rays[n].direction, flipVec))); } else { Transform t = SceneView.lastActiveSceneView.camera.transform; Vector3 o = t.InverseTransformPoint(s_Rays[n].origin); Vector3 d = t.InverseTransformDirection(s_Rays[n].direction); s_Rays.Add(new Ray(t.TransformPoint(Vector3.Scale(o, flipVec)), t.TransformDirection(Vector3.Scale(d, flipVec)))); } } } } bool hitMesh = false; int[] triangles = editable.editMesh.GetTriangles(); foreach (Ray ray in s_Rays) { PolyRaycastHit hit; if (PolySceneUtility.WorldRaycast(ray, editable.transform, editable.visualMesh.vertices, triangles, out hit)) { target.raycastHits.Add(hit); hitMesh = true; } } PolySceneUtility.CalculateWeightedVertices(target, brushSettings, tool, mode); return(hitMesh); }
/// <summary> /// Update the current brush object and weights with the current mouse position. /// </summary> /// <param name="mousePosition">current mouse position (from Event)</param> /// <param name="isDrag">optional, is dragging the mouse cursor</param> /// <param name="overridenGO">optional, provides an already selected gameobject (used in unit tests only)</param> /// <param name="overridenRay"> optional, provides a ray already created (used in unit tests only)</param> internal void UpdateBrush(Vector2 mousePosition, bool isUserHoldingControl = false, bool isUserHoldingShift = false, bool isDrag = false, GameObject overridenGO = null, Ray?overridenRay = null) { MirrorSettings mirrorSettings = m_BrushMirrorEditor.settings; // NOTE: Quick fix for the lockBrushToFirst feature, probably need to refactor // some code in order to be able to do it properly if (firstGameObject != null && s_LockBrushToFirst) { Ray mouseRay2 = overridenRay != null ? (Ray)overridenRay : HandleUtility.GUIPointToWorldRay(mousePosition); DoMeshRaycast(mouseRay2, brushTarget, mirrorSettings); OnBrushMove(); SceneView.RepaintAll(); this.Repaint(); return; } // Must check HandleUtility.PickGameObject only during MouseMoveEvents or errors will rain. GameObject go = null; brushTarget = null; if (isDrag && s_LockBrushToFirst && m_LastHoveredGameObject != null) { go = m_LastHoveredGameObject; brushTarget = GetBrushTarget(go); } else if (s_IgnoreUnselected || isDrag) { GameObject cur = null; int max = 0; // safeguard against unforeseen while loop errors crashing unity do { int tmp; // overloaded PickGameObject ignores array of GameObjects, this is used // when there are non-selected gameObjects between the mouse and selected // gameObjects. cur = overridenGO; if (cur == null) { m_IgnoreDrag.RemoveAll(x => x == null); cur = HandleUtility.PickGameObject(mousePosition, m_IgnoreDrag.ToArray(), out tmp); } if (cur != null) { if (!PolyEditorUtility.InSelection(cur)) { if (!m_IgnoreDrag.Contains(cur)) { m_IgnoreDrag.Add(cur); } } else { brushTarget = GetBrushTarget(cur); if (brushTarget != null) { go = cur; } else { m_IgnoreDrag.Add(cur); } } } } while(go == null && cur != null && max++ < 128); } else { go = overridenGO; if (go == null) { go = HandleUtility.PickGameObject(mousePosition, false); } if (go != null && PolyEditorUtility.InSelection(go)) { brushTarget = GetBrushTarget(go); } else { go = null; } } bool mouseHoverTargetChanged = false; Ray mouseRay = overridenRay != null ? (Ray)overridenRay : HandleUtility.GUIPointToWorldRay(mousePosition); // if the mouse hover picked up a valid editable, raycast against that. otherwise // raycast all meshes in selection if (go == null) { foreach (var kvp in m_Hovering) { BrushTarget t = kvp.Value; if (Util.IsValid(t) && DoMeshRaycast(mouseRay, t, mirrorSettings)) { brushTarget = t; go = t.gameObject; break; } } } else { if (!DoMeshRaycast(mouseRay, brushTarget, mirrorSettings)) { if (!isDrag || !s_LockBrushToFirst) { go = null; brushTarget = null; } return; } } // if m_Hovering off another gameobject, call OnBrushExit on that last one and mark the // target as having been changed if (go != m_LastHoveredGameObject) { OnBrushExit(m_LastHoveredGameObject); mouseHoverTargetChanged = true; m_LastHoveredGameObject = go; } SceneView.RepaintAll(); this.Repaint(); if (brushTarget == null) { return; } if (mouseHoverTargetChanged) { brushSettings.isUserHoldingControl = isUserHoldingControl; brushSettings.isUserHoldingShift = isUserHoldingShift; OnBrushEnter(brushTarget, brushSettings); // brush is in use, adding a new object to the undo if (m_ApplyingBrush && !m_UndoQueue.Contains(go)) { int curGroup = Undo.GetCurrentGroup(); brushTarget.editableObject.isDirty = true; OnBrushBeginApply(brushTarget, brushSettings); Undo.CollapseUndoOperations(curGroup); } } OnBrushMove(); SceneView.RepaintAll(); this.Repaint(); }
static void Main(string[] args) { try { SkimurContext.Initialize( new Program(), new Skimur.App.Registrar()); _mirrorSettings = SkimurContext.ServiceProvider.GetRequiredService <ISettingsProvider <MirrorSettings> >().Settings; _subService = SkimurContext.ServiceProvider.GetRequiredService <ISubService>(); _postService = SkimurContext.ServiceProvider.GetRequiredService <IPostService>(); _membershipService = SkimurContext.ServiceProvider.GetRequiredService <IMembershipService>(); _commandBus = SkimurContext.ServiceProvider.GetRequiredService <ICommandBus>(); if (_mirrorSettings.SubsToMirror == null || _mirrorSettings.SubsToMirror.Count == 0) { return; } var botUser = _membershipService.GetUserByUserName(_mirrorSettings.BotName); if (botUser == null) { return; } var reddit = new Reddit(); foreach (var subToMirror in _mirrorSettings.SubsToMirror) { Console.WriteLine("Attempting to mirror " + subToMirror + "."); var sub = _subService.GetSubByName(subToMirror); if (sub == null) { Console.WriteLine("Sub doesn't exist."); continue; } var redditSub = reddit.GetSubreddit("/r/" + subToMirror); if (redditSub == null) { Console.WriteLine("Couldn't find reddit sub."); continue; } foreach (var redditPost in redditSub.GetTop(_mirrorSettings.FromTime).Take(_mirrorSettings.PostsPerSub)) { Console.WriteLine("Syncing " + redditPost.Title); var existing = _postService.QueryPosts(redditPost.Title, sub.Id).Select(x => _postService.GetPostById(x)).ToList(); var exists = false; if (existing.Count > 0) { foreach (var item in existing) { if (item.Title == redditPost.Title && item.Mirrored == "reddit") { exists = true; } } } if (exists) { Console.WriteLine("Already exists."); continue; } var createPostResponse = _commandBus.Send <CreatePost, CreatePostResponse>( new CreatePost { CreatedByUserId = botUser.Id, Title = redditPost.Title, Url = redditPost.Url.ToString(), Content = redditPost.SelfText, PostType = redditPost.IsSelfPost ? PostType.Text : PostType.Link, SubName = subToMirror, NotifyReplies = false, Mirror = "reddit", OverrideDateCreated = redditPost.CreatedUTC }); if (!string.IsNullOrEmpty(createPostResponse.Error)) { Console.WriteLine("Couldn't create post. " + createPostResponse.Error); continue; } if (!createPostResponse.PostId.HasValue) { Console.WriteLine("No post id"); continue; } var createCommentResponse = _commandBus.Send <CreateComment, CreateCommentResponse>( new CreateComment { PostId = createPostResponse.PostId.Value, DateCreated = Common.CurrentTime(), AuthorUserName = botUser.UserName, Body = string.Format("Mirrored from [here]({0}).", redditPost.Shortlink), SendReplies = false }); if (!string.IsNullOrEmpty(createCommentResponse.Error)) { Console.WriteLine("Couldn't create comment. " + createCommentResponse.Error); } } } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
/// <summary> /// Calculate the weights for this ray. /// </summary> /// <param name="mouseRay">The ray used to calculate weights</param> /// <param name="target">The object on which to calculate the weights</param> /// <returns>true if mouseRay hits the target, false otherwise</returns> bool DoMeshRaycast(Ray mouseRay, BrushTarget target, MirrorSettings mirrorSettings) { m_SecondaryBrushTargets.Clear(); if (!Util.IsValid(target)) { return(false); } target.ClearRaycasts(); EditableObject editable = target.editableObject; s_Rays.Clear(); s_Rays.Add(mouseRay); if (mirrorSettings.Axes != BrushMirror.None) { for (int i = 0; i < 3; i++) { if (((uint)mirrorSettings.Axes & (1u << i)) < 1) { continue; } int len = s_Rays.Count; for (int n = 0; n < len; n++) { Vector3 flipVec = ((BrushMirror)(1u << i)).ToVector3(); if (mirrorSettings.Space == MirrorCoordinateSpace.World) { Vector3 cen = editable.gameObjectAttached.GetComponent <Renderer>().bounds.center; s_Rays.Add(new Ray(Vector3.Scale(s_Rays[n].origin - cen, flipVec) + cen, Vector3.Scale(s_Rays[n].direction, flipVec))); } else { Transform t = SceneView.lastActiveSceneView.camera.transform; Vector3 o = t.InverseTransformPoint(s_Rays[n].origin); Vector3 d = t.InverseTransformDirection(s_Rays[n].direction); s_Rays.Add(new Ray(t.TransformPoint(Vector3.Scale(o, flipVec)), t.TransformDirection(Vector3.Scale(d, flipVec)))); } } } } bool hitMesh = false; int[] triangles = editable.editMesh.GetTriangles(); foreach (Ray ray in s_Rays) { PolyRaycastHit hit; if (PolySceneUtility.WorldRaycast(ray, editable.transform, editable.visualMesh.vertices, triangles, out hit)) { target.raycastHits.Add(hit); hitMesh = true; } } PolySceneUtility.CalculateWeightedVertices(target, brushSettings, tool, mode); if (hitMesh && !s_LockBrushToFirst) { Transform[] trs = Selection.GetTransforms(SelectionMode.Unfiltered); var hits = target.raycastHits; foreach (var selectedTransform in trs) { bool isValid = false; if (selectedTransform != editable.transform) { BrushTarget secondaryTarget = GetOrCreateBrushTarget(selectedTransform.gameObject); isValid = Util.IsValid(secondaryTarget); if (isValid) { m_SecondaryBrushTargets.Add(secondaryTarget); secondaryTarget.ClearRaycasts(); foreach (var hit in hits) { PolyRaycastHit secondaryHit = new PolyRaycastHit(hit.distance, secondaryTarget.transform.InverseTransformPoint(editable.transform.TransformPoint(hit.position)), hit.normal, -1); secondaryTarget.raycastHits.Add(secondaryHit); } } PolySceneUtility.CalculateWeightedVertices(secondaryTarget, brushSettings, tool, mode); } } } return(hitMesh); }
/// <summary> /// Update the current brush object and weights with the current mouse position. /// </summary> /// <param name="mousePosition">current mouse position (from Event)</param> /// <param name="isDrag">optional, is dragging the mouse cursor</param> /// <param name="overridenGO">optional, provides an already selected gameobject (used in unit tests only)</param> /// <param name="overridenRay"> optional, provides a ray already created (used in unit tests only)</param> internal void UpdateBrush(Vector2 mousePosition, bool isUserHoldingControl = false, bool isUserHoldingShift = false, bool isDrag = false, GameObject overridenGO = null, Ray?overridenRay = null) { MirrorSettings mirrorSettings = m_BrushMirrorEditor.settings; // Must check HandleUtility.PickGameObject only during MouseMoveEvents or errors will rain. GameObject go = null; brushTarget = null; GameObject cur = null; #if UNITY_2021_1_OR_NEWER int materialIndex; cur = HandleUtility.PickGameObject(mousePosition, false, null, Selection.gameObjects, out materialIndex); if (cur != null) { brushTarget = GetOrCreateBrushTarget(cur); } if (brushTarget != null) { go = cur; } #else int max = 0; // safeguard against unforeseen while loop errors crashing unity do { int tmp; // overloaded PickGameObject ignores array of GameObjects, this is used // when there are non-selected gameObjects between the mouse and selected // gameObjects. cur = overridenGO; if (cur == null) { m_IgnoreDrag.RemoveAll(x => x == null); cur = HandleUtility.PickGameObject(mousePosition, m_IgnoreDrag.ToArray(), out tmp); } if (cur != null) { if (!PolyEditorUtility.InSelection(cur)) { if (!m_IgnoreDrag.Contains(cur)) { m_IgnoreDrag.Add(cur); } } else { brushTarget = GetOrCreateBrushTarget(cur); if (brushTarget != null) { go = cur; } else { m_IgnoreDrag.Add(cur); } } } } while(go == null && cur != null && max++ < 128); #endif bool mouseHoverTargetChanged = false; Ray mouseRay = overridenRay != null ? (Ray)overridenRay : HandleUtility.GUIPointToWorldRay(mousePosition); // if the mouse hover picked up a valid editable, raycast against that. otherwise // raycast all meshes in selection if (go == null) { foreach (var kvp in m_Hovering) { BrushTarget t = kvp.Value; if (Util.IsValid(t) && DoMeshRaycast(mouseRay, t, mirrorSettings)) { brushTarget = t; go = t.gameObject; break; } } } else { if (!DoMeshRaycast(mouseRay, brushTarget, mirrorSettings)) { brushTarget = null; return; } } // if m_Hovering off another gameobject, call OnBrushExit on that last one and mark the // target as having been changed if (go != m_LastHoveredGameObject) { if (m_LastHoveredGameObject) { OnBrushExit(m_LastHoveredGameObject); } if (m_ApplyingBrush) { mode.OnBrushFinishApply(brushTarget, brushSettings); } mouseHoverTargetChanged = true; m_LastHoveredGameObject = go; foreach (var secondaryTarget in m_LastSecondaryBrushTargets) { if (!m_SecondaryBrushTargets.Contains(secondaryTarget)) { OnBrushExit(secondaryTarget.gameObject); if (m_ApplyingBrush) { mode.OnBrushFinishApply(brushTarget, brushSettings); } } } } if (brushTarget == null) { SceneView.RepaintAll(); DoRepaint(); m_LastSecondaryBrushTargets.Clear(); m_SecondaryBrushTargets.Clear(); return; } brushSettings.isUserHoldingControl = isUserHoldingControl; brushSettings.isUserHoldingShift = isUserHoldingShift; if (mouseHoverTargetChanged) { foreach (var secondaryTarget in m_SecondaryBrushTargets) { if (!m_LastSecondaryBrushTargets.Contains(secondaryTarget)) { OnBrushEnter(secondaryTarget, brushSettings); if (m_ApplyingBrush) { mode.OnBrushBeginApply(secondaryTarget, brushSettings); } } } //The active brushtarget is the last one to notify the brush OnBrushEnter(brushTarget, brushSettings); // brush is in use, adding a new object to the undo if (m_ApplyingBrush) { if (!m_UndoQueue.Contains(go)) { int curGroup = Undo.GetCurrentGroup(); brushTarget.editableObject.isDirty = true; OnBrushBeginApply(brushTarget, brushSettings); Undo.CollapseUndoOperations(curGroup); } else { mode.OnBrushBeginApply(brushTarget, brushSettings); } } } m_LastSecondaryBrushTargets.Clear(); m_LastSecondaryBrushTargets.AddRange(m_SecondaryBrushTargets); OnBrushMove(); SceneView.RepaintAll(); DoRepaint(); }