Skip to content

Commit

Permalink
Merge pull request #29 from deadlykam/features-v1-placing-drag
Browse files Browse the repository at this point in the history
Features v1 placing drag
  • Loading branch information
deadlykam authored Sep 11, 2021
2 parents 682d8f0 + e2175f1 commit a786019
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ public BaseLayout(UnityAction repaint)
/// <param name="hideLayout">The hide method of the layout to be hidden, of type Action</param>
public void AddHideLayout(Action hideLayout) => _hideLayouts += hideLayout;

/// <summary>
/// This method makes the give layout hide when this layout is shown and vice versa.
/// </summary>
/// <param name="layout">The layout to hide when this layout is shown and vice versa, of type BaseLayout</param>
public void AddHideLayout(BaseLayout layout)
{
_hideLayouts += layout.Hide;
layout.AddHideLayout(Hide);
}

/// <summary>
/// This method gets the actual position.
/// </summary>
Expand Down Expand Up @@ -81,6 +91,7 @@ public BaseLayout(UnityAction repaint)
protected abstract void SetupOnEnable();

#region Creation
protected bool Toggle(string name, string tooltip, bool obj) => EditorGUILayout.Toggle(new GUIContent(name, tooltip), obj);
protected bool ToggleLeft(string name, string toolTip, AnimBool toggle) => EditorGUILayout.ToggleLeft(new GUIContent(name, toolTip), toggle.target);
protected Transform TransformField(string name, string toolTip, Transform obj, bool isHierarchy) => EditorGUILayout.ObjectField(new GUIContent(name, toolTip), obj, typeof(Transform), isHierarchy) as Transform;
protected int LayerField(string name, string toolTip, LayerMask layerMask) => EditorGUILayout.LayerField(new GUIContent(name, toolTip), layerMask);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using UnityEditor.AnimatedValues;
using UnityEngine;
using UnityEngine.Events;

namespace KamranWali.SimpleInterface.Editor.Layouts
{
public class OffsetPositionLayout : BaseLayout
{
private AnimBool _mainGroup;
private AnimBool _posGroupX;
private AnimBool _posGroupY;
private AnimBool _posGroupZ;
private float _posX;
private float _posY;
private float _posZ;
private Vector3 _prePos;
private bool _isStart; // Flag to check if the layout has been just enabled

public OffsetPositionLayout(UnityAction repaint) : base(repaint)
{
}

public override void Hide() { if (IsShown()) _mainGroup.target = false; }
public override bool IsShown() => _mainGroup.target;

public override void SetupOnGUI()
{
_mainGroup.target = ToggleLeft("Offset Position (V)", "Toggle to place prefab in given offset position. Hotkey = 'V'", _mainGroup);

if (BeginFadeGroup(_mainGroup.faded))
{
BeginHorizontalLayout(ref _posGroupX, ref _posX, "X", "Toggle to offset X axis.", 20f, 1f);
BeginHorizontalLayout(ref _posGroupY, ref _posY, "Y", "Toggle to offset Y axis.", 20f, 1f);
BeginHorizontalLayout(ref _posGroupZ, ref _posZ, "Z", "Toggle to offset Z axis.", 20f, 1f);
}
EndFadeGroup();
HideOtherLayouts(); // Hidding other layouts
}

public override void Update(Event currentEvent)
{
if (!IsShown() && !_isStart) _isStart = true; // Condition to reset flag

if (currentEvent.keyCode == KeyCode.V && currentEvent.type == EventType.KeyDown)
{
_mainGroup.target = !_mainGroup.target;
HideOtherLayouts(); // Hidding other layouts
}
}

public override Vector3 GetPosition(Vector3 position)
{
if (!_isStart) // Condition to check offset
{
if((_posGroupX.target ? Mathf.Abs(position.x - _prePos.x) >= _posX : true) &&
(_posGroupY.target ? Mathf.Abs(position.y - _prePos.y) >= _posY : true) &&
(_posGroupZ.target ? Mathf.Abs(position.z - _prePos.z) >= _posZ : true)) // Validating the current position
_prePos = position; // Sending the offset position
}
else // Condition for sending the start up position
{
_isStart = false;
_prePos = position; // Sending start up position
}
return _prePos;
}

protected override void SetupOnEnable()
{
_mainGroup = new AnimBool(false);
_mainGroup.valueChanged.AddListener(repaint);
_posGroupX = new AnimBool(false);
_posGroupX.valueChanged.AddListener(repaint);
_posGroupY = new AnimBool(false);
_posGroupY.valueChanged.AddListener(repaint);
_posGroupZ = new AnimBool(false);
_posGroupZ.valueChanged.AddListener(repaint);
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class PlacementLayout : BaseLayout
private UnityEditor.Editor _preview;
private GUIStyle _previewColour;
private GameObject _previewPrefab; // For storing the selected prefab
private bool _isDrag;

// Internal Fields
private RaycastHit _hit; // Storing ray hit
Expand All @@ -31,6 +32,7 @@ public class PlacementLayout : BaseLayout
private Func<Vector3, Vector3> _getActualPosition;
private Func<Quaternion, Quaternion> _getActualRotation;
private Func<Vector3, Vector3> _getActualScale;
private Func<bool> _isOffsetMode;
private int _curPlace;
private string[] _paths;
private string[] _objectNames;
Expand All @@ -39,8 +41,15 @@ public class PlacementLayout : BaseLayout
private List<string> _prefabsNames;
private int _prefabCounter;
private PrefabPathSearch _prefabSearch;
private Tool _currentTool;
private Vector3 _pos; // The position to place the prefab
private Vector3 _offsetPos; // Needed to verify offset position

// Default Fields
private readonly int _defaultMinPlace; // The minimum default value for placement limit
private readonly string _defaultPath; // The default path if no path given
private readonly string[] _defaultDropdown; // The default drop down value
private readonly string _defaultPrefabDeletedName; // The name of the prefab when deleted

/// <summary>
/// This constructor creates the PlacementLayout object.
Expand All @@ -49,16 +58,21 @@ public class PlacementLayout : BaseLayout
/// <param name="getActualPosition">The delegate that returns the actual position, of type Func<Vector3, Vector3></param>
/// <param name="getActualRotation">The delegate that returns the actual rotation, of type Func<Quaternion, Quaternion></param>
/// <param name="getActualScale">The delegate that returns the actual scale, of type Func<Vector3, Vector3></param>
public PlacementLayout(UnityAction repaint, Func<Vector3, Vector3> getActualPosition, Func<Quaternion, Quaternion> getActualRotation, Func<Vector3, Vector3> getActualScale) : base(repaint)
/// <param name="isOffsetMode">The delegate to check if offset mode is enabled/disabled, of type Func<bool></param>
public PlacementLayout(UnityAction repaint, Func<Vector3, Vector3> getActualPosition, Func<Quaternion, Quaternion> getActualRotation, Func<Vector3, Vector3> getActualScale, Func<bool> isOffsetMode) : base(repaint)
{
_getActualPosition = getActualPosition;
_getActualRotation = getActualRotation;
_getActualScale = getActualScale;
_isOffsetMode = isOffsetMode;
_prefabSearch = new PrefabPathSearch();
_prefabs = new List<Transform>();
_prefabsNames = new List<string>();
_currentTool = Tool.Transform; // Setting the starting tool
_defaultMinPlace = 1; // Setting the default min placement limit value
_defaultPath = "Assets";
_defaultDropdown = new string[] { "None" };
_defaultPrefabDeletedName = "Deleted!";
}

public override bool IsShown() => _placeGroup.target;
Expand Down Expand Up @@ -88,9 +102,9 @@ public override void SetupOnGUI()
BeginHorizontal();
Space(20f);
LabelWidth(90f);
_selPath = Popup(_selPath, "Prefab Paths", "Select a prefab path to load prefabs from.", IsPathsFound() ? _prefabSearch.GetPathNames() : new string[] { "None" });
_selPath = Popup(_selPath, "Prefab Paths", "Select a prefab path to load prefabs from.", IsPathsFound() ? _prefabSearch.GetPathNames() : _defaultDropdown);

if (IsPathsFound() && _curPath != _selPath) // Condition for loading the prefabs
if (IsPathsFound() && _curPath != _selPath) // Condition for loading the selected prefab list
{
LoadPrefabs(_paths[_selPath]);
_curPath = _selPath; // Updating the current path index
Expand All @@ -106,14 +120,17 @@ public override void SetupOnGUI()
#region Prefab Preview
if (IsPathsFound()) // Condition for showing preview
{
if (_previewPrefab != GetSelectedPrefab().gameObject) // Checking if selection have changed.
if (IsSelectedPrefabExist()) // Making sure the prefab was not Deleted
{
_previewPrefab = GetSelectedPrefab().gameObject; // Updating preview prefab

if (_previewPrefab != null) // Checking if the preview prefab is NOT null
if (_previewPrefab != GetSelectedPrefab().gameObject) // Checking if selection have changed.
{
if (_preview != null) UnityEditor.Editor.DestroyImmediate(_preview); // Destroying previous editor to avoid allocate cull masking issue
if (_preview == null) _preview = UnityEditor.Editor.CreateEditor(_previewPrefab); // Creating a new editor with the updated prefab view
_previewPrefab = GetSelectedPrefab().gameObject; // Updating preview prefab

if (_previewPrefab != null) // Checking if the preview prefab is NOT null
{
if (_preview != null) UnityEditor.Editor.DestroyImmediate(_preview); // Destroying previous editor to avoid allocate cull masking issue
if (_preview == null) _preview = UnityEditor.Editor.CreateEditor(_previewPrefab); // Creating a new editor with the updated prefab view
}
}
}

Expand Down Expand Up @@ -172,29 +189,64 @@ public override void SetupOnGUI()
}
EndFadeGroup();
EndHorizontal();

BeginHorizontal();
Space(20f);
LabelWidth(50f);
_isDrag = Toggle("Drag(M)", "For enabling/disabling drag placement", _isDrag);
if (_isDrag && Tools.current != Tool.View) // Condition for drag mode being enabled
{
_currentTool = Tools.current; // Saving the current tool
Tools.current = Tool.View; // Drag mode enabled
}
else if (!_isDrag && Tools.current != _currentTool && _currentTool != Tool.None) // Condition to set back the current tool
{
Tools.current = _currentTool; // Setting the current tool back
_currentTool = Tool.None; // Removing saved tool
}
EndHorizontal();
}
EndFadeGroup();
HideOtherLayouts(); // Hidding other layouts
}

public override void Update(Event currentEvent)
{
if (IsToggleGroupShown(_placeGroup.faded) && currentEvent.type == EventType.MouseDown && currentEvent.button == 0 && IsPlaceable())
if (IsToggleGroupShown(_placeGroup.faded) && (currentEvent.type == EventType.MouseDown || (currentEvent.type == EventType.MouseDrag && _isDrag)) && currentEvent.button == 0 && IsPlaceable())
{
if (Physics.Raycast(HandleUtility.GUIPointToWorldRay(currentEvent.mousePosition), out _hit, Mathf.Infinity, 1 << _layerMask)) // Hitting the correct layer
{
_prefabTemp = _root == null ? PrefabUtility.InstantiatePrefab(GetSelectedPrefab()) as Transform : PrefabUtility.InstantiatePrefab(GetSelectedPrefab(), _root) as Transform; // Creating the prefab
_prefabTemp.position = _getActualPosition(_hit.point); // Placing in hit position
_prefabTemp.rotation = _getActualRotation(_prefabTemp.rotation); // Rotating to the actual rotation
_prefabTemp.localScale = _getActualScale(_prefabTemp.localScale); // Setting the actual scale
if (IsSelectedPrefabExist()) // Validating that the selected prefab exists
{
_pos = _getActualPosition(_hit.point); // Getting the actual position

if (!_isOffsetMode() || (_pos != _offsetPos)) // Condition to check if Normal Mode or Offset Mode is enabled
{
_prefabTemp = _root == null ? PrefabUtility.InstantiatePrefab(GetSelectedPrefab()) as Transform : PrefabUtility.InstantiatePrefab(GetSelectedPrefab(), _root) as Transform; // Creating the prefab
_prefabTemp.position = _pos; // Placing in hit position
_prefabTemp.rotation = _getActualRotation(_prefabTemp.rotation); // Rotating to the actual rotation
_prefabTemp.localScale = _getActualScale(_prefabTemp.localScale); // Setting the actual scale

if (_placeLimitGroup.target) // Condition to check if limit placement mode activated
{
_curPlace = (_curPlace + 1) > _maxPlace ? _maxPlace : _curPlace + 1;
repaint(); // Repainting to update the UI
}

if (_isOffsetMode()) _offsetPos = _pos; // Updating offset position
if (_prefabTemp.gameObject != null) Undo.RegisterCreatedObjectUndo(_prefabTemp.gameObject, "Prefab Placement"); // Check if prefab has NOT been destroyed for Undo
}

if (_placeLimitGroup.target) // Condition to check if limit placement mode activated
if (_isDrag) currentEvent.Use(); // Drag mode enabled
}
else // Prefab has been deleted so changing the name to deleted name
{
_curPlace = (_curPlace + 1) > _maxPlace ? _maxPlace : _curPlace + 1;
repaint(); // Repainting to update the UI
if (_prefabsNames[_selPrefabGrid] != _defaultPrefabDeletedName) // Checking if name NOT changed
{
RenamePrefab(_defaultPrefabDeletedName, _selPrefabGrid); // Renaming the deleted prefab's selection name
repaint();
}
}

Undo.RegisterCreatedObjectUndo(_prefabTemp.gameObject, "Prefab Placement");
}
}

Expand All @@ -203,12 +255,18 @@ public override void Update(Event currentEvent)
_placeGroup.target = !_placeGroup.target; // Toggling placement
HideOtherLayouts(); // Hidding other layouts
}
else if (currentEvent.keyCode == KeyCode.B && currentEvent.type == EventType.KeyDown) _placeLimitGroup.target = !_placeLimitGroup.target;
else if (currentEvent.keyCode == KeyCode.N && currentEvent.type == EventType.KeyDown && _placeLimitGroup.target)
else if (currentEvent.keyCode == KeyCode.B && currentEvent.type == EventType.KeyDown) _placeLimitGroup.target = !_placeLimitGroup.target; // Toggling limit placement mode
else if (currentEvent.keyCode == KeyCode.N && currentEvent.type == EventType.KeyDown && _placeLimitGroup.target) // Resetting limit placement
{
ResetPlacementCounter();
repaint();
}

else if (currentEvent.keyCode == KeyCode.M && currentEvent.type == EventType.KeyDown) // Toggling drag mode
{
_isDrag = !_isDrag;
repaint();
}
}

public override void Hide() { if (IsShown()) _placeGroup.target = false; }
Expand Down Expand Up @@ -284,5 +342,18 @@ private void ClearPrefabs()
/// </summary>
/// <returns>The selected prefab, of type Transform</returns>
private Transform GetSelectedPrefab() => _prefabs[_selPrefabGrid];

/// <summary>
/// This method checks that the selected prefab exists and has NOT been deleted or removed.
/// </summary>
/// <returns>True means exists, false otherwise, of type bool</returns>
private bool IsSelectedPrefabExist() => GetSelectedPrefab() != null;

/// <summary>
/// This method renames the prefab name in the selection.
/// </summary>
/// <param name="name">The new name for the prefab, of type string</param>
/// <param name="index">The index of the prefab to be renamed, of type int</param>
private void RenamePrefab(string name, int index) => _prefabsNames[index] = name;
}
}
Loading

0 comments on commit a786019

Please sign in to comment.