You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
730 lines
18 KiB
730 lines
18 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Implements the entity/prefab placement tool. |
|
// |
|
//=============================================================================// |
|
|
|
#include "stdafx.h" |
|
#include "History.h" |
|
#include "MainFrm.h" |
|
#include "MapDefs.h" |
|
#include "MapSolid.h" |
|
#include "MapDoc.h" |
|
#include "MapView2D.h" |
|
#include "MapView3D.h" |
|
#include "Material.h" |
|
#include "materialsystem/imesh.h" |
|
#include "Render2D.h" |
|
#include "Render3D.h" |
|
#include "StatusBarIDs.h" |
|
#include "TextureSystem.h" |
|
#include "ToolEntity.h" |
|
#include "ToolManager.h" |
|
#include "hammer.h" |
|
#include "vgui/Cursor.h" |
|
#include "Selection.h" |
|
#include "vstdlib/random.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
|
|
|
|
//#pragma warning(disable:4244) |
|
|
|
|
|
static HCURSOR s_hcurEntity = NULL; |
|
|
|
|
|
class CToolEntityMessageWnd : public CWnd |
|
{ |
|
public: |
|
|
|
bool Create(void); |
|
void PreMenu2D(CToolEntity *pTool, CMapView2D *pView); |
|
|
|
protected: |
|
|
|
//{{AFX_MSG_MAP(CToolEntityMessageWnd) |
|
afx_msg void OnCreateObject(); |
|
//}}AFX_MSG |
|
|
|
DECLARE_MESSAGE_MAP() |
|
|
|
private: |
|
|
|
CToolEntity *m_pToolEntity; |
|
CMapView2D *m_pView2D; |
|
}; |
|
|
|
|
|
static CToolEntityMessageWnd s_wndToolMessage; |
|
static const char *g_pszClassName = "ValveEditor_EntityToolWnd"; |
|
|
|
|
|
BEGIN_MESSAGE_MAP(CToolEntityMessageWnd, CWnd) |
|
//{{AFX_MSG_MAP(CToolMessageWnd) |
|
ON_COMMAND(ID_CREATEOBJECT, OnCreateObject) |
|
//}}AFX_MSG_MAP |
|
END_MESSAGE_MAP() |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Creates the hidden window that receives context menu commands for the |
|
// entity tool. |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntityMessageWnd::Create(void) |
|
{ |
|
WNDCLASS wndcls; |
|
memset(&wndcls, 0, sizeof(WNDCLASS)); |
|
wndcls.lpfnWndProc = AfxWndProc; |
|
wndcls.hInstance = AfxGetInstanceHandle(); |
|
wndcls.lpszClassName = g_pszClassName; |
|
|
|
if (!AfxRegisterClass(&wndcls)) |
|
{ |
|
return(false); |
|
} |
|
|
|
return(CWnd::CreateEx(0, g_pszClassName, g_pszClassName, 0, CRect(0, 0, 10, 10), NULL, 0) == TRUE); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Attaches the entity tool to this window before activating the context |
|
// menu. |
|
//----------------------------------------------------------------------------- |
|
void CToolEntityMessageWnd::PreMenu2D(CToolEntity *pToolEntity, CMapView2D *pView) |
|
{ |
|
Assert(pToolEntity != NULL); |
|
m_pToolEntity = pToolEntity; |
|
m_pView2D = pView; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CToolEntityMessageWnd::OnCreateObject() |
|
{ |
|
m_pToolEntity->CreateMapObject(m_pView2D); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CToolEntity::CToolEntity(void) |
|
{ |
|
SetEmpty(); |
|
|
|
m_vecPos.Init(); |
|
|
|
if (s_hcurEntity == NULL) |
|
{ |
|
s_hcurEntity = LoadCursor(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDC_ENTITY)); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
CToolEntity::~CToolEntity(void) |
|
{ |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : pt - |
|
// BOOL - |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
int CToolEntity::HitTest(CMapView *pView, const Vector2D &ptClient, bool bTestHandles) |
|
{ |
|
return HitRect( pView, ptClient, m_vecPos, 8 )?TRUE:FALSE; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : bSave - |
|
//----------------------------------------------------------------------------- |
|
void CToolEntity::FinishTranslation(bool bSave) |
|
{ |
|
if (bSave) |
|
{ |
|
TranslatePoint( m_vecPos ); |
|
m_bEmpty = false; |
|
} |
|
|
|
Tool3D::FinishTranslation(bSave); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : pt - |
|
// uFlags - |
|
// size - |
|
// Output : Returns true if the translation delta was nonzero. |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntity::UpdateTranslation( const Vector &vUpdate, UINT uFlags) |
|
{ |
|
Vector vOldDelta = m_vTranslation; |
|
|
|
if ( !Tool3D::UpdateTranslation( vUpdate, uFlags ) ) |
|
return false; |
|
|
|
// apply snap to grid constrain |
|
if ( uFlags ) |
|
{ |
|
ProjectOnTranslationPlane( m_vecPos + m_vTranslation, m_vTranslation, uFlags ); |
|
m_vTranslation -= m_vecPos; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : pRender - |
|
//----------------------------------------------------------------------------- |
|
void CToolEntity::RenderTool2D(CRender2D *pRender) |
|
{ |
|
Vector v = m_vecPos; |
|
|
|
if ( IsTranslating() ) |
|
{ |
|
TranslatePoint( v ); |
|
} |
|
else if ( IsEmpty() ) |
|
{ |
|
return; |
|
} |
|
|
|
pRender->SetDrawColor( 35, 255, 75 ); |
|
|
|
// |
|
// Draw center rect. |
|
// |
|
pRender->DrawRectangle( v, v, false, 6.0f ); |
|
|
|
// |
|
// Draw crosshair |
|
// |
|
pRender->DrawLine( Vector( g_MIN_MAP_COORD, v.y, v.z), Vector( g_MAX_MAP_COORD, v.y , v.z) ); |
|
pRender->DrawLine( Vector( v.x, g_MIN_MAP_COORD, v.z), Vector( v.x, g_MAX_MAP_COORD, v.z) ); |
|
pRender->DrawLine( Vector( v.x, v.y, g_MIN_MAP_COORD), Vector( v.x, v.y, g_MAX_MAP_COORD) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : pView - |
|
// point - |
|
// Output : |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntity::OnContextMenu2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint) |
|
{ |
|
if (!IsEmpty()) |
|
{ |
|
CMapDoc *pDoc = pView->GetMapDoc(); |
|
if (pDoc == NULL) |
|
{ |
|
return true; |
|
} |
|
|
|
if (!pView->PointInClientRect(vPoint)) |
|
{ |
|
return true; |
|
} |
|
|
|
if ( HitTest( pView, vPoint, false) ) |
|
{ |
|
static CMenu menu, menuCreate; |
|
static bool bInit = false; |
|
|
|
if (!bInit) |
|
{ |
|
bInit = true; |
|
menu.LoadMenu(IDR_POPUPS); |
|
menuCreate.Attach(::GetSubMenu(menu.m_hMenu, 1)); |
|
|
|
// Create the window that handles menu messages. |
|
s_wndToolMessage.Create(); |
|
} |
|
|
|
CPoint ptScreen( vPoint.x,vPoint.y); |
|
pView->ClientToScreen(&ptScreen); |
|
|
|
s_wndToolMessage.PreMenu2D(this, pView); |
|
menuCreate.TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_LEFTALIGN, ptScreen.x, ptScreen.y, &s_wndToolMessage); |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pView - |
|
// nChar - |
|
// nRepCnt - |
|
// nFlags - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntity::OnKeyDown2D(CMapView2D *pView, UINT nChar, UINT nRepCnt, UINT nFlags) |
|
{ |
|
switch (nChar) |
|
{ |
|
case VK_RETURN: |
|
{ |
|
if (!IsEmpty()) |
|
{ |
|
CreateMapObject(pView); |
|
} |
|
return true; |
|
} |
|
|
|
case VK_ESCAPE: |
|
{ |
|
OnEscape(); |
|
return true; |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : pView - |
|
// nFlags - |
|
// point - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntity::OnLMouseDown2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint) |
|
{ |
|
unsigned int uConstraints = GetConstraints( nFlags ); |
|
|
|
Tool3D::OnLMouseDown2D(pView, nFlags, vPoint); |
|
|
|
if ( HitTest( pView, vPoint, false) ) |
|
{ |
|
// translate existing object |
|
StartTranslation( pView, vPoint ); |
|
} |
|
else |
|
{ |
|
Vector vecWorld; |
|
pView->ClientToWorld(vecWorld, vPoint ); |
|
|
|
// |
|
// Snap starting position to grid. |
|
// |
|
if ( uConstraints & constrainSnap ) |
|
m_pDocument->Snap(vecWorld, uConstraints); |
|
|
|
// create new one, keep old third axis |
|
m_vecPos[pView->axHorz] = vecWorld[pView->axHorz]; |
|
m_vecPos[pView->axVert] = vecWorld[pView->axVert]; |
|
m_bEmpty = false; |
|
StartTranslation( pView, vPoint ); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
// set temp transformation plane |
|
|
|
void CToolEntity::StartTranslation( CMapView *pView, const Vector2D &vPoint ) |
|
{ |
|
Vector vOrigin, v1,v2,v3; |
|
|
|
pView->GetBestTransformPlane( v1,v2,v3 ); |
|
|
|
SetTransformationPlane(m_vecPos, v1, v2, v3 ); |
|
// align translation plane to world origin |
|
ProjectOnTranslationPlane( vec3_origin, vOrigin, 0 ); |
|
// set transformation plane |
|
SetTransformationPlane(vOrigin, v1, v2, v3 ); |
|
|
|
Tool3D::StartTranslation( pView, vPoint, false ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : Pre CWnd::OnLButtonUp. |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntity::OnLMouseUp2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint) |
|
{ |
|
Tool3D::OnLMouseUp2D(pView, nFlags, vPoint); |
|
|
|
if (IsTranslating()) |
|
{ |
|
FinishTranslation( true ); |
|
} |
|
|
|
m_pDocument->UpdateStatusbar(); |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Returns true if the message was handled, false otherwise. |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntity::OnMouseMove2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint) |
|
{ |
|
Tool3D::OnMouseMove2D(pView, nFlags, vPoint); |
|
|
|
vgui::HCursor hCursor = vgui::dc_arrow; |
|
|
|
unsigned int uConstraints = GetConstraints( nFlags ); |
|
|
|
// Convert to world coords. |
|
|
|
Vector vecWorld; |
|
pView->ClientToWorld(vecWorld, vPoint); |
|
|
|
// Update status bar position display. |
|
|
|
char szBuf[128]; |
|
|
|
if ( uConstraints & constrainSnap ) |
|
m_pDocument->Snap(vecWorld,uConstraints); |
|
|
|
sprintf(szBuf, " @%.0f, %.0f ", vecWorld[pView->axHorz], vecWorld[pView->axVert] ); |
|
SetStatusText(SBI_COORDS, szBuf); |
|
|
|
// |
|
// If we are currently dragging the marker, update that operation based on |
|
// the current cursor position and keyboard state. |
|
// |
|
if (IsTranslating()) |
|
{ |
|
Tool3D::UpdateTranslation( pView, vPoint, uConstraints ); |
|
|
|
// Don't change the cursor while dragging - it should remain a cross. |
|
hCursor = vgui::dc_none; |
|
} |
|
else if (!IsEmpty()) |
|
{ |
|
// Don't change the cursor while dragging - it should remain a cross. |
|
hCursor = vgui::dc_crosshair; |
|
} |
|
|
|
if ( hCursor != vgui::dc_none ) |
|
pView->SetCursor( hCursor ); |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Returns true if the message was handled, false otherwise. |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntity::OnMouseMove3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) |
|
{ |
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Returns true if the message was handled, false otherwise. |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntity::OnKeyDown3D(CMapView3D *pView, UINT nChar, UINT nRepCnt, UINT nFlags) |
|
{ |
|
CMapDoc *pDoc = pView->GetMapDoc(); |
|
if (pDoc == NULL) |
|
{ |
|
return false; |
|
} |
|
|
|
switch (nChar) |
|
{ |
|
case VK_RETURN: |
|
{ |
|
// |
|
// Create the entity or prefab. |
|
// |
|
if (!IsEmpty()) |
|
{ |
|
//CreateMapObject(pView); // TODO: support in 3D |
|
} |
|
return true; |
|
} |
|
|
|
case VK_ESCAPE: |
|
{ |
|
OnEscape(); |
|
return true; |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Handles the escape key in the 2D or 3D views. |
|
//----------------------------------------------------------------------------- |
|
void CToolEntity::OnEscape(void) |
|
{ |
|
// |
|
// Cancel the object creation tool. |
|
// |
|
if (!IsEmpty()) |
|
{ |
|
SetEmpty(); |
|
} |
|
else |
|
{ |
|
ToolManager()->SetTool(TOOL_POINTER); |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *pView - |
|
// nFlags - |
|
// point - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CToolEntity::OnLMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) |
|
{ |
|
ULONG ulFace; |
|
VMatrix LocalMatrix, LocalMatrixNeg; |
|
CMapClass *pObject = pView->NearestObjectAt( vPoint, ulFace, FLAG_OBJECTS_AT_RESOLVE_INSTANCES, &LocalMatrix ); |
|
Tool3D::OnLMouseDown3D(pView, nFlags, vPoint); |
|
|
|
if (pObject != NULL) |
|
{ |
|
CMapSolid *pSolid = dynamic_cast <CMapSolid *> (pObject); |
|
if (pSolid == NULL) |
|
{ |
|
// Clicked on a point entity - do nothing. |
|
return true; |
|
} |
|
|
|
LocalMatrix.InverseTR( LocalMatrixNeg ); |
|
|
|
// Build a ray to trace against the face that they clicked on to |
|
// find the point of intersection. |
|
|
|
Vector Start,End; |
|
pView->GetCamera()->BuildRay( vPoint, Start, End); |
|
|
|
Vector HitPos, HitNormal; |
|
CMapFace *pFace = pSolid->GetFace(ulFace); |
|
Vector vFinalStart, vFinalEnd; |
|
LocalMatrixNeg.V3Mul( Start, vFinalStart ); |
|
LocalMatrixNeg.V3Mul( End, vFinalEnd ); |
|
if (pFace->TraceLine( HitPos, HitNormal, vFinalStart, vFinalEnd)) |
|
{ |
|
Vector vFinalHitPos, vFinalHitNormal; |
|
LocalMatrix.V3Mul( HitPos, vFinalHitPos ); |
|
vFinalHitNormal = LocalMatrix.ApplyRotation( HitNormal ); |
|
CMapClass *pNewObject = NULL; |
|
|
|
if (GetMainWnd()->m_ObjectBar.IsEntityToolCreatingPrefab()) |
|
{ |
|
// |
|
// Prefab creation. |
|
// |
|
unsigned int uConstraints = GetConstraints( nFlags ); |
|
m_pDocument->Snap(vFinalHitPos,uConstraints); |
|
|
|
GetHistory()->MarkUndoPosition(m_pDocument->GetSelection()->GetList(), "New Prefab"); |
|
|
|
// Get prefab object |
|
CMapClass *pPrefabObject = GetMainWnd()->m_ObjectBar.BuildPrefabObjectAtPoint(vFinalHitPos); |
|
|
|
// |
|
// Add prefab to the world. |
|
// |
|
CMapWorld *pWorld = m_pDocument->GetMapWorld(); |
|
m_pDocument->ExpandObjectKeywords(pPrefabObject, pWorld); |
|
|
|
pNewObject = pPrefabObject; |
|
} |
|
else if (GetMainWnd()->m_ObjectBar.IsEntityToolCreatingEntity()) |
|
{ |
|
// |
|
// Entity creation. |
|
// |
|
GetHistory()->MarkUndoPosition(m_pDocument->GetSelection()->GetList(), "New Entity"); |
|
|
|
CMapEntity *pEntity = new CMapEntity; |
|
pEntity->SetPlaceholder(TRUE); |
|
pEntity->SetOrigin(vFinalHitPos); |
|
pEntity->SetClass(CObjectBar::GetDefaultEntityClass()); |
|
|
|
VPlane BeforeTransform( pFace->plane.normal, pFace->plane.dist ), AfterTransform; |
|
LocalMatrix.TransformPlane( BeforeTransform, AfterTransform ); |
|
|
|
PLANE NewPlane; |
|
|
|
NewPlane.dist = AfterTransform.m_Dist; |
|
NewPlane.normal = AfterTransform.m_Normal; |
|
// Align the entity on the plane properly |
|
pEntity->AlignOnPlane(vFinalHitPos, &NewPlane, (vFinalHitNormal.z > 0.0f) ? CMapEntity::ALIGN_BOTTOM : CMapEntity::ALIGN_TOP); |
|
|
|
pNewObject = pEntity; |
|
} |
|
|
|
if ( pNewObject ) |
|
{ |
|
if ( GetMainWnd()->m_ObjectBar.UseRandomYawOnEntityPlacement() ) |
|
{ |
|
// They checked "random yaw" on the object bar, so come up with a random yaw. |
|
VMatrix vmRotate, vmT1, vmT2; |
|
Vector vOrigin; |
|
QAngle angRandom( 0, RandomInt( -180, 180 ), 0 ); |
|
|
|
pNewObject->GetOrigin( vOrigin ); |
|
|
|
// Setup a matrix that translates them to the origin, rotates it, then translates back. |
|
MatrixFromAngles( angRandom, vmRotate ); |
|
MatrixBuildTranslation( vmT1, -vOrigin ); |
|
MatrixBuildTranslation( vmT2, vOrigin ); |
|
|
|
// Transform the object. |
|
pNewObject->Transform( vmT2 * vmRotate * vmT1 ); |
|
} |
|
|
|
m_pDocument->AddObjectToWorld( pNewObject ); |
|
GetHistory()->KeepNew( pNewObject ); |
|
|
|
// Select the new object. |
|
m_pDocument->SelectObject( pNewObject, scClear|scSelect|scSaveChanges ); |
|
|
|
m_pDocument->SetModifiedFlag(); |
|
} |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Renders a selection gizmo at our bounds center. |
|
// Input : pRender - Rendering interface. |
|
//----------------------------------------------------------------------------- |
|
void CToolEntity::RenderTool3D(CRender3D *pRender) |
|
{ |
|
Vector pos = m_vecPos; |
|
|
|
if ( IsTranslating() ) |
|
{ |
|
TranslatePoint( pos ); |
|
} |
|
else if ( IsEmpty() ) |
|
{ |
|
return; |
|
} |
|
|
|
// |
|
// Setup the renderer. |
|
// |
|
pRender->PushRenderMode( RENDER_MODE_WIREFRAME); |
|
|
|
CMeshBuilder meshBuilder; |
|
CMatRenderContextPtr pRenderContext( MaterialSystemInterface() ); |
|
IMesh* pMesh = pRenderContext->GetDynamicMesh(); |
|
|
|
meshBuilder.Begin(pMesh, MATERIAL_LINES, 3); |
|
|
|
meshBuilder.Position3f(g_MIN_MAP_COORD, pos.y, pos.z); |
|
meshBuilder.Color3ub(255, 0, 0); |
|
meshBuilder.AdvanceVertex(); |
|
meshBuilder.Position3f(g_MAX_MAP_COORD, pos.y, pos.z); |
|
meshBuilder.Color3ub(255, 0, 0); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3f(pos.x, g_MIN_MAP_COORD, pos.z); |
|
meshBuilder.Color3ub(0, 255, 0); |
|
meshBuilder.AdvanceVertex(); |
|
meshBuilder.Position3f(pos.x, g_MAX_MAP_COORD, pos.z); |
|
meshBuilder.Color3ub(0, 255, 0); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.Position3f(pos.x, pos.y, g_MIN_MAP_COORD); |
|
meshBuilder.Color3ub(0, 0, 255); |
|
meshBuilder.AdvanceVertex(); |
|
meshBuilder.Position3f(pos.x, pos.y, g_MAX_MAP_COORD); |
|
meshBuilder.Color3ub(0, 0, 255); |
|
meshBuilder.AdvanceVertex(); |
|
|
|
meshBuilder.End(); |
|
pMesh->Draw(); |
|
|
|
pRender->PopRenderMode(); |
|
} |
|
|
|
|
|
void CToolEntity::CreateMapObject(CMapView2D *pView) |
|
{ |
|
CMapWorld *pWorld = m_pDocument->GetMapWorld(); |
|
CMapClass *pobj = NULL; |
|
|
|
// |
|
// Handle prefab creation. |
|
// |
|
if (GetMainWnd()->m_ObjectBar.IsEntityToolCreatingPrefab()) |
|
{ |
|
GetHistory()->MarkUndoPosition(m_pDocument->GetSelection()->GetList(), "New Prefab"); |
|
|
|
CMapClass *pPrefabObject = GetMainWnd()->m_ObjectBar.BuildPrefabObjectAtPoint(m_vecPos); |
|
|
|
if (pPrefabObject == NULL) |
|
{ |
|
pView->MessageBox("Unable to load prefab", "Error", MB_OK); |
|
SetEmpty(); |
|
return; |
|
} |
|
|
|
m_pDocument->ExpandObjectKeywords(pPrefabObject, pWorld); |
|
m_pDocument->AddObjectToWorld(pPrefabObject); |
|
|
|
GetHistory()->KeepNew(pPrefabObject); |
|
|
|
pobj = pPrefabObject; |
|
} |
|
// |
|
// Handle entity creation. |
|
// |
|
else if (GetMainWnd()->m_ObjectBar.IsEntityToolCreatingEntity()) |
|
{ |
|
GetHistory()->MarkUndoPosition(m_pDocument->GetSelection()->GetList(), "New Entity"); |
|
|
|
CMapEntity *pEntity = new CMapEntity; |
|
|
|
pEntity->SetPlaceholder(TRUE); |
|
pEntity->SetOrigin(m_vecPos); |
|
pEntity->SetClass(CObjectBar::GetDefaultEntityClass()); |
|
|
|
m_pDocument->AddObjectToWorld(pEntity); |
|
|
|
pobj = pEntity; |
|
|
|
GetHistory()->KeepNew(pEntity); |
|
} |
|
|
|
// |
|
// Select the new object. |
|
// |
|
m_pDocument->SelectObject(pobj, scClear |scSelect|scSaveChanges); |
|
|
|
SetEmpty(); |
|
|
|
m_pDocument->SetModifiedFlag(); |
|
} |
|
|
|
|
|
|