Index: source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PlaceObject.cpp
===================================================================
--- source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PlaceObject.cpp	(revision 16116)
+++ source/tools/atlas/AtlasUI/ScenarioEditor/Tools/PlaceObject.cpp	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013 Wildfire Games.
+/* Copyright (C) 2015 Wildfire Games.
  * This file is part of 0 A.D.
  *
  * 0 A.D. is free software: you can redistribute it and/or modify
@@ -181,9 +181,15 @@
 				return true;
 			else if (evt.LeftUp())
 			{
-				obj->m_Target = Position(evt.GetPosition());
-				// Create the actual object
-				obj->SendObjectMsg(false);
+				AtlasMessage::qCanPlaceObject canPlaceObject;
+				canPlaceObject.Post();
+
+				if (canPlaceObject.response)
+				{
+					obj->m_Target = Position(evt.GetPosition());
+					// Create the actual object
+					obj->SendObjectMsg(false);
+				}
 				// Go back to preview mode
 				SET_STATE(Waiting);
 				obj->m_ObjPos = obj->m_ScreenPos = obj->m_Target;
Index: source/tools/atlas/AtlasUI/ScenarioEditor/Tools/TransformObject.cpp
===================================================================
--- source/tools/atlas/AtlasUI/ScenarioEditor/Tools/TransformObject.cpp	(revision 16116)
+++ source/tools/atlas/AtlasUI/ScenarioEditor/Tools/TransformObject.cpp	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 Wildfire Games.
+/* Copyright (C) 2015 Wildfire Games.
  * This file is part of 0 A.D.
  *
  * 0 A.D. is free software: you can redistribute it and/or modify
@@ -366,6 +359,14 @@
 		{
 			if (evt.LeftUp())
 			{
+				AtlasMessage::qCanPlaceObject canPlaceObject;
+				canPlaceObject.Post();
+
+				if (!canPlaceObject.response)
+				{
+					ScenarioEditor::GetCommandProc().FinaliseLastCommand();
+					ScenarioEditor::GetCommandProc().Undo();
+				}
 				SET_STATE(Waiting);
 				return true;
 			}
@@ -536,8 +537,12 @@
 			}
 			else if (evt.LeftDown())
 			{
-				//Place the object and update 
-				obj->OnPasteEnd(false);
+				AtlasMessage::qCanPlaceObject canPlaceObject;
+				canPlaceObject.Post();
+
+				if (canPlaceObject.response)
+					obj->OnPasteEnd(false); //Place the object and update
+
 				return true;
 			}
 			else
Index: source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp
===================================================================
--- source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp	(revision 16116)
+++ source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 Wildfire Games.
+/* Copyright (C) 2015 Wildfire Games.
  * This file is part of 0 A.D.
  *
  * 0 A.D. is free software: you can redistribute it and/or modify
@@ -48,6 +48,7 @@
 #include "simulation2/components/ICmpSelectable.h"
 #include "simulation2/components/ICmpTemplateManager.h"
 #include "simulation2/components/ICmpVisual.h"
+#include "simulation2/components/ICmpObstruction.h"
 #include "simulation2/helpers/Selection.h"
 #include "ps/XML/XMLWriter.h"
 
@@ -61,6 +62,45 @@
 	}
 }
 
+//Helpers for object constraints
+bool CanPlaceObjectEntityHelper(entity_id_t ent)
+{
+	CmpPtr<ICmpObstruction> cmpObstruction(*g_Game->GetSimulation2(), ent);
+	if (!cmpObstruction)
+		return true;
+	else
+	{
+		//use default passClasName.
+		ICmpObstruction::EFoundationCheck result = cmpObstruction->CheckFoundation("default");
+		if (result != ICmpObstruction::FOUNDATION_CHECK_SUCCESS)
+			return false;
+	}
+	return true;
+}
+
+void CheckObstructionAndUpdateVisual(entity_id_t id)
+{
+	//Check build Constraint
+	CmpPtr<ICmpVisual> cmpVisual(*g_Game->GetSimulation2(), id);
+	if (cmpVisual)
+	{
+		if (!CanPlaceObjectEntityHelper(id))
+			cmpVisual->SetShadingColour(fixed::FromDouble(1.4), fixed::FromDouble(0.4), fixed::FromDouble(0.4), fixed::FromDouble(1));
+		else
+			cmpVisual->SetShadingColour(fixed::FromDouble(1), fixed::FromDouble(1), fixed::FromDouble(1), fixed::FromDouble(1));
+	}
+}
+
+bool CanPlaceObjectListHelper(std::vector<entity_id_t>::const_iterator start, std::vector<entity_id_t>::const_iterator end)
+{
+	for (std::vector<entity_id_t>::const_iterator i = start; i != end; i++)
+	{
+		if (!CanPlaceObjectEntityHelper(*i))
+			return false;
+	}
+	return true;
+}
+
 QUERYHANDLER(GetObjectsList)
 {
 	std::vector<sObjectsListItem> objects;
@@ -375,6 +415,16 @@
 	msg->ids = g_Selection;
 }
 
+QUERYHANDLER(CanPlaceObject)
+{
+	if (!g_PreviewEntitiesID.empty())
+		msg->response = CanPlaceObjectListHelper(g_PreviewEntitiesID.begin(), g_PreviewEntitiesID.end());
+	else if (!g_Selection.empty())
+		msg->response = CanPlaceObjectListHelper(g_Selection.begin(), g_Selection.end());
+	else
+		msg->response = true; //by default
+}
+
 MESSAGEHANDLER(ObjectPreviewToEntity)
 {
 	UNUSED2(msg);
@@ -473,6 +523,9 @@
 			posFinal = posFixed + dir;
 		}
 		cmpPosition->JumpTo(posFinal.X, posFinal.Z);
+
+		//Check build Constraint
+		CheckObstructionAndUpdateVisual(id);
 	}
 }
 
@@ -543,6 +596,9 @@
 		CmpPtr<ICmpOwnership> cmpOwnership(*g_Game->GetSimulation2(), g_PreviewEntityID);
 		if (cmpOwnership)
 			cmpOwnership->SetOwner((player_id_t)msg->settings->player);
+
+		//Check build Constraint
+		CheckObstructionAndUpdateVisual(g_PreviewEntityID);
 	}
 }
 
@@ -736,7 +792,8 @@
 		ObjectPositionMap::iterator it;
 		for (it = map.begin(); it != map.end(); ++it)
 		{
-			CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), (entity_id_t)it->first);
+			entity_id_t id = (entity_id_t)it->first;
+			CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), id);
 			if (!cmpPosition)
 				return;
 
@@ -743,6 +800,9 @@
 			// Set 2D position, ignoring height
 			CVector3D pos = it->second;
 			cmpPosition->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
+
+			//Check build Constraint
+			CheckObstructionAndUpdateVisual(id);
 		}
 	}
 
Index: source/tools/atlas/GameInterface/Messages.h
===================================================================
--- source/tools/atlas/GameInterface/Messages.h	(revision 16116)
+++ source/tools/atlas/GameInterface/Messages.h	(working copy)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 Wildfire Games.
+/* Copyright (C) 2015 Wildfire Games.
  * This file is part of 0 A.D.
  *
  * 0 A.D. is free software: you can redistribute it and/or modify
@@ -345,6 +349,11 @@
 	((std::vector<ObjectID>, ids))
 	);
 
+// Check if current preview(s) object(s) can create or current selection move can place
+QUERY(CanPlaceObject,
+	, //No inputs
+	((bool, response))
+	);
 // Moving Preview(s) object together, default is using the firs element in vector
 MESSAGE(MoveObjectPreview,
 		((Position,pos))