using System.Collections.Generic;
using UnityEditor;
namespace UnityEngine.ProBuilder.Shapes
{
///
/// Represents a basic [door](../manual/Door.html) shape.
///
[Shape("Door")]
public class Door : Shape
{
///
/// Sets the height of the top of the door frame in meters.
/// The default value is 0.5. The minimum value is 0.01.
///
[Min(0.01f)]
[SerializeField]
float m_DoorHeight = .5f;
///
/// Sets the width of the door frame on the sides in meters.
/// The default value is 0.75. The minimum value is 0.01.
///
[Min(0.01f)]
[SerializeField]
float m_LegWidth = .75f;
///
public override void CopyShape(Shape shape)
{
if(shape is Door)
{
m_DoorHeight = ( (Door) shape ).m_DoorHeight;
m_LegWidth = ( (Door) shape ).m_LegWidth;
}
}
///
public override Bounds RebuildMesh(ProBuilderMesh mesh, Vector3 size, Quaternion rotation)
{
var upDir = Vector3.Scale(rotation * Vector3.up, size) ;
var rightDir = Vector3.Scale(rotation * Vector3.right, size) ;
var forwardDir = Vector3.Scale(rotation * Vector3.forward, size) ;
float totalWidth = rightDir.magnitude;
float totalHeight = upDir.magnitude;
float depth = forwardDir.magnitude;
float xLegCoord = totalWidth / 2f;
var legWidth = xLegCoord - m_LegWidth > 0 ? xLegCoord - m_LegWidth : 0.001f;
var ledgeHeight = (totalHeight - m_DoorHeight * 2f) > 0 ? totalHeight - m_DoorHeight * 2f : 0.001f;
var baseY = -totalHeight;
var front = depth / 2f;
// 8---9---10--11
// | |
// 4 5---6 7
// | | | |
// 0 1 2 3
Vector3[] template = new Vector3[12]
{
new Vector3(-xLegCoord, baseY, front), // 0
new Vector3(-legWidth, baseY, front), // 1
new Vector3(legWidth, baseY, front), // 2
new Vector3(xLegCoord, baseY, front), // 3
new Vector3(-xLegCoord, ledgeHeight, front), // 4
new Vector3(-legWidth, ledgeHeight, front), // 5
new Vector3(legWidth, ledgeHeight, front), // 6
new Vector3(xLegCoord, ledgeHeight, front), // 7
new Vector3(-xLegCoord, totalHeight, front), // 8
new Vector3(-legWidth, totalHeight, front), // 9
new Vector3(legWidth, totalHeight, front), // 10
new Vector3(xLegCoord, totalHeight, front) // 11
};
List points = new List();
points.Add(template[4]);
points.Add(template[0]);
points.Add(template[5]);
points.Add(template[1]);
points.Add(template[2]);
points.Add(template[3]);
points.Add(template[6]);
points.Add(template[7]);
points.Add(template[4]);
points.Add(template[5]);
points.Add(template[8]);
points.Add(template[9]);
points.Add(template[10]);
points.Add(template[6]);
points.Add(template[11]);
points.Add(template[7]);
points.Add(template[5]);
points.Add(template[6]);
points.Add(template[9]);
points.Add(template[10]);
List reverse = new List();
for (int i = 0; i < points.Count; i += 4)
{
reverse.Add(points[i + 0] - Vector3.forward * depth);
reverse.Add(points[i + 2] - Vector3.forward * depth);
reverse.Add(points[i + 1] - Vector3.forward * depth);
reverse.Add(points[i + 3] - Vector3.forward * depth);
}
points.AddRange(reverse);
points.Add(template[6]);
points.Add(template[5]);
points.Add(template[6] - Vector3.forward * depth);
points.Add(template[5] - Vector3.forward * depth);
points.Add(template[2] - Vector3.forward * depth);
points.Add(template[2]);
points.Add(template[6] - Vector3.forward * depth);
points.Add(template[6]);
points.Add(template[1]);
points.Add(template[1] - Vector3.forward * depth);
points.Add(template[5]);
points.Add(template[5] - Vector3.forward * depth);
var sizeSigns = Math.Sign(size);
for(int i = 0; i < points.Count; i++)
points[i] = Vector3.Scale(rotation * points[i], sizeSigns);
mesh.GeometryWithPoints(points.ToArray());
var sizeSign = sizeSigns.x * sizeSigns.y * sizeSigns.z;
if(sizeSign < 0)
{
var faces = mesh.facesInternal;
foreach(var face in faces)
face.Reverse();
}
return mesh.mesh.bounds;
}
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(Door))]
public class DoorDrawer : PropertyDrawer
{
static bool s_foldoutEnabled = true;
const bool k_ToggleOnLabelClick = true;
static readonly GUIContent k_HeightContent = new GUIContent("Pediment Height", L10n.Tr("Set the height of the door's top."));
static readonly GUIContent k_SideContent = new GUIContent("Side Width", L10n.Tr("Set the width of the door's sides."));
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
s_foldoutEnabled = EditorGUI.Foldout(position, s_foldoutEnabled, "Door Settings", k_ToggleOnLabelClick);
EditorGUI.indentLevel++;
if(s_foldoutEnabled)
{
EditorGUILayout.PropertyField(property.FindPropertyRelative("m_DoorHeight"), k_HeightContent);
EditorGUILayout.PropertyField(property.FindPropertyRelative("m_LegWidth"), k_SideContent);
}
EditorGUI.indentLevel--;
EditorGUI.EndProperty();
}
}
#endif
}