예제 #1
0
void LandscapePropertyControl::ReadFrom(SceneNode * sceneNode)
{
	NodesPropertyControl::ReadFrom(sceneNode);

    LandscapeNode *landscape = dynamic_cast<LandscapeNode*> (sceneNode);
	DVASSERT(landscape);

    propertyList->AddSection("property.landscape.landscape", GetHeaderState("property.landscape.landscape", true));
    
    propertyList->AddFloatProperty("property.landscape.size", PropertyList::PROPERTY_IS_EDITABLE);
    propertyList->AddFloatProperty("property.landscape.height", PropertyList::PROPERTY_IS_EDITABLE); 
    Vector3 size(445.0f, 445.0f, 50.f);
    AABBox3 bbox = landscape->GetBoundingBox();
    AABBox3 emptyBox;
    if((emptyBox.min != bbox.min) && (emptyBox.max != bbox.max))
    {
        AABBox3 transformedBox;
        bbox.GetTransformedBox(landscape->GetWorldTransform(), transformedBox);
        size = transformedBox.max - transformedBox.min;
    }
    propertyList->SetFloatPropertyValue("property.landscape.size", size.x);
    propertyList->SetFloatPropertyValue("property.landscape.height", size.z);

    propertyList->AddComboProperty("property.landscape.tilemode", tiledModes);
    propertyList->SetComboPropertyIndex("property.landscape.tilemode", landscape->GetTiledShaderMode());

    propertyList->AddFilepathProperty("property.landscape.heightmap", ".png;.heightmap", false, PropertyList::PROPERTY_IS_EDITABLE);
    propertyList->SetFilepathPropertyValue("property.landscape.heightmap", landscape->GetHeightmapPathname());
    
    
    propertyList->AddSubsection("property.landscape.subsection.textures");
    AddFilepathProperty(String("property.landscape.texture.color"), String(".png;.pvr"), LandscapeNode::TEXTURE_COLOR);
    AddFilepathProperty(String("property.landscape.texture.tile0"), String(".png;.pvr"), LandscapeNode::TEXTURE_TILE0);
    AddFilepathProperty(String("property.landscape.texture.tile1"), String(".png;.pvr"), LandscapeNode::TEXTURE_TILE1);
    AddFilepathProperty(String("property.landscape.texture.tile2"), String(".png;.pvr"), LandscapeNode::TEXTURE_TILE2);
    AddFilepathProperty(String("property.landscape.texture.tile3"), String(".png;.pvr"), LandscapeNode::TEXTURE_TILE3);
    AddFilepathProperty(String("property.landscape.texture.tilemask"), String(".png;.pvr"), LandscapeNode::TEXTURE_TILE_MASK);
    AddFilepathProperty(String("property.landscape.texture.tiledtexture"), String(".png;.pvr"), LandscapeNode::TEXTURE_TILE_FULL);
    propertyList->AddMessageProperty(String("property.landscape.generatefulltiled"), 
                                     Message(this, &LandscapePropertyControl::GenerateFullTiledTexture));

    propertyList->AddSubsection("property.landscape.subsection.build_mask");
    propertyList->AddFilepathProperty("property.landscape.lightmap", String(".png;.pvr"), true, PropertyList::PROPERTY_IS_EDITABLE);
    propertyList->AddFilepathProperty("property.landscape.alphamask", String(".png;.pvr"), true, PropertyList::PROPERTY_IS_EDITABLE);
    propertyList->SetFilepathPropertyValue("property.landscape.lightmap", String(""));
    propertyList->SetFilepathPropertyValue("property.landscape.alphamask", String(""));

    
    propertyList->AddBoolProperty("property.landscape.showgrid", PropertyList::PROPERTY_IS_EDITABLE);
    bool showGrid =  (0 != (landscape->GetDebugFlags() & SceneNode::DEBUG_DRAW_GRID));
    propertyList->SetBoolPropertyValue("property.landscape.showgrid", showGrid);
    

	propertyList->AddIntProperty("lightmap.size");
	propertyList->SetIntPropertyValue("lightmap.size", currentSceneNode->GetCustomProperties()->GetInt32("lightmap.size", 1024));

    propertyList->AddFloatProperty("property.landscape.texture0.tilex");
    propertyList->SetFloatPropertyValue("property.landscape.texture0.tilex", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE0).x);
    propertyList->AddFloatProperty("property.landscape.texture0.tiley");
    propertyList->SetFloatPropertyValue("property.landscape.texture0.tiley", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE0).y);
    
    propertyList->AddFloatProperty("property.landscape.texture1.tilex");
    propertyList->SetFloatPropertyValue("property.landscape.texture1.tilex", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE1).x);
    propertyList->AddFloatProperty("property.landscape.texture1.tiley");
    propertyList->SetFloatPropertyValue("property.landscape.texture1.tiley", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE1).y);

    propertyList->AddFloatProperty("property.landscape.texture2.tilex");
    propertyList->SetFloatPropertyValue("property.landscape.texture2.tilex", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE2).x);
    propertyList->AddFloatProperty("property.landscape.texture2.tiley");
    propertyList->SetFloatPropertyValue("property.landscape.texture2.tiley", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE2).y);
    
    propertyList->AddFloatProperty("property.landscape.texture3.tilex");
    propertyList->SetFloatPropertyValue("property.landscape.texture3.tilex", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE3).x);
    propertyList->AddFloatProperty("property.landscape.texture3.tiley");
    propertyList->SetFloatPropertyValue("property.landscape.texture3.tiley", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE3).y);
    
    ControlsFactory::AddFogSubsection(propertyList, landscape->IsFogEnabled(), landscape->GetFogDensity(), landscape->GetFogColor());
}
void VegetationFixedGeometry::GenerateVertices(uint32 maxClusters,
                    size_t maxTotalClusters,
                    uint32 maxClusterRowSize,
                    uint32 tilesPerRow,
                    Vector2 unitSize,
                    Vector<uint32>& layerOffsets,
                    VegetationRenderData& renderData)
{
    uint32 clustersPerTile = maxClusters * maxClusters;
    float32 atomicOffsetY = unitSize.y / clustersPerTile;
    
    Vector<uint32> shuffleDepth;
    shuffleDepth.reserve(maxTotalClusters);
    
    Vector<uint32> shuffleDensity;
    shuffleDensity.reserve(maxTotalClusters);
    
    Vector<uint32> depthScratchArray;
    depthScratchArray.reserve(clustersPerTile);
    
    Vector<uint32> densityScratchArray;
    densityScratchArray.reserve(clustersPerTile);
    
    for(uint32 i = 0; i < clustersPerTile; ++i)
    {
        depthScratchArray[i] = i;
        densityScratchArray[i] = (i % maxDensityLevels) + 1;
    }
    
    Vector<VegetationVertex>& vertexData = renderData.GetVertices();
    
    size_t vertexIndex = 0;
    uint32 totalTiles = tilesPerRow * tilesPerRow;
    for(uint32 layerIndex = 0; layerIndex < maxLayerTypes; ++layerIndex)
    {
        layerOffsets[layerIndex] = vertexIndex;
        
        TextureSheetCell& cellData = textureSheet.cells[layerIndex];
        
        const Vector3* clusterVertices = VEGETATION_CLUSTER[cellData.geometryId];
        const Vector3* clusterNormals = VEGETATION_CLUSTER_NORMALS[cellData.geometryId];
        uint32 clusterVertexCount = VEGETATION_CLUSTER_SIZE[cellData.geometryId];
        
        uint32 clusterCounter = 0;
        for(uint32 i = 0; i < totalTiles; ++i)
        {
            std::random_shuffle(densityScratchArray.begin(), densityScratchArray.end(), RandomShuffleFunc);
            std::random_shuffle(depthScratchArray.begin(), depthScratchArray.end(), RandomShuffleFunc);
            for(uint32 k = 0; k < clustersPerTile; ++k)
            {
                shuffleDensity[clusterCounter] = densityScratchArray[k];
                shuffleDepth[clusterCounter] = depthScratchArray[k];
                clusterCounter++;
            }
        }
        
        DVASSERT(clusterCounter == maxTotalClusters);
        
        AABBox3 clusterBBox;
        for(uint32 clusterVertexIndex = 0; clusterVertexIndex < clusterVertexCount; ++clusterVertexIndex)
        {
            clusterBBox.AddPoint(clusterVertices[clusterVertexIndex]);
        }
        
        float32 clusterVisualSize = cellData.geometryScale.x * (clusterBBox.max.x - clusterBBox.min.x);
        uint32 clustersInRow = (uint32)(unitSize.x / clusterVisualSize);
        if(clustersInRow <= 0)
        {
            clustersInRow = 1;
        }
        
        for(size_t clusterIndex = 0; clusterIndex < maxTotalClusters; ++clusterIndex)
        {
            uint32 clusterIndexX = clusterIndex % maxClusterRowSize;
            uint32 clusterIndexY = clusterIndex / maxClusterRowSize;
            
            uint32 matrixIndex = (clusterIndexX / maxClusters) + tilesPerRow * (clusterIndexY / maxClusters); //0...15
            DVASSERT(matrixIndex >= 0 && matrixIndex < (tilesPerRow * tilesPerRow));
            
            uint32 matrixIndexX = matrixIndex % tilesPerRow;
            uint32 matrixIndexY = matrixIndex / tilesPerRow;
            
            Vector2 matrixCellStart(unitSize.x * matrixIndexX, unitSize.y * matrixIndexY);
            
            float32 randomOffsetX = clusterVisualSize * (clusterIndex % clustersInRow) + clusterVisualSize * (0.5f - (float32)Random::Instance()->RandFloat());//unitSize.x * Random::Instance()->RandFloat();
            float32 randomOffsetY = atomicOffsetY * shuffleDepth[clusterIndex]; //unitSize.y * Random::Instance()->RandFloat();
            
            Vector3 clusterCenter(matrixCellStart.x + randomOffsetX, matrixCellStart.y + randomOffsetY, 0.0f);
            
            uint32 densityId = shuffleDensity[clusterIndex];
            
            for(uint32 clusterVertexIndex = 0; clusterVertexIndex < clusterVertexCount; ++clusterVertexIndex)
            {
                DVASSERT(vertexIndex < vertexData.size());
                VegetationVertex& vertex = vertexData[vertexIndex];
                
                vertex.coord.x = clusterCenter.x + clusterVertices[clusterVertexIndex].x * cellData.geometryScale.x;
                vertex.coord.y = clusterCenter.y + clusterVertices[clusterVertexIndex].y * cellData.geometryScale.x;
                vertex.coord.z = clusterCenter.z + clusterVertices[clusterVertexIndex].z * cellData.geometryScale.y;
                
                vertex.normal = clusterNormals[clusterVertexIndex];
                
                vertex.binormal = clusterCenter;
                
                vertex.tangent.y = (float32)layerIndex;
                vertex.tangent.z = (float32)densityId;
                
                vertex.texCoord0.x = cellData.coords[clusterVertexIndex % MAX_CELL_TEXTURE_COORDS].x;
                vertex.texCoord0.y = cellData.coords[clusterVertexIndex % MAX_CELL_TEXTURE_COORDS].y;
                
                vertexIndex++;
            }
        }
    }
}
예제 #3
0
void ImposterNode::UpdateState()
{
	if(GetChildrenCount() > 0)
	{
		DVASSERT(GetChildrenCount() == 1);
		AABBox3 bbox = GetChild(0)->GetWTMaximumBoundingBoxSlow();
		Vector3 bboxCenter = bbox.GetCenter();
		float32 distanceSquare = (scene->GetCurrentCamera()->GetPosition() - bboxCenter).SquareLength();
		distanceSquare *= scene->GetCurrentCamera()->GetZoomFactor() * scene->GetCurrentCamera()->GetZoomFactor();
		
		Vector3 newDirection = scene->GetCurrentCamera()->GetPosition()-center;
		newDirection.Normalize();
		float32 dotProduct = newDirection.DotProduct(direction);

		switch(state)
		{
		case STATE_3D:
		{
			if(distanceSquare > TOGGLE_SQUARE_DISTANCE)
			{
				UpdatePriority(distanceSquare, 0);
				AskForRedraw();
			}
			else
			{
				isReady = false;
			}
		}
		break;

		case STATE_QUEUED:
		{
			if(IsAngleOrRangeChangedEnough(distanceSquare, dotProduct))
			{
				UpdatePriority(distanceSquare, dotProduct);
				manager->UpdateQueue(this);
			}
		}
		break;

		case STATE_IMPOSTER:
		{
			if(distanceSquare < TOGGLE_SQUARE_DISTANCE)
			{
				isReady = false;
				state = STATE_3D;
				manager->RemoveFromQueue(this);
				break;
			}

			if(IsAngleOrRangeChangedEnough(distanceSquare, dotProduct))
			{
				UpdatePriority(distanceSquare, dotProduct);
				AskForRedraw();
			}
		}
		break;

		case STATE_REDRAW_APPROVED:
		{
		}
		break;
		}
	}
}
예제 #4
0
void ImposterNode::UpdateImposter()
{
	Camera * camera = scene->GetCurrentCamera();

	Camera * imposterCamera = new Camera();
	Vector3 cameraPos = camera->GetPosition();

	Entity * child = GetChild(0);
	AABBox3 bbox = child->GetWTMaximumBoundingBoxSlow();
	Vector3 bboxCenter = bbox.GetCenter();

	imposterCamera->SetupPerspective(camera->GetFOV(), camera->GetAspect(), camera->GetZNear(), camera->GetZFar());
	imposterCamera->SetTarget(bbox.GetCenter());
	imposterCamera->SetPosition(cameraPos);
	imposterCamera->SetUp(camera->GetUp());
	imposterCamera->SetLeft(camera->GetLeft());

	Rect viewport = RenderManager::Instance()->GetViewport();
	
	const Matrix4 & mvp = imposterCamera->GetUniformProjModelMatrix();

	AABBox3 screenBounds;
	GetOOBBoxScreenCoords(child, mvp, screenBounds);

	Vector4 pv(bboxCenter);
	pv = pv*mvp;
	pv.z = (pv.z/pv.w + 1.f) * 0.5f;
	float32 bboxCenterZ = pv.z;

	Vector2 screenSize = Vector2(screenBounds.max.x-screenBounds.min.x, screenBounds.max.y-screenBounds.min.y);

	Vector3 screenBillboardVertices[4];
	screenBillboardVertices[0] = Vector3(screenBounds.min.x, screenBounds.min.y, screenBounds.min.z);
	screenBillboardVertices[1] = Vector3(screenBounds.max.x, screenBounds.min.y, screenBounds.min.z);
	screenBillboardVertices[2] = Vector3(screenBounds.min.x, screenBounds.max.y, screenBounds.min.z);
	screenBillboardVertices[3] = Vector3(screenBounds.max.x, screenBounds.max.y, screenBounds.min.z);

	center = Vector3();
	Matrix4 invMvp = mvp;
	invMvp.Inverse();
	for(int32 i = 0; i < 4; ++i)
	{
		//unproject
		Vector4 out;
		out.x = 2.f*(screenBillboardVertices[i].x-viewport.x)/viewport.dx-1.f;
		out.y = 2.f*(screenBillboardVertices[i].y-viewport.y)/viewport.dy-1.f;
		out.z = 2.f*screenBillboardVertices[i].z-1.f;
		out.w = 1.f;

		out = out*invMvp;
		DVASSERT(out.w != 0.f);

		out.x /= out.w;
		out.y /= out.w;
		out.z /= out.w;

		imposterVertices[i] = Vector3(out.x, out.y, out.z);
		center += imposterVertices[i];
	}
	center /= 4.f;


	//draw
	RecreateFbo(screenSize);
	//Logger::Info("%f, %f", screenSize.x, screenSize.y);
	if(!block)
	{
		return;
	}

	direction = camera->GetPosition()-center;
	direction.Normalize();

	distanceSquaredToCamera = (center-cameraPos).SquareLength();

	float32 nearPlane = sqrtf(distanceSquaredToCamera);
	//float32 farPlane = nearPlane + (bbox.max.z-bbox.min.z);
	float32 w = (imposterVertices[1]-imposterVertices[0]).Length();
	float32 h = (imposterVertices[2]-imposterVertices[0]).Length();
	
	//TODO: calculate instead of +50
	imposterCamera->Setup(-w/2.f, w/2.f, -h/2.f, h/2.f, nearPlane, nearPlane+50.f);

	Rect oldViewport = RenderManager::Instance()->GetViewport();
	
	//Texture * target = fbo->GetTexture();

	RenderManager::Instance()->AppendState(RenderState::STATE_SCISSOR_TEST);
	RenderManager::Instance()->State()->SetScissorRect(Rect(block->offset.x, block->offset.y, block->size.dx, block->size.dy));
	RenderManager::Instance()->FlushState();
	//TODO: use one "clear" function instead of two
	//if(block->size.x == 512.f)
	//{
	//	RenderManager::Instance()->ClearWithColor(0.f, .8f, 0.f, 1.f);
	//}
	//else if(block->size.x == 256.f)
	//{
	//	RenderManager::Instance()->ClearWithColor(0.f, .3f, 0.f, 1.f);
	//}
	//else if(block->size.x == 128.f)
	//{
	//	RenderManager::Instance()->ClearWithColor(.3f, .3f, 0.f, 1.f);
	//}
	//else
	//{
	//	RenderManager::Instance()->ClearWithColor(.3f, 0.f, 0.f, 1.f);
	//}
    
	RenderManager::Instance()->ClearWithColor(.0f, .0f, 0.f, .0f);
	RenderManager::Instance()->ClearDepthBuffer();
	RenderManager::Instance()->RemoveState(RenderState::STATE_SCISSOR_TEST);

	RenderManager::Instance()->SetViewport(Rect(block->offset.x, block->offset.y, block->size.dx, block->size.dy), true);


	imposterCamera->SetTarget(center);
	imposterCamera->Set();

	//TODO: remove this call
	HierarchicalRemoveCull(child);
	RenderManager::Instance()->FlushState();
	child->Draw();

	RenderManager::Instance()->SetViewport(oldViewport, true);

	isReady = true;
	state = STATE_IMPOSTER;

	//unproject
	screenBillboardVertices[0] = Vector3(screenBounds.min.x, screenBounds.min.y, bboxCenterZ);
	screenBillboardVertices[1] = Vector3(screenBounds.max.x, screenBounds.min.y, bboxCenterZ);
	screenBillboardVertices[2] = Vector3(screenBounds.min.x, screenBounds.max.y, bboxCenterZ);
	screenBillboardVertices[3] = Vector3(screenBounds.max.x, screenBounds.max.y, bboxCenterZ);
	for(int32 i = 0; i < 4; ++i)
	{
		//unproject
		Vector4 out;
		out.x = 2.f*(screenBillboardVertices[i].x-viewport.x)/viewport.dx-1.f;
		out.y = 2.f*(screenBillboardVertices[i].y-viewport.y)/viewport.dy-1.f;
		out.z = 2.f*screenBillboardVertices[i].z-1.f;
		out.w = 1.f;

		out = out*invMvp;
		DVASSERT(out.w != 0.f);

		out.x /= out.w;
		out.y /= out.w;
		out.z /= out.w;

		imposterVertices[i] = Vector3(out.x, out.y, out.z);
	}

	SafeRelease(imposterCamera);

	ClearGeometry();
	CreateGeometry();
}
void LandscapePropertyControl::ReadFrom(SceneNode * sceneNode)
{
	NodesPropertyControl::ReadFrom(sceneNode);

	LandscapeNode *landscape = GetLandscape();
	if (!landscape)
		return;

    propertyList->AddSection("property.landscape.landscape", GetHeaderState("property.landscape.landscape", true));
    
    propertyList->AddFloatProperty("property.landscape.size", PropertyList::PROPERTY_IS_EDITABLE);
    propertyList->AddFloatProperty("property.landscape.height", PropertyList::PROPERTY_IS_EDITABLE); 
    Vector3 size(445.0f, 445.0f, 50.f);
    AABBox3 bbox = landscape->GetBoundingBox();
    AABBox3 emptyBox;
    if((emptyBox.min != bbox.min) && (emptyBox.max != bbox.max))
    {
        AABBox3 transformedBox;
        bbox.GetTransformedBox(*landscape->GetWorldTransformPtr(), transformedBox);
        size = transformedBox.max - transformedBox.min;
    }
    propertyList->SetFloatPropertyValue("property.landscape.size", size.x);
    propertyList->SetFloatPropertyValue("property.landscape.height", size.z);

    propertyList->AddComboProperty("property.landscape.tilemode", tiledModes);
    propertyList->SetComboPropertyIndex("property.landscape.tilemode", landscape->GetTiledShaderMode());

    propertyList->AddFilepathProperty("property.landscape.heightmap", ".png;.heightmap", false, PropertyList::PROPERTY_IS_EDITABLE);
    propertyList->SetFilepathPropertyValue("property.landscape.heightmap", landscape->GetHeightmapPathname());
    
    
    propertyList->AddSubsection("property.landscape.subsection.textures");
    AddFilepathProperty(String("property.landscape.texture.color"), TextureDescriptor::GetSupportedTextureExtensions(), LandscapeNode::TEXTURE_COLOR);
    AddFilepathProperty(String("property.landscape.texture.tile0"), TextureDescriptor::GetSupportedTextureExtensions(), LandscapeNode::TEXTURE_TILE0);
    AddFilepathProperty(String("property.landscape.texture.tile1"), TextureDescriptor::GetSupportedTextureExtensions(), LandscapeNode::TEXTURE_TILE1);
    AddFilepathProperty(String("property.landscape.texture.tile2"), TextureDescriptor::GetSupportedTextureExtensions(), LandscapeNode::TEXTURE_TILE2);
    AddFilepathProperty(String("property.landscape.texture.tile3"), TextureDescriptor::GetSupportedTextureExtensions(), LandscapeNode::TEXTURE_TILE3);
    AddFilepathProperty(String("property.landscape.texture.tilemask"), TextureDescriptor::GetSupportedTextureExtensions(), LandscapeNode::TEXTURE_TILE_MASK);
    AddFilepathProperty(String("property.landscape.texture.tiledtexture"), TextureDescriptor::GetSupportedTextureExtensions(), LandscapeNode::TEXTURE_TILE_FULL);

    propertyList->AddColorProperty("property.landscape.texture.tilecolor0");
    propertyList->SetColorPropertyValue("property.landscape.texture.tilecolor0", landscape->GetTileColor(LandscapeNode::TEXTURE_TILE0));
    
    propertyList->AddColorProperty("property.landscape.texture.tilecolor1");
    propertyList->SetColorPropertyValue("property.landscape.texture.tilecolor1", landscape->GetTileColor(LandscapeNode::TEXTURE_TILE1));
    
    propertyList->AddColorProperty("property.landscape.texture.tilecolor2");
    propertyList->SetColorPropertyValue("property.landscape.texture.tilecolor2", landscape->GetTileColor(LandscapeNode::TEXTURE_TILE2));
    
    propertyList->AddColorProperty("property.landscape.texture.tilecolor3");
    propertyList->SetColorPropertyValue("property.landscape.texture.tilecolor3", landscape->GetTileColor(LandscapeNode::TEXTURE_TILE3));

    propertyList->AddMessageProperty(String("property.landscape.generatefulltiled"),
                                     Message(this, &LandscapePropertyControl::GenerateFullTiledTexture));

    propertyList->AddMessageProperty(String("property.landscape.saveheightmaptopng"),
                                     Message(this, &LandscapePropertyControl::SaveHeightmapToPng));


    propertyList->AddBoolProperty("property.landscape.showgrid", PropertyList::PROPERTY_IS_EDITABLE);
    
    // RETURN TO THIS CODE LATER
    // bool showGrid =  (0 != (landscape->GetDebugFlags() & DebugRenderComponent::DEBUG_DRAW_GRID));
    bool showGrid = false;
    propertyList->SetBoolPropertyValue("property.landscape.showgrid", showGrid);
    

	propertyList->AddIntProperty("lightmap.size");
	propertyList->SetIntPropertyValue("lightmap.size", currentSceneNode->GetCustomProperties()->GetInt32("lightmap.size", 1024));

    propertyList->AddFloatProperty("property.landscape.texture0.tilex");
    propertyList->SetFloatPropertyValue("property.landscape.texture0.tilex", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE0).x);
    propertyList->AddFloatProperty("property.landscape.texture0.tiley");
    propertyList->SetFloatPropertyValue("property.landscape.texture0.tiley", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE0).y);
    
    propertyList->AddFloatProperty("property.landscape.texture1.tilex");
    propertyList->SetFloatPropertyValue("property.landscape.texture1.tilex", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE1).x);
    propertyList->AddFloatProperty("property.landscape.texture1.tiley");
    propertyList->SetFloatPropertyValue("property.landscape.texture1.tiley", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE1).y);

    propertyList->AddFloatProperty("property.landscape.texture2.tilex");
    propertyList->SetFloatPropertyValue("property.landscape.texture2.tilex", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE2).x);
    propertyList->AddFloatProperty("property.landscape.texture2.tiley");
    propertyList->SetFloatPropertyValue("property.landscape.texture2.tiley", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE2).y);
    
    propertyList->AddFloatProperty("property.landscape.texture3.tilex");
    propertyList->SetFloatPropertyValue("property.landscape.texture3.tilex", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE3).x);
    propertyList->AddFloatProperty("property.landscape.texture3.tiley");
    propertyList->SetFloatPropertyValue("property.landscape.texture3.tiley", landscape->GetTextureTiling(LandscapeNode::TEXTURE_TILE3).y);
    
    ControlsFactory::AddFogSubsection(propertyList, landscape->IsFogEnabled(), landscape->GetFogDensity(), landscape->GetFogColor());
}
void LandscapePropertyControl::OnFilepathPropertyChanged(PropertyList *forList, const String &forKey, const String &newValue)
{
	Set<String> errorsLog;
	if("property.landscape.heightmap" == forKey)
	{
		bool isValid = SceneValidator::Instance()->ValidateHeightmapPathname(newValue, errorsLog);
		if(isValid)
		{
			LandscapeNode *landscape = GetLandscape();
			if (!landscape)
				return;

			Vector3 size(
				propertyList->GetFloatPropertyValue("property.landscape.size"),
				propertyList->GetFloatPropertyValue("property.landscape.size"),
				propertyList->GetFloatPropertyValue("property.landscape.height"));
			AABBox3 bbox;
			bbox.AddPoint(Vector3(-size.x/2.f, -size.y/2.f, 0.f));
			bbox.AddPoint(Vector3(size.x/2.f, size.y/2.f, size.z));

			if(newValue.length())
			{
				landscape->BuildLandscapeFromHeightmapImage(newValue, bbox);
			}
		}
	}
	else
	{
		bool isValid = (newValue.empty()) ? true: SceneValidator::Instance()->ValidateTexturePathname(newValue, errorsLog);
		if(isValid)
		{
            String descriptorPathname = String("");
            if(!newValue.empty())
            {
                descriptorPathname = TextureDescriptor::GetDescriptorPathname(newValue);
            }
            
			if("property.landscape.texture.tile0" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE0, descriptorPathname);
			}
			else if("property.landscape.texture.tile1" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE1, descriptorPathname);
			}
			else if("property.landscape.texture.tile2" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE2, descriptorPathname);
			}
			else if("property.landscape.texture.tile3" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE3, descriptorPathname);
			}
			else if("property.landscape.texture.tilemask" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE_MASK, descriptorPathname);
			}
			else if("property.landscape.texture.color" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_COLOR, descriptorPathname);
			}
			else if("property.landscape.texture.tiledtexture" == forKey)
			{
				SetLandscapeTexture(LandscapeNode::TEXTURE_TILE_FULL, descriptorPathname);
			}
		}
	}

	if(0 == errorsLog.size())
	{
		NodesPropertyControl::OnFilepathPropertyChanged(forList, forKey, newValue);
	}
	else
	{
		ShowErrorDialog(errorsLog);
	}
}
void LandscapePropertyControl::OnFloatPropertyChanged(PropertyList *forList, const String &forKey, float newValue)
{
    if("property.landscape.size" == forKey || "property.landscape.height" == forKey)
    {
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector3 size(
						 propertyList->GetFloatPropertyValue("property.landscape.size"),
						 propertyList->GetFloatPropertyValue("property.landscape.size"),
						 propertyList->GetFloatPropertyValue("property.landscape.height"));
			AABBox3 bbox;
			bbox.AddPoint(Vector3(-size.x/2.f, -size.y/2.f, 0.f));
			bbox.AddPoint(Vector3(size.x/2.f, size.y/2.f, size.z));
			
			Set<String> errorsLog;
			String heightMap = propertyList->GetFilepathPropertyValue("property.landscape.heightmap");
			if(SceneValidator::Instance()->ValidateHeightmapPathname(heightMap, errorsLog) && heightMap.length())
			{
				landscape->BuildLandscapeFromHeightmapImage(heightMap, bbox);
			}
        }
    }
    if ("property.landscape.texture0.tilex" == forKey || "property.landscape.texture0.tiley" == forKey)
    {
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture0.tilex"),
						   propertyList->GetFloatPropertyValue("property.landscape.texture0.tiley"));
			landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE0, tiling);
		}
    }
    if ("property.landscape.texture1.tilex" == forKey || "property.landscape.texture1.tiley" == forKey)
    {
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture1.tilex"),
						   propertyList->GetFloatPropertyValue("property.landscape.texture1.tiley"));
			landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE1, tiling);
		}
    }
	if ("property.landscape.texture2.tilex" == forKey || "property.landscape.texture2.tiley" == forKey)
	{
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture2.tilex"),
				propertyList->GetFloatPropertyValue("property.landscape.texture2.tiley"));
			landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE2, tiling);
		}
	}
	if ("property.landscape.texture3.tilex" == forKey || "property.landscape.texture3.tiley" == forKey)
	{
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
		{
			Vector2 tiling(propertyList->GetFloatPropertyValue("property.landscape.texture3.tilex"),
				propertyList->GetFloatPropertyValue("property.landscape.texture3.tiley"));
			landscape->SetTextureTiling(LandscapeNode::TEXTURE_TILE3, tiling);
		}
	}
    
    if ("property.material.dencity" == forKey)
    {
		LandscapeNode *landscape = GetLandscape();
		if (landscape)
			landscape->SetFogDensity(newValue);
    }

    NodesPropertyControl::OnFloatPropertyChanged(forList, forKey, newValue);
}