示例#1
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : dwNodeID - 
// Output : CMapEntity *
//-----------------------------------------------------------------------------
CMapEntity *CMapPath::CreateEntityForNode(DWORD dwNodeID)
{
	int iIndex;
	CMapPathNode *pNode = NodeForID(dwNodeID, &iIndex);
	if (pNode == NULL)
	{
		return NULL;	// no node, no entity!
	}

	CMapEntity *pEntity = new CMapEntity;

	for (int k = pNode->kv.GetFirst(); k != pNode->kv.GetInvalidIndex(); k=pNode->kv.GetNext( k ) )
	{
		pEntity->SetKeyValue(pNode->kv.GetKey(k), pNode->kv.GetValue(k));
	}
	
	// store target/targetname properties:
	CString str;
	str.Format("%s%02d", m_szName, iIndex);
	pEntity->SetKeyValue("targetname", str);

	int iNext = iIndex + 1;
	if(iNext != -1)
	{
		str.Format("%s%02d", m_szName, iNext);
		pEntity->SetKeyValue("target", str);
	}

	pEntity->SetClass(m_szClass);

	return pEntity;
}
//-----------------------------------------------------------------------------
// Purpose: Called when an object that we depend on has changed.
//-----------------------------------------------------------------------------
void CMapKeyFrame::OnNotifyDependent(CMapClass *pObject, Notify_Dependent_t eNotifyType)
{
	CMapClass::OnNotifyDependent(pObject, eNotifyType);

	if ((pObject == m_pAnimator) && (eNotifyType == Notify_Removed))
	{
		SetAnimator(NULL);
	}

	//
	// If our next keyframe was deleted, try to link to the one after it.
	//
	if ((pObject == m_pNextKeyFrame) && (eNotifyType == Notify_Removed))
	{
		CMapEntity *pNextParent = m_pNextKeyFrame->GetParentEntity();
		CMapEntity *pParent = GetParentEntity();

		if ( pNextParent && pParent )
		{
			const char *szNext = pNextParent->GetKeyValue("NextKey");
			pParent->SetKeyValue("NextKey", szNext);
		}
	}

	m_bRebuildPath = true;
}
示例#3
0
//-----------------------------------------------------------------------------
// Purpose: Updates the cached pointers to our start and end entities by looking
//			for them in the given world.
// Input  : pWorld - World to search.
//-----------------------------------------------------------------------------
void CMapLine::UpdateDependencies(CMapWorld *pWorld, CMapClass *pObject)
{
	CMapClass::UpdateDependencies(pWorld, pObject);

	if (pWorld == NULL)
	{
		return;
	}

	CMapEntity *pEntity = dynamic_cast <CMapEntity *> (m_pParent);
	Assert(pEntity != NULL);

	if (pEntity != NULL)
	{
		const char *pszValue = pEntity->GetKeyValue(m_szStartValueKey);
		m_pStartEntity = (CMapEntity *)UpdateDependency(m_pStartEntity, pWorld->FindChildByKeyValue(m_szStartKey, pszValue));

		if (m_szEndValueKey[0] != '\0')
		{
			pszValue = pEntity->GetKeyValue(m_szEndValueKey);
			m_pEndEntity = (CMapEntity *)UpdateDependency(m_pEndEntity, pWorld->FindChildByKeyValue(m_szEndKey, pszValue));
		}
		else
		{
			// We don't have an end entity specified, use our parent as the end point.
			m_pEndEntity = (CMapEntity *)UpdateDependency(m_pEndEntity, GetParent());
		}

		BuildLine();
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pError - 
//-----------------------------------------------------------------------------
static void FixDuplicateKeys(MapError *pError)
{
	// find duplicate keys in keyvalues and kill them
	CMapEntity *pEntity = (CMapEntity *)pError->pObjects[0];
	int nKeyValues = pEntity->GetKeyValueCount();

DoAgain:

	for (int i = 0; i < nKeyValues; i++)
	{
		for (int j = 0; j < nKeyValues; j++)
		{
			if (i == j)
			{
				continue;
			}

			if (!strcmpi(pEntity->GetKey(i), pEntity->GetKey(j)))
			{
				pEntity->RemoveKey(i);
				//--kv.nkv;
				goto DoAgain;
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Builds a new value string for our parent's facelist key from our
//			current list of faces and submits the keyvalue to our parent for
//			storage.
//-----------------------------------------------------------------------------
void CMapSideList::UpdateParentKey(void)
{
	char szValue[KEYVALUE_MAX_VALUE_LENGTH];
	CMapWorld::FaceID_FaceListsToString(szValue, sizeof(szValue), &m_Faces, NULL);

	CMapEntity *pEntity = dynamic_cast<CMapEntity *>(Parent);
	if (pEntity != NULL)
	{
		pEntity->NotifyChildKeyChanged(this, m_szKeyName, szValue);
	}
}
//-----------------------------------------------------------------------------
// Purpose: Called after the entire map has been loaded. This allows the object
//			to perform any linking with other map objects or to do other operations
//			that require all world objects to be present.
// Input  : pWorld - The world that we are in.
//-----------------------------------------------------------------------------
void CMapSideList::PostloadWorld(CMapWorld *pWorld)
{
	CMapClass::PostloadWorld(pWorld);

	//
	// Generate our list of faces from our parent's keyvalue.
	//
	CMapEntity *pEntity = dynamic_cast<CMapEntity *>(Parent);
	if (pEntity != NULL)
	{
		const char *pszValue = pEntity->GetKeyValue(m_szKeyName);
		if (pszValue != NULL)
		{
			BuildFaceListForValue(pszValue, pWorld);
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: notifies the keyframe that it has been cloned
//			inserts the clone into the correct place in the keyframe list
// Input  : *pClone - 
//-----------------------------------------------------------------------------
void CMapKeyFrame::OnClone( CMapClass *pClone, CMapWorld *pWorld, const CMapObjectList &OriginalList, CMapObjectList &NewList )
{
	CMapClass::OnClone( pClone, pWorld, OriginalList, NewList );

	CMapKeyFrame *pNewKey = dynamic_cast<CMapKeyFrame*>( pClone );
	Assert( pNewKey != NULL );
	if ( !pNewKey )
		return;

	CMapEntity *pEntity = dynamic_cast<CMapEntity*>( m_pParent );
	CMapEntity *pNewEntity = dynamic_cast<CMapEntity*>( pClone->GetParent() );

	// insert the newly created keyframe into the sequence

	// point the clone's next at what we were pointing at
	const char *nextKey = pEntity->GetKeyValue( "NextKey" );
	if ( nextKey )
	{
		pNewEntity->SetKeyValue( "NextKey", nextKey );
	}

	// create a new targetname for the clone
	char newName[128];
	const char *oldName = pEntity->GetKeyValue( "targetname" );
	if ( !oldName || oldName[0] == 0 )
		oldName = "keyframe";

	pWorld->GenerateNewTargetname( oldName, newName, sizeof( newName ), true, NULL );
	pNewEntity->SetKeyValue( "targetname", newName );

	// point the current keyframe at the clone
	pEntity->SetKeyValue( "NextKey", newName );
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pObject - 
//			FindObject - 
// Output : Returns true if the object matches the search criteria, false if not.
//-----------------------------------------------------------------------------
bool FindCheck(CMapClass *pObject, FindObject_t &FindObject)
{
	CMapEntity *pEntity = dynamic_cast <CMapEntity *>(pObject);
	if (!pEntity)
	{
		return false;
	}

	if (FindObject.bVisiblesOnly && !pObject->IsVisible())
	{
		return false;
	}

	//
	// Search keyvalues.
	//
	int nKeyCount = pEntity->GetKeyValueCount();
	for (int i = 0; i < nKeyCount; i++)
	{
		const char *pszValue = pEntity->GetKeyValue(i);
		if (pszValue && MatchString(pszValue, FindObject))
		{
			return true;
		}
	}

	//
	// Search connections.
	//
	POSITION pos = pEntity->Connections_GetHeadPosition();
	while (pos)
	{
		CEntityConnection *pConn = pEntity->Connections_GetNext(pos);
		if (pConn)
		{
			if (MatchString(pConn->GetTargetName(), FindObject) ||
				MatchString(pConn->GetParam(), FindObject))
			{
				return true;
			}
		}
	}

	return false;
}
//-----------------------------------------------------------------------------
// Purpose: Checks for node entities with the same node ID.
//-----------------------------------------------------------------------------
static void CheckDuplicateNodeIDs(CListBox *pList, CMapWorld *pWorld)
{
	EnumChildrenPos_t pos;
	CMapClass *pChild = pWorld->GetFirstDescendent(pos);
	while (pChild != NULL)
	{
		CMapEntity *pEntity = dynamic_cast<CMapEntity *>(pChild);
		if (pEntity && pEntity->IsNodeClass())
		{
			if (FindDuplicateNodeID(pEntity, pWorld))
			{
				AddError(pList, ErrorDuplicateNodeIDs, (DWORD)pWorld, pEntity);
			}
		}
		
		pChild = pWorld->GetNextDescendent(pos);
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CMapPointHandle::UpdateParentKey(void)
{
	// Snap to prevent error creep.
	for (int i = 0; i < 3; i++)
	{
		m_Origin[i] = rint(m_Origin[i] / 0.01f) * 0.01f;
	}

	if (m_szKeyName[0])
	{
		CMapEntity *pEntity = dynamic_cast <CMapEntity *> (m_pParent);
		if (pEntity != NULL)
		{
			char szValue[KEYVALUE_MAX_VALUE_LENGTH];
			sprintf(szValue, "%g %g %g", (double)m_Origin.x, (double)m_Origin.y, (double)m_Origin.z);
			pEntity->NotifyChildKeyChanged(this, m_szKeyName, szValue);

		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pCopy - 
//			pSourceWorld - 
//			pDestWorld - 
//			OriginalList - 
//			NewList - 
//-----------------------------------------------------------------------------
void CMapSideList::OnPaste(CMapClass *pCopyObject, CMapWorld *pSourceWorld, CMapWorld *pDestWorld, CMapObjectList &OriginalList, CMapObjectList &NewList)
{
	CMapSideList *pCopy = (CMapSideList *)pCopyObject;

	//
	// HACK: This is kinda nasty. Build a list of face IDs from our parent keyvalue so
	// we can remap them to faces in the clipboard.
	//
	CMapEntity *pParent = dynamic_cast <CMapEntity *>(pCopy->GetParent());
	const char *pszValue = pParent->GetKeyValue(m_szKeyName);
	if (pszValue != NULL)
	{
		char szVal[KEYVALUE_MAX_VALUE_LENGTH];
		strcpy(szVal, pszValue);

		char *psz = strtok(szVal, " ");
		while (psz != NULL)
		{
			//
			// The substring should now be a single face ID. Get the corresponding
			// face and add it to the list.
			//
			int nFaceID = atoi(psz);
			CMapFace *pFace = FindFaceIDInList(nFaceID, OriginalList);
			if (pFace != NULL)
			{
				pCopy->m_Faces.AddToTail(pFace);
			}

			//
			// Get the next substring.
			//
			psz = strtok(NULL, " ");
		}
	}

	//
	// Now replace all faces with their new counterparts, as in Clone.
	//
	ReplaceFacesInCopy(pCopy, OriginalList, NewList);
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : iInterpolator - 
// Output : IPositionInterpolator
//-----------------------------------------------------------------------------
IPositionInterpolator* CMapKeyFrame::SetupPositionInterpolator( int iInterpolator )
{
	if( iInterpolator != m_iPositionInterpolator )
	{
		if( m_pPositionInterpolator )
			m_pPositionInterpolator->Release();

		m_pPositionInterpolator = Motion_GetPositionInterpolator( iInterpolator );
		m_iPositionInterpolator = iInterpolator;

		// Feed keys..
		CMapEntity *pEnt = GetParentEntity();
		if( pEnt )
		{
			for ( int i=pEnt->GetFirstKeyValue(); i != pEnt->GetInvalidKeyValue(); i=pEnt->GetNextKeyValue( i ) )
			{
				m_pPositionInterpolator->ProcessKey( 
					pEnt->GetKey( i ),
					pEnt->GetKeyValue( i ) );
			}
		}
	}


	return m_pPositionInterpolator;
}
//-----------------------------------------------------------------------------
// Purpose: Returns true if there is another node entity in the world with the
//			same node ID as the given entity.
// Input  : pNode - 
//			pWorld - 
//-----------------------------------------------------------------------------
bool FindDuplicateNodeID(CMapEntity *pNode, CMapWorld *pWorld)
{
	EnumChildrenPos_t pos;
	CMapClass *pChild = pWorld->GetFirstDescendent(pos);
	while (pChild != NULL)
	{
		CMapEntity *pEntity = dynamic_cast<CMapEntity *>(pChild);
		if (pEntity && (pEntity != pNode) && pEntity->IsNodeClass())
		{
			int nNodeID1 = pNode->GetNodeID();
			int nNodeID2 = pEntity->GetNodeID();
			if ((nNodeID1 != 0) && (nNodeID2 != 0) && (nNodeID1 == nNodeID2))
			{
				return true;
			}
		}
		
		pChild = pWorld->GetNextDescendent(pos);
	}

	return false;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CMapSweptPlayerHull::UpdateParentKey(void)
{
	CMapEntity *pEntity = dynamic_cast <CMapEntity *> (m_pParent);
	if (pEntity != NULL)
	{
		Vector vecOrigin1;
		Vector vecOrigin2;
		m_Point[0]->GetOrigin(vecOrigin1);
		m_Point[1]->GetOrigin(vecOrigin2);

		vecOrigin1 -= playerFixup;
		vecOrigin2 -= playerFixup;

		PostUpdate(Notify_Changed);

		char szValue[KEYVALUE_MAX_VALUE_LENGTH];
		sprintf(szValue, "%g %g %g", (double)vecOrigin1.x, (double)vecOrigin1.y, (double)vecOrigin1.z );
		pEntity->NotifyChildKeyChanged(this, "point0", szValue);
		pEntity->NotifyChildKeyChanged(this, "origin", szValue);

		sprintf(szValue, "%g %g %g", (double)vecOrigin2.x, (double)vecOrigin2.y, (double)vecOrigin2.z);
		pEntity->NotifyChildKeyChanged(this, "point1", szValue);
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : pError - 
//-----------------------------------------------------------------------------
static void FixUnusedKeyvalues(MapError *pError)
{
	CMapEntity *pEntity = (CMapEntity*) pError->pObjects[0];

	GDclass *pClass = pEntity->GetClass();
	if (!pClass)
	{
		return;
	}

	int nKeyValues = pEntity->GetKeyValueCount();
	for (int i = nKeyValues - 1; i >= 0; i--)
	{
		if (pClass->VarForName(pEntity->GetKey(i)) == NULL)
		{
			pEntity->DeleteKeyValue(pEntity->GetKey(i));
		}
	}
}
示例#16
0
void Marker3D::CreateMapObject(CMapView2D *pView)
{
	CMapWorld *pWorld = m_pDocument->GetMapWorld();
	CMapClass *pobj = NULL;

	//
	// Handle prefab creation.
	//
	if (GetMainWnd()->m_ObjectBar.IsEntityToolCreatingPrefab())
	{			
		GetHistory()->MarkUndoPosition(m_pDocument->Selection_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->Selection_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);
	}

	m_pDocument->ToolUpdateViews(CMapView2D::updEraseTool);

	//
	// Select the new object.
	//
	m_pDocument->SelectObject(pobj, CMapDoc::scClear | CMapDoc::scSelect | CMapDoc::scUpdateDisplay);

	//
	// Update all the views.
	//	
	UpdateBox ub;
	CMapObjectList ObjectList;
	ObjectList.AddTail(pobj);
	ub.Objects = &ObjectList;

	Vector mins;
	Vector maxs;
	pobj->GetRender2DBox(mins, maxs);
	ub.Box.SetBounds(mins, maxs);

	m_pDocument->UpdateAllViews(NULL, MAPVIEW_UPDATE_OBJECTS, &ub);

	SetEmpty();

	m_pDocument->SetModifiedFlag();
}
//-----------------------------------------------------------------------------
// Purpose: Fixes duplicate node IDs by assigning the entity a unique node ID.
// Input  : pError - Holds the world and the entity that is in error.
//-----------------------------------------------------------------------------
static void FixDuplicateNodeIDs(MapError *pError)
{
	CMapEntity *pEntity = (CMapEntity *)pError->pObjects[0];
	CMapWorld *pWorld = (CMapWorld *)pError->dwExtra;
	pEntity->AssignNodeID();
}
//-----------------------------------------------------------------------------
// Purpose: creates a new keyframe at the specified time
// Input  : time - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
CMapEntity *CMapAnimator::CreateNewKeyFrame( float time )
{
	// work out where we are in the animation
	CMapKeyFrame *key;
	CMapKeyFrame *pPrevKey;
	float partialTime = GetKeyFramesAtTime( time, key, pPrevKey );

	CMapEntity *pCurrentEnt = dynamic_cast<CMapEntity*>( key->Parent );

	// check to see if we're direction on a key frame
	Vector posOffset( 0, 0, 0 );
	if ( partialTime == 0 )
	{
		// create this new key frame slightly after the current one, and offset
		posOffset[0] = 64;
	}

	// get our orientation and position at this time
	Vector vOrigin;
	QAngle angles;
	Quaternion qAngles;
	GetAnimationAtTime( key, pPrevKey, partialTime, vOrigin, qAngles, m_iPositionInterpolator, m_iRotationInterpolator );
	QuaternionAngles( qAngles, angles );

	// create the new map entity
	CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
	CMapWorld *pWorld = pDoc->GetMapWorld();

	CMapEntity *pNewEntity = new CMapEntity;

	Vector newPos;
	VectorAdd( vOrigin, posOffset, newPos );
	pNewEntity->SetPlaceholder( TRUE );
	pNewEntity->SetOrigin( newPos );
	pNewEntity->SetClass( "keyframe_track" );

	char buf[128];
	sprintf( buf, "%f %f %f", angles[0], angles[1], angles[2] );
	pNewEntity->SetKeyValue( "angles", buf );

	// link it into the keyframe list

	// take over this existing next keyframe pointer
	const char *nextKeyName = pCurrentEnt->GetKeyValue( "NextKey" );
	if ( nextKeyName )
	{
		pNewEntity->SetKeyValue( "NextKey", nextKeyName );
	}
		
	// create a new unique name for this ent
	char newName[128];
	const char *oldName = pCurrentEnt->GetKeyValue( "targetname" );
	if ( !oldName || oldName[0] == 0 )
		oldName = "keyframe";

	CMapEntity::GenerateNewTargetname( oldName, newName, 127 );
	pNewEntity->SetKeyValue( "targetname", newName );

	// point the current entity at the newly created one
	pCurrentEnt->SetKeyValue( "NextKey", newName );

	// copy any relevant values
	const char *keyValue = pCurrentEnt->GetKeyValue( "parentname" );
	if ( keyValue )
		pNewEntity->SetKeyValue( "parentname", keyValue );

	keyValue = pCurrentEnt->GetKeyValue( "MoveSpeed" );
	if ( keyValue )
		pNewEntity->SetKeyValue( "MoveSpeed", keyValue );

	return(pNewEntity);
}
//-----------------------------------------------------------------------------
// Purpose: Rebuilds the line path between keyframe entities
//			samples the interpolator function to get an approximation of the curve
//-----------------------------------------------------------------------------
void CMapAnimator::RebuildPath( void )
{
	CMapClass *pWorld = GetWorldObject( this );
	if ( !pWorld )
	{
		// Sometimes the object isn't linked back into the world yet when RebuildPath() 
		// is called... we will be get called again when needed, but may cause an incorrect
		// (linear-only) path to get drawn temporarily.
		return;
	}

	//
	// Build the path forward from the head. Keep a list of nodes we've visited to
	// use in detecting circularities.
	//
	CMapObjectList VisitedList;
	CMapKeyFrame *pCurKey = this;
	while ( pCurKey != NULL )
	{
		VisitedList.AddTail( pCurKey );

		//
		// Attach ourselves as this keyframe's animator.
		//
		pCurKey->SetAnimator( this );

		//
		// Get the entity parent of this keyframe so we can query keyvalues.
		//
		CMapEntity *pCurEnt = dynamic_cast<CMapEntity *>( pCurKey->GetParent() );
		if ( !pCurEnt )
		{
			return;
		}

		//
		// Find the next keyframe in the path.
		//
		CMapEntity *pNextEnt = pWorld->FindChildByKeyValue( "targetname", pCurEnt->GetKeyValue( "NextKey" ) );
		CMapKeyFrame *pNextKey = NULL;

		if ( pNextEnt )
		{
			pNextKey = pNextEnt->GetChildOfType( ( CMapKeyFrame * )NULL );
			pCurKey->SetNextKeyFrame(pNextKey);
		}
		else
		{
			pCurKey->SetNextKeyFrame( NULL );
		}

		pCurKey = pNextKey;

		//
		// If we detect a circularity, stop.
		//
		if ( VisitedList.Find( pCurKey ) )
		{
			break;
		}
	}

	//
	// Now traverse the path again building the spline points, once again checking
	// the visited list for circularities.
	//
	VisitedList.RemoveAll();
	pCurKey = this;
	CMapKeyFrame *pPrevKey = this;
	while ( pCurKey != NULL )
	{
		VisitedList.AddTail( pCurKey );

		pCurKey->BuildPathSegment(pPrevKey);

		pPrevKey = pCurKey;
		pCurKey = pCurKey->m_pNextKeyFrame;

		//
		// If we detect a circularity, stop.
		//
		if ( VisitedList.Find( pCurKey ) )
		{
			break;
		}
	}
}
示例#20
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pView - 
//			nFlags - 
//			point - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool Marker3D::OnLMouseDown3D(CMapView3D *pView, UINT nFlags, CPoint point)
{
	ULONG ulFace;
	CMapClass *pObject = pView->NearestObjectAt(point, ulFace);
	if (pObject != NULL)
	{
		CMapSolid *pSolid = dynamic_cast <CMapSolid *> (pObject);
		if (pSolid == NULL)
		{
			// Clicked on a point entity - do nothing.
			return true;
		}

		CMapDoc *pDoc = pView->GetDocument();

		//
		// Build a ray to trace against the face that they clicked on to
		// find the point of intersection.
		//			
		Vector Start;
		Vector End;
		pView->BuildRay(point, Start, End);

		Vector HitPos, HitNormal;
		CMapFace *pFace = pSolid->GetFace(ulFace);
		if (pFace->TraceLine(HitPos, HitNormal, Start, End))
		{
			if (GetMainWnd()->m_ObjectBar.IsEntityToolCreatingPrefab())
			{
				//
				// Prefab creation.
				//
				pDoc->Snap(HitPos);

				GetHistory()->MarkUndoPosition(pDoc->Selection_GetList(), "New Prefab");

				// Get prefab object
				CMapClass *pPrefabObject = GetMainWnd()->m_ObjectBar.BuildPrefabObjectAtPoint(HitPos);

				//
				// Add prefab to the world.
				//
				CMapWorld *pWorld = pDoc->GetMapWorld();
				pDoc->ExpandObjectKeywords(pPrefabObject, pWorld);
				pDoc->AddObjectToWorld(pPrefabObject);
				GetHistory()->KeepNew(pPrefabObject);

				//
				// Select the new object.
				//
				pDoc->SelectObject(pPrefabObject, CMapDoc::scClear | CMapDoc::scSelect | CMapDoc::scUpdateDisplay);

				//
				// Update world bounds.
				//
				UpdateBox ub;
				CMapObjectList ObjectList;
				ObjectList.AddTail(pPrefabObject);
				ub.Objects = &ObjectList;

				Vector mins;
				Vector maxs;
				pPrefabObject->GetRender2DBox(mins, maxs);
				ub.Box.SetBounds(mins, maxs);

				pDoc->UpdateAllViews(NULL, MAPVIEW_UPDATE_OBJECTS, &ub);
				
				pDoc->SetModifiedFlag();
			}
			else if (GetMainWnd()->m_ObjectBar.IsEntityToolCreatingEntity())
			{
				//
				// Entity creation.
				//
				GetHistory()->MarkUndoPosition(pDoc->Selection_GetList(), "New Entity");
				
				CMapEntity *pEntity = new CMapEntity;
				pEntity->SetPlaceholder(TRUE);
				pEntity->SetOrigin(HitPos);
				pEntity->SetClass(CObjectBar::GetDefaultEntityClass());
				
				//Align the entity on the plane properly
				//				pEntity->AlignOnPlane(HitPos, &pFace->plane, (pFace->plane.normal[2] > 0.0f) ? CMapEntity::ALIGN_BOTTOM : CMapEntity::ALIGN_TOP);
				pEntity->AlignOnPlane(HitPos, &pFace->plane, (HitNormal[2] > 0.0f) ? CMapEntity::ALIGN_BOTTOM : CMapEntity::ALIGN_TOP);
									
				CMapWorld *pWorld = pDoc->GetMapWorld();
				pDoc->AddObjectToWorld(pEntity);
				
				GetHistory()->KeepNew(pEntity);

				//
				// Select the new object.
				//
				pDoc->SelectObject(pEntity, CMapDoc::scClear | CMapDoc::scSelect | CMapDoc::scUpdateDisplay);
				
 				UpdateBox ub;
				CMapObjectList ObjectList;
				ObjectList.AddTail(pEntity);
				ub.Objects = &ObjectList;

				Vector mins;
				Vector maxs;
				pEntity->GetRender2DBox(mins, maxs);
				ub.Box.SetBounds(mins, maxs);

				pDoc->UpdateAllViews(NULL, MAPVIEW_UPDATE_OBJECTS, &ub);
			
				pDoc->SetModifiedFlag();
			}
		}
	}

	return true;
}