1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
5 #include "DesignerEditor.h"
6 #include "Tools/Select/SelectTool.h"
8 #include "Util/HeightManipulator.h"
9 #include "Util/ExtrusionSnappingHelper.h"
10 #include "ToolFactory.h"
11 #include "Core/Helper.h"
12 #include "DesignerSession.h"
16 void BoxTool::Serialize(Serialization::IArchive
& ar
)
18 __super::Serialize(ar
);
19 m_BoxParameter
.Serialize(ar
);
22 void BoxTool::OnLButtonDownAboutPlaceStartingPointPhase(CViewport
* view
, UINT nFlags
, CPoint point
)
24 __super::OnLButtonDownAboutPlaceStartingPointPhase(view
, nFlags
, point
);
26 StoreSeparateStatus();
27 m_BoxParameter
.m_Height
= 0;
28 s_SnappingHelper
.Init(GetModel());
31 bool BoxTool::OnLButtonDown(CViewport
* view
, UINT nFlags
, CPoint point
)
33 __super::OnLButtonDown(view
, nFlags
, point
);
35 if (m_Phase
== eBoxPhase_RaiseHeight
)
36 m_Phase
= eBoxPhase_Done
;
41 bool BoxTool::OnLButtonUp(CViewport
* view
, UINT nFlags
, CPoint point
)
43 if (m_Phase
== eBoxPhase_DrawRectangle
)
45 if (std::abs(GetCurrentSpotPos().x
- GetStartSpotPos().x
) > (BrushFloat
)0.01 ||
46 std::abs(GetCurrentSpotPos().y
- GetStartSpotPos().y
) > (BrushFloat
)0.01 ||
47 std::abs(GetCurrentSpotPos().z
- GetStartSpotPos().z
) > (BrushFloat
)0.01)
49 m_Phase
= eBoxPhase_RaiseHeight
;
50 s_SnappingHelper
.SearchForOppositePolygons(m_pCapPolygon
);
52 m_bIsOverOpposite
= false;
53 s_HeightManipulator
.Init(GetPlane(), GetCurrentSpotPos());
60 bool BoxTool::OnMouseMove(CViewport
* view
, UINT nFlags
, CPoint point
)
62 __super::OnMouseMove(view
, nFlags
, point
);
64 if (m_Phase
== eBoxPhase_RaiseHeight
)
66 m_BoxParameter
.m_Height
= (float)s_HeightManipulator
.Update(GetWorldTM(), view
, GetDesigner()->GetRay());
68 if (m_BoxParameter
.m_Height
< (float)kInitialPrimitiveHeight
)
69 m_BoxParameter
.m_Height
= 0;
71 if (m_BoxParameter
.m_bAlignment
)
73 PolygonPtr pAlignedPolygon
= s_SnappingHelper
.FindAlignedPolygon(m_pCapPolygon
, GetWorldTM(), view
, point
);
75 m_BoxParameter
.m_Height
= (float)(GetPlane().Distance() - pAlignedPolygon
->GetPlane().Distance());
78 UpdateShapeWithBoundaryCheck();
84 void BoxTool::UpdateShapeWithBoundaryCheck(bool bUpdateUIs
)
86 UpdateShape(bUpdateUIs
);
87 m_bIsOverOpposite
= m_pCapPolygon
&& s_SnappingHelper
.IsOverOppositePolygon(m_pCapPolygon
, ePP_Pull
);
88 if (m_bIsOverOpposite
)
90 m_BoxParameter
.m_Height
= (float)s_SnappingHelper
.GetNearestDistanceToOpposite(ePP_Pull
);
91 UpdateShape(bUpdateUIs
);
95 void BoxTool::UpdateShape(bool bUpdateUIs
)
97 std::vector
<PolygonPtr
> polygonList
;
99 m_v
[0] = GetStartSpotPos();
100 m_v
[1] = GetCurrentSpotPos();
102 BrushVec2 p0
= GetPlane().W2P(m_v
[0]);
103 BrushVec2 p1
= GetPlane().W2P(m_v
[1]);
105 std::vector
<BrushVec3
> vList(4);
107 vList
[1] = GetPlane().P2W(BrushVec2(p1
.x
, p0
.y
));
109 vList
[3] = GetPlane().P2W(BrushVec2(p0
.x
, p1
.y
));
111 polygonList
.push_back(new Polygon(vList
));
112 if (polygonList
[0]->IsOpen())
114 if (polygonList
[0]->GetPlane().IsSameFacing(GetPlane()))
115 polygonList
[0]->Flip();
117 for (int i
= 0; i
< 4; ++i
)
118 vList
[i
] += GetPlane().Normal() * (BrushFloat
)m_BoxParameter
.m_Height
;
119 polygonList
.push_back(new Polygon(vList
));
120 if (!polygonList
[1]->GetPlane().IsSameFacing(GetPlane()))
121 polygonList
[1]->Flip();
123 for (int i
= 0; i
< 4; ++i
)
125 BrushEdge3D e
= polygonList
[0]->GetEdge(i
);
129 vList
[2] = e
.m_v
[0] + GetPlane().Normal() * (BrushFloat
)m_BoxParameter
.m_Height
;
130 vList
[3] = e
.m_v
[1] + GetPlane().Normal() * (BrushFloat
)m_BoxParameter
.m_Height
;
132 polygonList
.push_back(new Polygon(vList
));
135 MODEL_SHELF_RECONSTRUCTOR(GetModel());
137 GetModel()->SetShelf(eShelf_Construction
);
140 for (int i
= 0, iCount(polygonList
.size()); i
< iCount
; ++i
)
142 if (polygonList
[i
]->IsOpen())
145 if (GetStartSpot().m_pPolygon
)
147 polygonList
[i
]->SetTexInfo(GetStartSpot().m_pPolygon
->GetTexInfo());
148 polygonList
[i
]->SetSubMatID(GetStartSpot().m_pPolygon
->GetSubMatID());
151 AddPolygonWithSubMatID(polygonList
[i
]);
153 if (Comparison::IsEquivalent(polygonList
[i
]->GetPlane().Normal(), GetPlane().Normal()))
154 m_pCapPolygon
= polygonList
[i
];
159 m_RectangleParameter
.m_Width
= std::abs(p0
.x
- p1
.x
);
160 m_RectangleParameter
.m_Depth
= std::abs(p0
.y
- p1
.y
);
161 DesignerSession::GetInstance()->signalDesignerEvent(eDesignerNotify_SubtoolOptionChanged
, nullptr);
164 ApplyPostProcess(ePostProcess_Mesh
| ePostProcess_Mirror
| ePostProcess_SmoothingGroup
);
167 void BoxTool::Display(SDisplayContext
& dc
)
169 DisplayCurrentSpot(dc
);
170 DisplayDimensionHelper(dc
, eShelf_Construction
);
171 if (GetStartSpot().m_pPolygon
)
172 DisplayDimensionHelper(dc
);
173 s_HeightManipulator
.Display(dc
);
176 void BoxTool::Register()
178 RegisterShape(GetStartSpot().m_pPolygon
);
181 void BoxTool::RegisterShape(PolygonPtr pFloorPolygon
)
183 if (!GetModel() || GetModel()->IsEmpty(eShelf_Construction
))
186 MODEL_SHELF_RECONSTRUCTOR(GetModel());
190 GetModel()->SetShelf(eShelf_Construction
);
191 if (m_bIsOverOpposite
)
193 s_SnappingHelper
.ApplyOppositePolygons(m_pCapPolygon
, ePP_Pull
, true);
194 GetModel()->RemovePolygon(GetModel()->QueryEquivalentPolygon(m_pCapPolygon
));
197 if (!IsSeparateStatus())
199 std::vector
<PolygonPtr
> sidePolygons
;
201 BrushPlane invertedCapPolygonPlane
= m_pCapPolygon
->GetPlane().GetInverted();
202 for (int i
= 0, iPolygonCount(GetModel()->GetPolygonCount()); i
< iPolygonCount
; ++i
)
204 PolygonPtr pPolygon
= GetModel()->GetPolygon(i
);
205 if (pPolygon
!= m_pCapPolygon
&& !Comparison::IsEquivalent(invertedCapPolygonPlane
.Normal(), pPolygon
->GetPlane().Normal()))
206 sidePolygons
.push_back(pPolygon
);
209 std::vector
<PolygonPtr
> intersectedSidePolygons
;
210 for (int i
= 0, iSidePolygonCount(sidePolygons
.size()); i
< iSidePolygonCount
; ++i
)
212 for (int k
= 0; k
< 2; ++k
)
214 PolygonPtr pSidePolygon
= k
== 0 ? sidePolygons
[i
]->Clone()->Flip() : sidePolygons
[i
];
216 GetModel()->SetShelf(eShelf_Base
);
217 bool bHasIntersected
= GetModel()->HasIntersection(pSidePolygon
, true);
218 bool bTouched
= GetModel()->HasTouched(pSidePolygon
);
219 if ((!bHasIntersected
&& !bTouched
) || (bTouched
&& k
== 0))
222 GetModel()->SetShelf(eShelf_Construction
);
223 GetModel()->RemovePolygon(sidePolygons
[i
]);
225 GetModel()->SetShelf(eShelf_Base
);
228 GetModel()->AddXORPolygon(pSidePolygon
);
229 intersectedSidePolygons
.push_back(pSidePolygon
);
233 GetModel()->AddUnionPolygon(pSidePolygon
);
239 for (int i
= 0, iCount(intersectedSidePolygons
.size()); i
< iCount
; ++i
)
241 GetModel()->SetShelf(eShelf_Base
);
246 __super::RegisterShape(pFloorPolygon
);
251 REGISTER_DESIGNER_TOOL_WITH_PROPERTYTREE_PANEL_AND_COMMAND(eDesigner_Box
, eToolGroup_Shape
, "Box", BoxTool
,
252 box
, "runs box tool", "designer.box");