public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { commonUI.OnSceneGUI2D(terrain, editContext); if (!editContext.hitValidTerrain && !commonUI.isInUse) { return; } // update brush UI group commonUI.OnSceneGUI(terrain, editContext); if (Event.current.type != EventType.Repaint) { return; } if (commonUI.isRaycastHitUnderCursorValid) { using (IBrushRenderPreviewUnderCursor brushRender = new BrushRenderPreviewUIGroupUnderCursor(commonUI, "PaintHoles", editContext.brushTexture)) { if (brushRender.CalculateBrushTransform(out BrushTransform brushXform)) { PaintContext paintContext = brushRender.AcquireHeightmap(false, brushXform.GetBrushXYBounds(), 1); Material previewMaterial = Utility.GetDefaultPreviewMaterial(); var texelCtx = Utility.CollectTexelValidity(paintContext.originTerrain, brushXform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(paintContext, texelCtx, brushXform, previewMaterial); TerrainPaintUtilityEditor.DrawBrushPreview(paintContext, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 0); texelCtx.Cleanup(); } } } }
public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { commonUI.OnSceneGUI2D(terrain, editContext); if (!editContext.hitValidTerrain && !commonUI.isInUse) { return; } commonUI.OnSceneGUI(terrain, editContext); Event evt = Event.current; if (evt.control && (evt.type == EventType.ScrollWheel)) { const float k_mouseWheelToHeightRatio = -0.004f; stampToolProperties.stampHeight += Event.current.delta.y * k_mouseWheelToHeightRatio * editContext.raycastHit.distance; evt.Use(); editContext.Repaint(); SaveSetting(); } // We're only doing painting operations, early out if it's not a repaint if (evt.type != EventType.Repaint) { return; } if (commonUI.isRaycastHitUnderCursorValid) { Texture brushTexture = editContext.brushTexture; using (IBrushRenderPreviewUnderCursor brushRender = new BrushRenderPreviewUIGroupUnderCursor(commonUI, "Stamp", brushTexture)) { if (brushRender.CalculateBrushTransform(out BrushTransform brushXform)) { PaintContext paintContext = brushRender.AcquireHeightmap(false, brushXform.GetBrushXYBounds(), 1); Material previewMaterial = Utility.GetDefaultPreviewMaterial(); var texelCtx = Utility.CollectTexelValidity(paintContext.originTerrain, brushXform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(paintContext, texelCtx, brushXform, previewMaterial); TerrainPaintUtilityEditor.DrawBrushPreview(paintContext, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 0); // draw result preview { ApplyBrushInternal(brushRender, paintContext, commonUI.brushStrength, brushTexture, brushXform, terrain); // restore old render target RenderTexture.active = paintContext.oldRenderTexture; previewMaterial.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture); TerrainPaintUtilityEditor.DrawBrushPreview(paintContext, TerrainBrushPreviewMode.DestinationRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 1); } TerrainPaintUtility.ReleaseContextResources(paintContext); texelCtx.Cleanup(); } } } }
public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { commonUI.OnSceneGUI2D(terrain, editContext); // only do the rest if user mouse hits valid terrain or they are using the // brush parameter hotkeys to resize, etc if (!editContext.hitValidTerrain && !commonUI.isInUse) { return; } // update brush UI group commonUI.OnSceneGUI(terrain, editContext); // dont render preview if this isnt a repaint. losing performance if we do if (Event.current.type != EventType.Repaint) { return; } using (IBrushRenderPreviewUnderCursor brushRender = new BrushRenderPreviewUIGroupUnderCursor(commonUI, "ThermalErosion", editContext.brushTexture)) { if (brushRender.CalculateBrushTransform(out BrushTransform brushXform)) { Material previewMaterial = Utility.GetDefaultPreviewMaterial(); PaintContext ctx = brushRender.AcquireHeightmap(false, brushXform.GetBrushXYBounds(), 1); var texelCtx = Utility.CollectTexelValidity(ctx.originTerrain, brushXform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(ctx, texelCtx, brushXform, previewMaterial); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 0); texelCtx.Cleanup(); } } }
public override void OnRenderBrushPreview(Terrain terrain, IOnSceneGUI editContext) { // We're only doing painting operations, early out if it's not a repaint if (Event.current.type != EventType.Repaint) { return; } if (editContext.hitValidTerrain) { BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); PaintContext paintContext = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); Material material = TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(); TerrainPaintUtilityEditor.DrawBrushPreview( paintContext, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, material, 0); // draw result preview { ApplyBrushInternal(paintContext, editContext.brushStrength, editContext.brushTexture, brushXform); // restore old render target RenderTexture.active = paintContext.oldRenderTexture; material.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture); TerrainPaintUtilityEditor.DrawBrushPreview( paintContext, TerrainBrushPreviewMode.DestinationRenderTexture, editContext.brushTexture, brushXform, material, 1); } TerrainPaintUtility.ReleaseContextResources(paintContext); } }
private void RemoveTrees(Terrain terrain, IOnPaint editContext, bool clearSelectedOnly) { PaintTreesDetailsContext ctx = PaintTreesDetailsContext.Create(terrain, editContext.uv); for (int i = 0; i < ctx.neighborTerrains.Length; ++i) { Terrain ctxTerrain = ctx.neighborTerrains[i]; if (ctxTerrain != null) { Vector2 ctxUV = ctx.neighborUvs[i]; float radius = 0.5f * brushSize / ctxTerrain.terrainData.size.x; int treePrototype = kInvalidTree; if (clearSelectedOnly && selectedTree != kInvalidTree) { treePrototype = PaintTreesUtils.FindTreePrototype(ctxTerrain, m_TargetTerrain, selectedTree); } if (!clearSelectedOnly || treePrototype != kInvalidTree) { TerrainPaintUtilityEditor.UpdateTerrainDataUndo(ctxTerrain.terrainData, "Terrain - Remove Trees"); ctxTerrain.RemoveTrees(ctxUV, radius, treePrototype); } } } }
public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { commonUI.OnSceneGUI2D(terrain, editContext); // only do the rest if user mouse hits valid terrain or they are using the // brush parameter hotkeys to resize, etc if (!editContext.hitValidTerrain && !commonUI.isInUse) { return; } // update brush UI group commonUI.OnSceneGUI(terrain, editContext); // dont render preview if this isnt a repaint. losing performance if we do if (Event.current.type != EventType.Repaint) { return; } if (commonUI.isRaycastHitUnderCursorValid) { Texture brushTexture = editContext.brushTexture; using (IBrushRenderPreviewUnderCursor brushRender = new BrushRenderPreviewUIGroupUnderCursor(commonUI, "Twist", editContext.brushTexture)) { //draw brush circle if (brushRender.CalculateBrushTransform(out BrushTransform brushXform)) { PaintContext ctx = brushRender.AcquireHeightmap(false, brushXform.GetBrushXYBounds(), 1); Material previewMaterial = Utility.GetDefaultPreviewMaterial(); var texelCtx = Utility.CollectTexelValidity(ctx.originTerrain, brushXform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(ctx, texelCtx, brushXform, previewMaterial); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 0); // draw result preview { float finalTwistAmount = m_TwistAmount * -0.002f; //scale to a reasonable value and negate so default mode is clockwise if (Event.current.shift) { finalTwistAmount *= -1.0f; } ApplyBrushInternal(brushRender, ctx, commonUI.brushStrength, finalTwistAmount, brushTexture, brushXform); // restore old render target RenderTexture.active = ctx.oldRenderTexture; previewMaterial.SetTexture("_HeightmapOrig", ctx.sourceRenderTexture); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.DestinationRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 1); } texelCtx.Cleanup(); } } } }
public override void OnRenderBrushPreview(Terrain terrain, IOnSceneGUI editContext) { if (m_MouseOnPatchIndex == -1 && editContext.hitValidTerrain && Event.current.type == EventType.Repaint) { BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(), 0); TerrainPaintUtility.ReleaseContextResources(ctx); } }
public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { commonUI.OnSceneGUI2D(terrain, editContext); // only do the rest if user mouse hits valid terrain or they are using the // brush parameter hotkeys to resize, etc if (!editContext.hitValidTerrain && !commonUI.isInUse) { return; } // update brush UI group commonUI.OnSceneGUI(terrain, editContext); // dont render preview if this isnt a repaint. losing performance if we do if (Event.current.type != EventType.Repaint) { return; } using (IBrushRenderPreviewUnderCursor brushPreview = new BrushRenderPreviewUIGroupUnderCursor(commonUI, "NoiseHeightTool", editContext.brushTexture)) { float brushSize = commonUI.brushSize; float brushStrength = Event.current.control ? -commonUI.brushStrength : commonUI.brushStrength; Vector3 brushPosWS = commonUI.raycastHitUnderCursor.point; brushPreview.CalculateBrushTransform(out var brushXform); PaintContext ctx = brushPreview.AcquireHeightmap(false, brushXform.GetBrushXYBounds(), 1); Material previewMaterial = Utility.GetDefaultPreviewMaterial(); var texelCtx = Utility.CollectTexelValidity(ctx.originTerrain, brushXform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(ctx, texelCtx, brushXform, previewMaterial); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 0); ApplyBrushInternal(terrain, ctx, brushXform, brushPosWS, commonUI.brushRotation, brushStrength, brushSize, editContext.brushTexture); TerrainPaintUtility.SetupTerrainToolMaterialProperties(ctx, brushXform, previewMaterial); // restore old render target RenderTexture.active = ctx.oldRenderTexture; previewMaterial.SetTexture("_HeightmapOrig", ctx.sourceRenderTexture); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.DestinationRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 1); texelCtx.Cleanup(); TerrainPaintUtility.ReleaseContextResources(ctx); } }
public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { commonUI.OnSceneGUI2D(terrain, editContext); // only do the rest if user mouse hits valid terrain or they are using the // brush parameter hotkeys to resize, etc if (!editContext.hitValidTerrain && !commonUI.isInUse) { return; } // update brush UI group commonUI.OnSceneGUI(terrain, editContext); // dont render preview if this isnt a repaint. losing performance if we do if (Event.current.type != EventType.Repaint) { return; } if (commonUI.isRaycastHitUnderCursorValid) { using (IBrushRenderPreviewUnderCursor brushRender = new BrushRenderPreviewUIGroupUnderCursor(commonUI, "PaintHeight", editContext.brushTexture)) { if (brushRender.CalculateBrushTransform(out BrushTransform brushXform)) { PaintContext paintContext = brushRender.AcquireHeightmap(false, brushXform.GetBrushXYBounds(), 1); Material previewMaterial = Utility.GetDefaultPreviewMaterial(); var texelCtx = Utility.CollectTexelValidity(paintContext.originTerrain, brushXform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(paintContext, texelCtx, brushXform, previewMaterial); TerrainPaintUtilityEditor.DrawBrushPreview(paintContext, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 0); // draw result preview { float s = Event.current.control ? -commonUI.brushStrength : commonUI.brushStrength; ApplyBrushInternal(terrain, brushRender, paintContext, s, editContext.brushTexture, brushXform); // restore old render target RenderTexture.active = paintContext.oldRenderTexture; previewMaterial.SetTexture("_HeightmapOrig", paintContext.sourceRenderTexture); TerrainPaintUtilityEditor.DrawBrushPreview(paintContext, TerrainBrushPreviewMode.DestinationRenderTexture, editContext.brushTexture, brushXform, previewMaterial, 1); texelCtx.Cleanup(); } } } } }
private void DrawBrushPreviews(Terrain terrain, IOnSceneGUI editContext) { Vector2 sampleUV; BrushTransform sampleXform; PaintContext sampleContext = null; Material previewMat = Utility.GetDefaultPreviewMaterial(); // draw sample location brush and create context data to be used when drawing target brush previews if (m_SampleLocation.terrain != null) { sampleUV = TerrainUVFromBrushLocation(m_SampleLocation.terrain, m_SampleLocation.pos); sampleXform = TerrainPaintUtility.CalculateBrushTransform(m_SampleLocation.terrain, sampleUV, commonUI.brushSize, commonUI.brushRotation); sampleContext = TerrainPaintUtility.BeginPaintHeightmap(m_SampleLocation.terrain, sampleXform.GetBrushXYBounds()); var texelCtx = Utility.CollectTexelValidity(sampleContext.originTerrain, sampleXform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(sampleContext, texelCtx, sampleXform, previewMat); TerrainPaintUtilityEditor.DrawBrushPreview(sampleContext, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, sampleXform, previewMat, 0); texelCtx.Cleanup(); } // draw brush preview and mesh preview for current mouse position if (commonUI.isRaycastHitUnderCursorValid) { BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, commonUI.raycastHitUnderCursor.textureCoord, commonUI.brushSize, commonUI.brushRotation); PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); var texelCtx = Utility.CollectTexelValidity(ctx.originTerrain, brushXform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(ctx, texelCtx, brushXform, previewMat); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, previewMat, 0); if (sampleContext != null && cloneToolProperties.m_PaintHeightmap) { ApplyHeightmap(sampleContext, ctx, brushXform, terrain, editContext.brushTexture, commonUI.brushStrength); RenderTexture.active = ctx.oldRenderTexture; previewMat.SetTexture("_HeightmapOrig", ctx.sourceRenderTexture); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.DestinationRenderTexture, editContext.brushTexture, brushXform, previewMat, 1); } // Restores RenderTexture.active ctx.Cleanup(); texelCtx.Cleanup(); } // Restores RenderTexture.active sampleContext?.Cleanup(); }
public override void OnRenderBrushPreview(Terrain terrain, IOnSceneGUI editContext) { // We're only doing painting operations, early out if it's not a repaint if (Event.current.type != EventType.Repaint) { return; } if (editContext.hitValidTerrain) { BrushTransform brushXform = TerrainPaintUtility.CalculateBrushTransform(terrain, editContext.raycastHit.textureCoord, editContext.brushSize, 0.0f); PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(terrain, brushXform.GetBrushXYBounds(), 1); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushXform, TerrainPaintUtilityEditor.GetDefaultBrushPreviewMaterial(), 0); TerrainPaintUtility.ReleaseContextResources(ctx); } }
public void RenderBrushPreview(PaintContext paintContext, TerrainBrushPreviewMode previewTexture, BrushTransform brushTransform, Material material, int pass) { TerrainPaintUtilityEditor.DrawBrushPreview(paintContext, previewTexture, brushTexture, brushTransform, material, pass); }
private void PlaceTrees(Terrain terrain, IOnPaint editContext) { if (m_TargetTerrain == null || selectedTree == kInvalidTree || selectedTree >= m_TargetTerrain.terrainData.treePrototypes.Length) { return; } PaintTreesDetailsContext ctx = PaintTreesDetailsContext.Create(terrain, editContext.uv); int placedTreeCount = 0; int treePrototype = PaintTreesUtils.FindTreePrototype(terrain, m_TargetTerrain, selectedTree); if (treePrototype == kInvalidTree) { treePrototype = PaintTreesUtils.CopyTreePrototype(terrain, m_TargetTerrain, selectedTree); } if (PaintTreesUtils.ValidateTreePrototype(terrain, treePrototype)) { // When painting single tree // And just clicking we always place it, so you can do overlapping trees Vector3 position = new Vector3(editContext.uv.x, 0, editContext.uv.y); bool checkTreeDistance = Event.current.type == EventType.MouseDrag || brushSize > 1; if (!checkTreeDistance || TerrainInspectorUtil.CheckTreeDistance(terrain.terrainData, position, treePrototype, spacing)) { TerrainPaintUtilityEditor.UpdateTerrainDataUndo(terrain.terrainData, "Terrain - Place Trees"); var instanceHeight = GetTreeHeight(); PaintTreesUtils.PlaceTree(terrain, treePrototype, position, GetTreeColor(), instanceHeight, GetTreeWidth(instanceHeight), GetTreeRotation()); ++placedTreeCount; } } for (int i = 0; i < ctx.neighborTerrains.Length; ++i) { Terrain ctxTerrain = ctx.neighborTerrains[i]; if (ctxTerrain != null) { Vector2 ctxUV = ctx.neighborUvs[i]; treePrototype = PaintTreesUtils.FindTreePrototype(ctxTerrain, m_TargetTerrain, selectedTree); if (treePrototype == kInvalidTree) { treePrototype = PaintTreesUtils.CopyTreePrototype(ctxTerrain, m_TargetTerrain, selectedTree); } if (PaintTreesUtils.ValidateTreePrototype(ctxTerrain, treePrototype)) { Vector3 size = TerrainInspectorUtil.GetPrototypeExtent(ctxTerrain.terrainData, treePrototype); size.y = 0; float treeCountOneAxis = brushSize / (size.magnitude * spacing * .5f); int treeCount = (int)((treeCountOneAxis * treeCountOneAxis) * .5f); treeCount = Mathf.Clamp(treeCount, 0, 100); // Plant a bunch of trees for (int j = ctxTerrain == terrain ? 1 : 0; j < treeCount && placedTreeCount < treeCount; ++j) { Vector2 randomOffset = 0.5f * Random.insideUnitCircle; randomOffset.x *= brushSize / ctxTerrain.terrainData.size.x; randomOffset.y *= brushSize / ctxTerrain.terrainData.size.z; Vector3 position = new Vector3(ctxUV.x + randomOffset.x, 0, ctxUV.y + randomOffset.y); if (position.x >= 0 && position.x <= 1 && position.z >= 0 && position.z <= 1 && TerrainInspectorUtil.CheckTreeDistance(ctxTerrain.terrainData, position, treePrototype, spacing * .5f)) { TerrainPaintUtilityEditor.UpdateTerrainDataUndo(ctxTerrain.terrainData, "Terrain - Place Trees"); var instanceHeight = GetTreeHeight(); PaintTreesUtils.PlaceTree(ctxTerrain, treePrototype, position, GetTreeColor(), instanceHeight, GetTreeWidth(instanceHeight), GetTreeRotation()); ++placedTreeCount; } } } } } }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { if (m_TargetTerrain == null || selectedDetail == kInvalidDetail || selectedDetail >= m_TargetTerrain.terrainData.detailPrototypes.Length) { return(false); } Texture2D brush = editContext.brushTexture as Texture2D; if (brush == null) { Debug.LogError("Brush texture is not a Texture2D."); return(false); } if (m_BrushRep == null) { m_BrushRep = new BrushRep(); } PaintTreesDetailsContext ctx = PaintTreesDetailsContext.Create(terrain, editContext.uv); for (int t = 0; t < ctx.terrains.Length; ++t) { Terrain ctxTerrain = ctx.terrains[t]; if (ctxTerrain != null) { int detailPrototype = PaintDetailsUtils.FindDetailPrototype(ctxTerrain, m_TargetTerrain, selectedDetail); if (detailPrototype == kInvalidDetail) { detailPrototype = PaintDetailsUtils.CopyDetailPrototype(ctxTerrain, m_TargetTerrain, selectedDetail); } TerrainData terrainData = ctxTerrain.terrainData; TerrainPaintUtilityEditor.UpdateTerrainDataUndo(terrainData, "Terrain - Detail Edit"); int size = (int)Mathf.Max(1.0f, editContext.brushSize * ((float)terrainData.detailResolution / terrainData.size.x)); m_BrushRep.CreateFromBrush(brush, size); Vector2 ctxUV = ctx.uvs[t]; int xCenter = Mathf.FloorToInt(ctxUV.x * terrainData.detailWidth); int yCenter = Mathf.FloorToInt(ctxUV.y * terrainData.detailHeight); int intRadius = Mathf.RoundToInt(size) / 2; int intFraction = Mathf.RoundToInt(size) % 2; int xmin = xCenter - intRadius; int ymin = yCenter - intRadius; int xmax = xCenter + intRadius + intFraction; int ymax = yCenter + intRadius + intFraction; if (xmin >= terrainData.detailWidth || ymin >= terrainData.detailHeight || xmax <= 0 || ymax <= 0) { continue; } xmin = Mathf.Clamp(xmin, 0, terrainData.detailWidth - 1); ymin = Mathf.Clamp(ymin, 0, terrainData.detailHeight - 1); xmax = Mathf.Clamp(xmax, 0, terrainData.detailWidth); ymax = Mathf.Clamp(ymax, 0, terrainData.detailHeight); int width = xmax - xmin; int height = ymax - ymin; float targetStrength = m_DetailsStrength; if (Event.current.shift || Event.current.control) { targetStrength = -targetStrength; } int[] layers = { detailPrototype }; if (targetStrength < 0.0F && !Event.current.control) { layers = terrainData.GetSupportedLayers(xmin, ymin, width, height); } for (int i = 0; i < layers.Length; i++) { int[,] alphamap = terrainData.GetDetailLayer(xmin, ymin, width, height, layers[i]); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int xBrushOffset = (xmin + x) - (xCenter - intRadius + intFraction); int yBrushOffset = (ymin + y) - (yCenter - intRadius + intFraction); float opa = detailOpacity * m_BrushRep.GetStrengthInt(xBrushOffset, yBrushOffset); float targetValue = Mathf.Lerp(alphamap[y, x], targetStrength * terrainData.maxDetailScatterPerRes, opa); alphamap[y, x] = Mathf.Min(Mathf.RoundToInt(targetValue - .5f + Random.value), terrainData.maxDetailScatterPerRes); } } terrainData.SetDetailLayer(xmin, ymin, layers[i], alphamap); } } } return(false); }
public override bool OnPaint(Terrain terrain, IOnPaint editContext) { if (m_TargetTerrain == null || selectedDetail == kInvalidDetail || selectedDetail >= m_TargetTerrain.terrainData.detailPrototypes.Length) { return(false); } Texture2D brush = editContext.brushTexture as Texture2D; if (brush == null) { Debug.LogError("Brush texture is not a Texture2D."); return(false); } if (m_BrushRep == null) { m_BrushRep = new DetailBrushRepresentation(); } PaintTreesDetailsContext ctx = PaintTreesDetailsContext.Create(terrain, editContext.uv); for (int t = 0; t < ctx.neighborTerrains.Length; ++t) { Terrain ctxTerrain = ctx.neighborTerrains[t]; if (ctxTerrain != null) { int detailPrototype = PaintDetailsToolUtility.FindDetailPrototype(ctxTerrain, m_TargetTerrain, selectedDetail); if (detailPrototype == kInvalidDetail) { detailPrototype = PaintDetailsToolUtility.CopyDetailPrototype(ctxTerrain, m_TargetTerrain, selectedDetail); } TerrainData terrainData = ctxTerrain.terrainData; TerrainPaintUtilityEditor.UpdateTerrainDataUndo(terrainData, "Terrain - Detail Edit"); int size = (int)Mathf.Max(1.0f, editContext.brushSize * ((float)terrainData.detailResolution / terrainData.size.x)); m_BrushRep.Update(brush, size); float targetStrength = m_DetailsStrength; if (Event.current.shift || Event.current.control) { targetStrength = -targetStrength; } DetailBrushBounds brushBounds = new DetailBrushBounds(terrainData, ctx, size, t); int[] layers = { detailPrototype }; if (targetStrength < 0.0F && !Event.current.control) { layers = terrainData.GetSupportedLayers(brushBounds.min, brushBounds.bounds.size); } for (int i = 0; i < layers.Length; i++) { int[,] alphamap = terrainData.GetDetailLayer(brushBounds.min, brushBounds.bounds.size, layers[i]); for (int y = 0; y < brushBounds.bounds.height; y++) { for (int x = 0; x < brushBounds.bounds.width; x++) { Vector2Int brushOffset = brushBounds.GetBrushOffset(x, y); float opa = detailOpacity * m_BrushRep.GetStrength(brushOffset.x, brushOffset.y); float targetValue = Mathf.Lerp(alphamap[y, x], targetStrength * terrainData.maxDetailScatterPerRes, opa); alphamap[y, x] = Mathf.Min(Mathf.RoundToInt(targetValue - .5f + Random.value), terrainData.maxDetailScatterPerRes); } } terrainData.SetDetailLayer(brushBounds.min, layers[i], alphamap); } } } return(false); }
public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { commonUI.OnSceneGUI2D(terrain, editContext); #if UNITY_2019_1_OR_NEWER // Don't paint if eyedropper is selected if (m_EyedropperSelected) { EditorGUIUtility.AddCursorRect(new Rect(0, 0, Screen.width, Screen.height), MouseCursor.CustomCursor); editContext.Repaint(); return; } #endif // We're only doing painting operations, early out if it's not a repaint if (!editContext.hitValidTerrain && !commonUI.isInUse) { return; } // update brush UI group commonUI.OnSceneGUI(terrain, editContext); // Don't render preview if this isn't a repaint. losing performance if we do if (Event.current.type != EventType.Repaint) { return; } Texture brushTexture = editContext.brushTexture; using (IBrushRenderPreviewUnderCursor brushRender = new BrushRenderPreviewUIGroupUnderCursor(commonUI, "PaintTextureTool", brushTexture)) { if (brushRender.CalculateBrushTransform(out BrushTransform brushTransform)) //cute. { RenderTexture tmpRT = RenderTexture.active; Rect brushBounds = brushTransform.GetBrushXYBounds(); PaintContext heightmapContext = brushRender.AcquireHeightmap(false, brushBounds, 1); Material brushMaterial = GetBrushPreviewMaterial(); brushMaterial.SetFloat("_BrushStrength", commonUI.brushStrength); var defaultPreviewMaterial = Utility.GetDefaultPreviewMaterial(); var texelCtx = Utility.CollectTexelValidity(heightmapContext.originTerrain, brushTransform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(heightmapContext, texelCtx, brushTransform, defaultPreviewMaterial); if (commonUI.brushMaskFilterStack.filters.Count > 0) { // Evaluate the brush mask filter stack var brushMask = RTUtils.GetTempHandle(heightmapContext.sourceRenderTexture.width, heightmapContext.sourceRenderTexture.height, 0, FilterUtility.defaultFormat); commonUI.GetBrushMask(heightmapContext.sourceRenderTexture, brushMask); RenderTexture.active = tmpRT; Utility.SetupMaterialForPaintingWithTexelValidityContext(heightmapContext, texelCtx, brushTransform, brushMaterial); brushMaterial.SetTexture("_FilterTex", brushMask); TerrainPaintUtilityEditor.DrawBrushPreview(heightmapContext, TerrainBrushPreviewMode.SourceRenderTexture, editContext.brushTexture, brushTransform, brushMaterial, 0); RTUtils.Release(brushMask); } brushRender.RenderBrushPreview(heightmapContext, TerrainBrushPreviewMode.SourceRenderTexture, brushTransform, defaultPreviewMaterial, 0); texelCtx.Cleanup(); } } }
public override void OnSceneGUI(Terrain terrain, IOnSceneGUI editContext) { Init(); // m_rtCollection.OnSceneGUI( EditorWindow.GetWindow<SceneView>().position.height / 4 ); commonUI.OnSceneGUI2D(terrain, editContext); // only do the rest if user mouse hits valid terrain or they are using the // brush parameter hotkeys to resize, etc if (!editContext.hitValidTerrain && !commonUI.isInUse && !m_editTransform && !debugOrtho) { return; } // update brush UI group commonUI.OnSceneGUI(terrain, editContext); bool justPressedEditKey = m_editTransform && !m_prevEditTransform; bool justReleaseEditKey = m_prevEditTransform && !m_editTransform; m_prevEditTransform = m_editTransform; if (justPressedEditKey) { (commonUI as MeshBrushUIGroup).LockTerrainUnderCursor(true); m_baseHandlePos = commonUI.raycastHitUnderCursor.point; m_handleHeightOffsetWS = 0; } else if (justReleaseEditKey) { (commonUI as MeshBrushUIGroup).UnlockTerrainUnderCursor(); m_handleHeightOffsetWS = 0; } // don't render mesh previews, etc. if the mesh field has not been populated yet if (activeMesh == null) { return; } // dont render preview if this isnt a repaint. losing performance if we do if (Event.current.type == EventType.Repaint) { Terrain currTerrain = commonUI.terrainUnderCursor; Vector2 uv = commonUI.raycastHitUnderCursor.textureCoord; float brushSize = commonUI.brushSize; float brushRotation = commonUI.brushRotation; if (commonUI.isRaycastHitUnderCursorValid) { BrushTransform brushTransform = TerrainPaintUtility.CalculateBrushTransform(currTerrain, uv, brushSize, brushRotation); PaintContext ctx = TerrainPaintUtility.BeginPaintHeightmap(commonUI.terrainUnderCursor, brushTransform.GetBrushXYBounds(), 1); Material previewMaterial = Utility.GetDefaultPreviewMaterial(); var texelCtx = Utility.CollectTexelValidity(ctx.originTerrain, brushTransform.GetBrushXYBounds()); Utility.SetupMaterialForPaintingWithTexelValidityContext(ctx, texelCtx, brushTransform, previewMaterial); // don't draw the brush mask preview // but draw the resulting mesh stamp preview { ApplyBrushInternal(terrain, ctx, brushTransform); RenderTexture.active = ctx.oldRenderTexture; previewMaterial.SetTexture("_HeightmapOrig", ctx.sourceRenderTexture); TerrainPaintUtilityEditor.DrawBrushPreview(ctx, TerrainBrushPreviewMode.DestinationRenderTexture, editContext.brushTexture, brushTransform, previewMaterial, 1); TerrainPaintUtility.ReleaseContextResources(ctx); m_rtCollection.ReleaseRTHandles(); } texelCtx.Cleanup(); } } if (m_editTransform) { EditorGUI.BeginChangeCheck(); { Vector3 prevHandlePosWS = m_baseHandlePos + Vector3.up * m_handleHeightOffsetWS; // draw transform handles float handleSize = HandleUtility.GetHandleSize(prevHandlePosWS); Quaternion brushRotation = Quaternion.AngleAxis(commonUI.brushRotation, Vector3.up); Matrix4x4 brushRotMat = Matrix4x4.Rotate(brushRotation); Matrix4x4 toolRotMat = Matrix4x4.Rotate(toolSettings.rotation); Quaternion handleRot = MeshUtils.QuaternionFromMatrix(brushRotMat * toolRotMat); Quaternion newRot = Handles.RotationHandle(handleRot, prevHandlePosWS); toolSettings.rotation = MeshUtils.QuaternionFromMatrix(brushRotMat.inverse * Matrix4x4.Rotate(newRot)); toolSettings.scale = Handles.ScaleHandle(toolSettings.scale, prevHandlePosWS, handleRot, handleSize * 1.5f); Vector3 currHandlePosWS = Handles.Slider(prevHandlePosWS, Vector3.up, handleSize, Handles.ArrowHandleCap, 1f); float deltaHeight = (currHandlePosWS.y - prevHandlePosWS.y); m_handleHeightOffsetWS += deltaHeight; toolSettings.stampHeight += deltaHeight; } if (EditorGUI.EndChangeCheck()) { SaveSettings(); editContext.Repaint(); } } }