protected override bool OnMouseDown(Viewport viewport, EMouseButtons button) { if (button == EMouseButtons.Left) { if (GetToolPosition(viewport, out var terrain, out toolModifyStartPosition)) { var layer = DocumentWindow.TerrainPaintLayersGetSelected(); if (IsCurrentPaintTool() && layer != null) { if (layer.Mask.Value != null && layer.Mask.Value.Length != 0) { if (layer.Mask.Value.Length != terrain.GetPaintMaskSizeInteger() * terrain.GetPaintMaskSizeInteger()) { EditorMessageBox.ShowWarning(EditorLocalization.Translate("Terrain", "Unable to paint to selected layer because Mask size of the layer and MaskSize of the terrain are not equal.")); return(true); } } } if (mode == ModeEnum.PaintFlatten) { if (layer != null) { Vector2I maskIndex = terrain.GetMaskIndexByPosition(toolModifyStartPosition.ToVector2()); toolModifyStartMaskValue = layer.GetMaskValue(maskIndex); } } toolModify = true; return(true); } } return(false); }
protected virtual void ToolPutTickPaint(Viewport viewport, double delta) { if (!GetToolPosition(viewport, out var selectedTerrain, out var position)) { return; } var layer = DocumentWindow.TerrainPaintLayersGetSelected(); if (layer == null) { return; } var toolRadius = (float)Component_Scene_DocumentWindow.TerrainToolRadius; var toolHardness = (float)Component_Scene_DocumentWindow.TerrainToolHardness; var toolShapeType = Component_Scene_DocumentWindow.TerrainToolShape; float strength = (float)(delta * Component_Scene_DocumentWindow.TerrainToolStrength * toolRadius * 0.5 * 2.0); Vector2 positionMin = position.ToVector2() - new Vector2(toolRadius, toolRadius); Vector2 positionMax = position.ToVector2() + new Vector2(toolRadius, toolRadius); List <Component_Terrain> terrains; //!!!! //if( selectedTerrain.HeightmapTerrainManager != null && HeightmapTerrainManager.Instance != null ) //{ // terrains = HeightmapTerrainManager.Instance.GetTerrainsByArea( positionMin, positionMax, true ); //} //else //{ terrains = new List <Component_Terrain>(); terrains.Add(selectedTerrain); //} foreach (var terrain in terrains) { UndoActionPropertiesChange undoSetPropertyAction = paintSetPropertyUndoActions.Find(a => a.Items[0].Obj == layer); var undoChangeAction = paintChangeUndoActions.Find(a => a.Terrain == terrain); Vector2I indexMin = terrain.GetMaskIndexByPosition(positionMin); Vector2I indexMax = terrain.GetMaskIndexByPosition(positionMax) + new Vector2I(1, 1); terrain.ClampMaskIndex(ref indexMin); terrain.ClampMaskIndex(ref indexMax); for (int y = indexMin.Y; y <= indexMax.Y; y++) { for (int x = indexMin.X; x <= indexMax.X; x++) { Vector2 point = terrain.GetPositionXYByMaskIndex(new Vector2I(x, y)); float coef; { double length; if (toolShapeType == ToolShape.Circle) { length = (point - position.ToVector2()).Length(); } else { length = Math.Max(Math.Abs(point.X - position.X), Math.Abs(point.Y - position.Y)); } if (length >= toolRadius) { coef = 0; } else if (length == 0) { coef = 1; } else if (length <= toolHardness * toolRadius) { coef = 1; } else { double c; if (toolRadius - toolRadius * toolHardness != 0) { c = (length - toolRadius * toolHardness) / (toolRadius - toolRadius * toolHardness); } else { c = 0; } coef = (float)Math.Cos(Math.PI / 2 * c); } } if (coef != 0) { float oldValue = layer.GetMaskValue(new Vector2I(x, y)); float value = oldValue; //near corner (x == 0 or y == 0) take value from near terrain. bool takeValueFromNearTerrain = false; //!!!! //if( selectedTerrain.HeightmapTerrainManager != null && HeightmapTerrainManager.Instance != null ) //{ // if( x == 0 ) // { // HeightmapTerrain terrain2 = // FindTerrainWithIndex( terrains, terrain.HeightmapTerrainManagerIndex - new Vector2I( 1, 0 ) ); // if( terrain2 != null ) // { // value = terrain2.GetHeight( terrain.GetPositionXY( new Vector2I( x, y ) ), false ) + terrain2.Position.Z; // value -= terrain.Position.Z; // takeValueFromNearTerrain = true; // } // } // else if( y == 0 ) // { // HeightmapTerrain terrain2 = // FindTerrainWithIndex( terrains, terrain.HeightmapTerrainManagerIndex - new Vector2I( 0, 1 ) ); // if( terrain2 != null ) // { // value = terrain2.GetHeight( terrain.GetPositionXY( new Vector2I( x, y ) ), false ) + terrain2.Position.Z; // value -= terrain.Position.Z; // takeValueFromNearTerrain = true; // } // } //} if (!takeValueFromNearTerrain) { switch (mode) { case ModeEnum.PaintPaint: case ModeEnum.PaintClear: { bool paint = mode == ModeEnum.PaintPaint; if ((Form.ModifierKeys & Keys.Shift) != 0) { paint = !paint; } if (paint) { value = oldValue + strength * coef; } else { value = oldValue - strength * coef; } } break; case ModeEnum.PaintSmooth: { float needValue = 0; { needValue += layer.GetMaskValue(new Vector2I(x - 1, y)); needValue += layer.GetMaskValue(new Vector2I(x + 1, y)); needValue += layer.GetMaskValue(new Vector2I(x, y - 1)); needValue += layer.GetMaskValue(new Vector2I(x, y + 1)); //needValue += layer.GetMaskValue( GetClampedMaskIndex( terrain, new Vec2I( x - 1, y ) ) ); //needValue += layer.GetMaskValue( GetClampedMaskIndex( terrain, new Vec2I( x + 1, y ) ) ); //needValue += layer.GetMaskValue( GetClampedMaskIndex( terrain, new Vec2I( x, y - 1 ) ) ); //needValue += layer.GetMaskValue( GetClampedMaskIndex( terrain, new Vec2I( x, y + 1 ) ) ); needValue /= 4; } if (oldValue < needValue) { value = oldValue + strength * coef; if (value > needValue) { value = needValue; } } else if (oldValue > needValue) { value = oldValue - strength * coef; if (value < needValue) { value = needValue; } } } break; case ModeEnum.PaintFlatten: { float needValue = toolModifyStartMaskValue; if (oldValue < needValue) { value = oldValue + strength * coef; if (value > needValue) { value = needValue; } } else if (oldValue > needValue) { value = oldValue - strength * coef; if (value < needValue) { value = needValue; } } } break; } } MathEx.Clamp(ref value, 0, 1); if (oldValue != value) { //undo if (layer.Mask.Value == null || layer.Mask.Value.Length == 0 || undoSetPropertyAction != null) { if (undoSetPropertyAction == null) { var oldValue2 = layer.Mask; layer.Mask = new byte[terrain.GetPaintMaskSizeInteger() * terrain.GetPaintMaskSizeInteger()]; var property = (Metadata.Property)layer.MetadataGetMemberBySignature("property:Mask"); var undoItem = new UndoActionPropertiesChange.Item(layer, property, oldValue2); undoSetPropertyAction = new UndoActionPropertiesChange(undoItem); paintSetPropertyUndoActions.Add(undoSetPropertyAction); } } else { if (undoChangeAction == null) { undoChangeAction = new Component_Terrain_PaintChangeUndoAction(terrain); paintChangeUndoActions.Add(undoChangeAction); } undoChangeAction.SaveValue(layer, new Vector2I(x, y), oldValue); } //update terrain layer.SetMaskValue(new Vector2I(x, y), value); } } } } //!!!!use mask indexes //var updateRectangle = new RectangleI( indexMin, indexMax ); //terrain.UpdateRenderingData( updateRectangle, false ); //bool foundItemForTerrain = false; //foreach( var updateItem in needUpdateRectangle ) //{ // if( updateItem.Terrain == terrain ) // { // updateItem.Rectangle.Add( updateRectangle ); // foundItemForTerrain = true; // break; // } //} //if( !foundItemForTerrain ) //{ // NeedUpdateRectangleItem item = new NeedUpdateRectangleItem(); // item.Terrain = terrain; // item.Rectangle = updateRectangle; // needUpdateRectangle.Add( item ); //} } }