From 2eb2cbc302cf0a2a64cd7ede13872121f415c424 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 17 Feb 2025 05:48:15 -0600 Subject: [PATCH 01/10] add erosion brushes todo: sort why noise... isn't. --- .../source/gui/worldEditor/terrainActions.cpp | 100 ++++++++++++++---- .../source/gui/worldEditor/terrainActions.h | 22 +++- .../source/gui/worldEditor/terrainEditor.cpp | 3 +- Engine/source/util/noise2d.cpp | 2 +- .../worldEditor/scripts/EditorGui.ed.tscript | 22 ++-- 5 files changed, 113 insertions(+), 36 deletions(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index 2552a4d78..630aed26c 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -746,51 +746,57 @@ void PaintNoiseAction::process(Selection * sel, const Gui3DMouseEvent &, bool se mTerrainEditor->scheduleGridUpdate(); } } -/* -void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type) + +void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type type) { - if( selChanged ) + if (selChanged) { - TerrainBlock *tblock = mTerrainEditor->getActiveTerrain(); - if ( !tblock ) + TerrainBlock* tblock = mTerrainEditor->getActiveTerrain(); + if (!tblock) return; - + U32 size = tblock->getBlockSize(); F32 height = 0; F32 maxHeight = 0; - U32 shift = getBinLog2( TerrainBlock::BlockSize ); + U32 shift = getBinLog2(size); - for ( U32 x = 0; x < TerrainBlock::BlockSize; x++ ) + mNoiseData.setSize(size * size); + mTerrainHeights.setSize(size * size); + mNoise.fBm(&mNoiseData, size, 12, 1.0f, 5.0f); + Vector scratch = mNoiseData; + mNoise.rigidMultiFractal( &mNoiseData, &scratch, size, 12, 1.0f, 5.0f ); + + for (U32 x = 0; x < size; x++) { - for ( U32 y = 0; y < TerrainBlock::BlockSize; y++ ) + for (U32 y = 0; y < size; y++) { - height = fixedToFloat( tblock->getHeight( x, y ) ); - mTerrainHeights[ x + (y << 8)] = height; + height = fixedToFloat(tblock->getHeight(Point2I(x, y))); + mTerrainHeights[x + (y << 8)] = height * mNoiseData[x + (y << 8)]; - if ( height > maxHeight ) + if (height > maxHeight) maxHeight = height; } } - //mNoise.erodeThermal( &mTerrainHeights, &mNoiseData, 30.0f, 5.0f, 5, TerrainBlock::BlockSize, tblock->getSquareSize(), maxHeight ); - - mNoise.erodeHydraulic( &mTerrainHeights, &mNoiseData, 1, TerrainBlock::BlockSize ); + mNoise.erodeThermal( &mTerrainHeights, &mNoiseData, 45.0f, 0.5f, 12, size, tblock->getSquareSize(), maxHeight ); + + //mNoise.erodeHydraulic(&mTerrainHeights, &mNoiseData, 1, tblock->getBlockSize()); F32 heightDiff = 0; - for( U32 i = 0; i < sel->size(); i++ ) + for (U32 i = 0; i < sel->size(); i++) { mTerrainEditor->getUndoSel()->add((*sel)[i]); - const Point2I &gridPos = (*sel)[i].mGridPoint.gridPos; - + const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; + // Need to get the height difference // between the current height and the // erosion height to properly apply the // softness and pressure settings of the brush // for this selection. - heightDiff = (*sel)[i].mHeight - mNoiseData[ gridPos.x + (gridPos.y << shift)]; + heightDiff = (*sel)[i].mHeight - mNoiseData[gridPos.x + (gridPos.y << shift)]; - (*sel)[i].mHeight -= (heightDiff * (*sel)[i].mWeight); + (*sel)[i].mHeight -= (heightDiff * (*sel)[i].mWeight) / maxHeight; mTerrainEditor->setGridInfo((*sel)[i]); } @@ -798,8 +804,60 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo mTerrainEditor->gridUpdateComplete(); } } -*/ +void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) +{ + if (selChanged) + { + TerrainBlock* tblock = mTerrainEditor->getActiveTerrain(); + if (!tblock) + return; + U32 size = tblock->getBlockSize(); + F32 height = 0; + F32 maxHeight = 0; + U32 shift = getBinLog2(size); + + mNoiseData.setSize(size * size); + mTerrainHeights.setSize(size * size); + mNoise.fBm(&mNoiseData, size, 12, 1.0f, 5.0f); + + for (U32 x = 0; x < size; x++) + { + for (U32 y = 0; y < size; y++) + { + height = fixedToFloat(tblock->getHeight(Point2I(x, y))); + mTerrainHeights[x + (y << 8)] = height * mNoiseData[x + (y << 8)]; + + if (height > maxHeight) + maxHeight = height; + } + } + + mNoise.erodeHydraulic(&mTerrainHeights, &mNoiseData, 1, size); + + F32 heightDiff = 0; + + for (U32 i = 0; i < sel->size(); i++) + { + mTerrainEditor->getUndoSel()->add((*sel)[i]); + + const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; + + // Need to get the height difference + // between the current height and the + // erosion height to properly apply the + // softness and pressure settings of the brush + // for this selection. + heightDiff = (*sel)[i].mHeight - mNoiseData[gridPos.x + (gridPos.y << shift)]; + + (*sel)[i].mHeight -= (heightDiff * (*sel)[i].mWeight) / maxHeight; + + mTerrainEditor->setGridInfo((*sel)[i]); + } + + mTerrainEditor->gridUpdateComplete(); + } +} IMPLEMENT_CONOBJECT( TerrainSmoothAction ); diff --git a/Engine/source/gui/worldEditor/terrainActions.h b/Engine/source/gui/worldEditor/terrainActions.h index c59451717..d04c1658e 100644 --- a/Engine/source/gui/worldEditor/terrainActions.h +++ b/Engine/source/gui/worldEditor/terrainActions.h @@ -302,7 +302,7 @@ class PaintNoiseAction : public TerrainAction F32 mScale; }; -/* + class ThermalErosionAction : public TerrainAction { public: @@ -310,8 +310,6 @@ class ThermalErosionAction : public TerrainAction : TerrainAction(editor) { mNoise.setSeed( 1 );//Sim::getCurrentTime() ); - mNoiseData.setSize( TerrainBlock::BlockSize * TerrainBlock::BlockSize ); - mTerrainHeights.setSize( TerrainBlock::BlockSize * TerrainBlock::BlockSize ); } StringTableEntry getName(){return("thermalErode");} @@ -322,7 +320,23 @@ class ThermalErosionAction : public TerrainAction Vector mNoiseData; Vector mTerrainHeights; }; -*/ + +class HydraulicErosionAction : public TerrainAction +{ +public: + HydraulicErosionAction(TerrainEditor* editor) + : TerrainAction(editor) + { + mNoise.setSeed(1);//Sim::getCurrentTime() ); + } + + StringTableEntry getName() { return("hydraulicErode"); } + void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type); + Noise2D mNoise; + Vector mNoiseData; + Vector mTerrainHeights; +}; + /// An undo action used to perform terrain wide smoothing. class TerrainSmoothAction : public UndoAction diff --git a/Engine/source/gui/worldEditor/terrainEditor.cpp b/Engine/source/gui/worldEditor/terrainEditor.cpp index ff3ee9e30..30ac24d28 100644 --- a/Engine/source/gui/worldEditor/terrainEditor.cpp +++ b/Engine/source/gui/worldEditor/terrainEditor.cpp @@ -712,7 +712,8 @@ TerrainEditor::TerrainEditor() : mActions.push_back(new SmoothHeightAction(this)); mActions.push_back(new SmoothSlopeAction(this)); mActions.push_back(new PaintNoiseAction(this)); - //mActions.push_back(new ThermalErosionAction(this)); + mActions.push_back(new ThermalErosionAction(this)); + mActions.push_back(new HydraulicErosionAction(this)); // set the default action diff --git a/Engine/source/util/noise2d.cpp b/Engine/source/util/noise2d.cpp index 24c1579dd..34405bd56 100644 --- a/Engine/source/util/noise2d.cpp +++ b/Engine/source/util/noise2d.cpp @@ -345,7 +345,7 @@ bool Noise2D::erodeThermal(Vector *src, Vector *dst, F32 slope, F32 ma //dMemset( r.address(), 0, r.memSize() ); F32 conservation = 1.0f - mClampF(materialLoss, 0.0f, 100.0f)/100.0f; - slope = mClampF(conservation, 0.0f, 89.0f); // clamp to 0-89 degrees + slope = mMin(slope, mClampF(conservation, 0.0f, 89.0f)); // clamp to 0-89 degrees F32 talusConst = mTan(mDegToRad(slope)) * squareSize; // in world units talusConst = talusConst * (fmax-fmin) / maxHeight; // scale to current height units diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript index 5ba3a9e08..4aca0698c 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript @@ -1205,10 +1205,12 @@ function TerrainEditorPlugin::onWorldEditorStartup( %this ) %map.bindCmd( keyboard, "4", "ToolsPaletteArray->smoothHeight.performClick();", "" ); // Average Height %map.bindCmd( keyboard, "5", "ToolsPaletteArray->smoothSlope.performClick();", "" ); // Smooth Slope %map.bindCmd( keyboard, "6", "ToolsPaletteArray->paintNoise.performClick();", "" ); // Noise - %map.bindCmd( keyboard, "7", "ToolsPaletteArray->flattenHeight.performClick();", "" ); // Flatten - %map.bindCmd( keyboard, "8", "ToolsPaletteArray->setHeight.performClick();", "" ); // Set Height - %map.bindCmd( keyboard, "9", "ToolsPaletteArray->setEmpty.performClick();", "" ); // Clear Terrain - %map.bindCmd( keyboard, "0", "ToolsPaletteArray->clearEmpty.performClick();", "" ); // Restore Terrain + %map.bindCmd( keyboard, "6", "ToolsPaletteArray->thermalErode.performClick();", "" ); // Noise + %map.bindCmd( keyboard, "7", "ToolsPaletteArray->hydraulicErode.performClick();", "" ); // Noise + %map.bindCmd( keyboard, "8", "ToolsPaletteArray->flattenHeight.performClick();", "" ); // Flatten + %map.bindCmd( keyboard, "9", "ToolsPaletteArray->setHeight.performClick();", "" ); // Set Height + %map.bindCmd( keyboard, "0", "ToolsPaletteArray->setEmpty.performClick();", "" ); // Clear Terrain + %map.bindCmd( keyboard, "shift 0", "ToolsPaletteArray->clearEmpty.performClick();", "" ); // Restore Terrain %map.bindCmd( keyboard, "v", "EWTerrainEditToolbarBrushType->ellipse.performClick();", "" );// Circle Brush %map.bindCmd( keyboard, "b", "EWTerrainEditToolbarBrushType->box.performClick();", "" );// Box Brush %map.bindCmd( keyboard, "=", "TerrainEditorPlugin.keyboardModifyBrushSize(1);", "" );// +1 Brush Size @@ -1248,11 +1250,13 @@ function EditorGui::SetTerrainPalletBar() EWToolsPaletteWindow.addButton("LowerHeight", "ToolsModule:lowerHeight_n_image", "ETerrainEditor.switchAction( lowerHeight );", "", "Lower Height", "3"); EWToolsPaletteWindow.addButton("SmoothHeight", "ToolsModule:smoothHeight_n_image", "ETerrainEditor.switchAction( smoothHeight );", "", "Smooth Height", "4"); EWToolsPaletteWindow.addButton("SmoothSlope", "ToolsModule:softCurve_n_image", "ETerrainEditor.switchAction( smoothSlope );", "", "Smooth Slope", "5"); - EWToolsPaletteWindow.addButton("PaintNoise", "ToolsModule:brushPaintNoise_n_image", "ETerrainEditor.switchAction( paintNoise );", "", "Paint Noise", "6"); - EWToolsPaletteWindow.addButton("FlattenHeight", "ToolsModule:flattenHeight_n_image", "ETerrainEditor.switchAction( flattenHeight );", "", "Flatten Height", "7"); - EWToolsPaletteWindow.addButton("SetHeight", "ToolsModule:setHeight_n_image", "ETerrainEditor.switchAction( setHeight );", "", "Set Height", "8"); - EWToolsPaletteWindow.addButton("SetEmpty", "ToolsModule:setEmpty_n_image", "ETerrainEditor.switchAction( setEmpty );", "", "Set Empty", "9"); - EWToolsPaletteWindow.addButton("ClearEmpty", "ToolsModule:clearEmpty_n_image", "ETerrainEditor.switchAction( clearEmpty );", "", "Clear Empty", "0"); + EWToolsPaletteWindow.addButton("PaintNoise", "ToolsModule:brushPaintNoise_n_image", "ETerrainEditor.switchAction( paintNoise );", "", "Paint Noise", "6"); + EWToolsPaletteWindow.addButton("thermalErode", "ToolsModule:brushPaintNoise_n_image", "ETerrainEditor.switchAction( thermalErode );", "", "thermal Erode", "7"); + EWToolsPaletteWindow.addButton("hydraulicErode", "ToolsModule:brushPaintNoise_n_image", "ETerrainEditor.switchAction( hydraulicErode );", "", "hydraulic Erode", "8"); + EWToolsPaletteWindow.addButton("FlattenHeight", "ToolsModule:flattenHeight_n_image", "ETerrainEditor.switchAction( flattenHeight );", "", "Flatten Height", "9"); + EWToolsPaletteWindow.addButton("SetHeight", "ToolsModule:setHeight_n_image", "ETerrainEditor.switchAction( setHeight );", "", "Set Height", "0"); + EWToolsPaletteWindow.addButton("SetEmpty", "ToolsModule:setEmpty_n_image", "ETerrainEditor.switchAction( setEmpty );", "", "Set Empty", "0"); + EWToolsPaletteWindow.addButton("ClearEmpty", "ToolsModule:clearEmpty_n_image", "ETerrainEditor.switchAction( clearEmpty );", "", "Clear Empty", "shift 0"); EWToolsPaletteWindow.refresh(); } From 329ffab86cf4845333758e26318851988441184d Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 17 Feb 2025 16:43:10 -0600 Subject: [PATCH 02/10] work towards adding erosion noise --- .../source/gui/worldEditor/terrainActions.cpp | 93 ++++++++++++------- .../source/gui/worldEditor/terrainActions.h | 15 ++- 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index 630aed26c..fb2ab86a7 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -749,42 +749,56 @@ void PaintNoiseAction::process(Selection * sel, const Gui3DMouseEvent &, bool se void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, bool selChanged, Type type) { + // If this is the ending + // mouse down event, then + // update the noise values. + U32 shift = getBinLog2(mNoiseSize); + TerrainBlock* tblock = mTerrainEditor->getActiveTerrain(); + if (!tblock) + return; + + mSelectionOrigin = Point2I(S32_MAX, S32_MAX); + + F32 height = 0; + F32 maxHeight = 0; + U32 i = 0; + for (i=0; i < sel->size(); i++) + { + mSelectionOrigin.x = S32(mMin(F32((*sel)[i].mGridPoint.gridPos.x), F32(mSelectionOrigin.x))); + mSelectionOrigin.y = S32(mMin(F32((*sel)[i].mGridPoint.gridPos.y), F32(mSelectionOrigin.y))); + height = fixedToFloat(tblock->getHeight((*sel)[i].mGridPoint.gridPos)); + if (height > maxHeight) + maxHeight = height; + } + + for (i = 0; i < mTerrainHeights.size(); i++) + { + mTerrainHeights[i] = 0; + } + + for (i = 0; i < sel->size(); i++) + { + mTerrainHeights[((*sel)[i].mGridPoint.gridPos.x - mSelectionOrigin.x) + (((*sel)[i].mGridPoint.gridPos.y - mSelectionOrigin.y) << shift)] = (*sel)[i].mHeight; + } + + mNoise.setSeed(Sim::getCurrentTime()); + //mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); + //generate noise based on terrain hieghts + mNoise.rigidMultiFractal( &mNoiseData, &mTerrainHeights, mNoiseSize, 12, 1.0f, 5.0f ); + //erode the noise + mNoise.erodeThermal(&mNoiseData, &mTerrainHeights, 45.0f, 0.5f, 12, mNoiseSize, 1, maxHeight); + + mNoise.getMinMax(&mTerrainHeights, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); + mScale = (mMinMaxNoise.x - mMinMaxNoise.y) / maxHeight; + if (selChanged) { - TerrainBlock* tblock = mTerrainEditor->getActiveTerrain(); - if (!tblock) - return; - U32 size = tblock->getBlockSize(); - F32 height = 0; - F32 maxHeight = 0; - U32 shift = getBinLog2(size); - - mNoiseData.setSize(size * size); - mTerrainHeights.setSize(size * size); - mNoise.fBm(&mNoiseData, size, 12, 1.0f, 5.0f); - Vector scratch = mNoiseData; - mNoise.rigidMultiFractal( &mNoiseData, &scratch, size, 12, 1.0f, 5.0f ); - - for (U32 x = 0; x < size; x++) - { - for (U32 y = 0; y < size; y++) - { - height = fixedToFloat(tblock->getHeight(Point2I(x, y))); - mTerrainHeights[x + (y << 8)] = height * mNoiseData[x + (y << 8)]; - - if (height > maxHeight) - maxHeight = height; - } - } - - mNoise.erodeThermal( &mTerrainHeights, &mNoiseData, 45.0f, 0.5f, 12, size, tblock->getSquareSize(), maxHeight ); - - //mNoise.erodeHydraulic(&mTerrainHeights, &mNoiseData, 1, tblock->getBlockSize()); - F32 heightDiff = 0; - - for (U32 i = 0; i < sel->size(); i++) + for (i = 0; i < sel->size(); i++) { + if (!isValid((*sel)[i])) + continue; + mTerrainEditor->getUndoSel()->add((*sel)[i]); const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; @@ -794,15 +808,22 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo // erosion height to properly apply the // softness and pressure settings of the brush // for this selection. - heightDiff = (*sel)[i].mHeight - mNoiseData[gridPos.x + (gridPos.y << shift)]; + heightDiff = ((*sel)[i].mHeight - mTerrainHeights[(gridPos.x - mSelectionOrigin.x) + ((gridPos.y-mSelectionOrigin.y) << shift)]) * mScale; - (*sel)[i].mHeight -= (heightDiff * (*sel)[i].mWeight) / maxHeight; + (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight * mTerrainEditor->getBrushPressure(); + + if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight) + (*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight; + + if ((*sel)[i].mHeight < mTerrainEditor->mTileMinHeight) + (*sel)[i].mHeight = mTerrainEditor->mTileMinHeight; mTerrainEditor->setGridInfo((*sel)[i]); } - mTerrainEditor->gridUpdateComplete(); + mTerrainEditor->scheduleGridUpdate(); } + } void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) @@ -826,7 +847,7 @@ void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, boo for (U32 y = 0; y < size; y++) { height = fixedToFloat(tblock->getHeight(Point2I(x, y))); - mTerrainHeights[x + (y << 8)] = height * mNoiseData[x + (y << 8)]; + mTerrainHeights[x + (y << shift)] = height * mNoiseData[x + (y << shift)]; if (height > maxHeight) maxHeight = height; diff --git a/Engine/source/gui/worldEditor/terrainActions.h b/Engine/source/gui/worldEditor/terrainActions.h index d04c1658e..844e04d3d 100644 --- a/Engine/source/gui/worldEditor/terrainActions.h +++ b/Engine/source/gui/worldEditor/terrainActions.h @@ -307,18 +307,31 @@ class ThermalErosionAction : public TerrainAction { public: ThermalErosionAction(TerrainEditor * editor) - : TerrainAction(editor) + : TerrainAction(editor), + mNoiseSize(256) { mNoise.setSeed( 1 );//Sim::getCurrentTime() ); + mNoiseData.setSize(mNoiseSize * mNoiseSize); + mTerrainHeights.setSize(mNoiseSize * mNoiseSize); + mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); + //Vector scratch = mNoiseData; + //mNoise.rigidMultiFractal( &mNoiseData, &scratch, TerrainBlock::BlockSize, 12, 1.0f, 5.0f ); + mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); + + mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y); } StringTableEntry getName(){return("thermalErode");} void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type); + const U32 mNoiseSize; Noise2D mNoise; Vector mNoiseData; Vector mTerrainHeights; + Point2F mMinMaxNoise; + Point2I mSelectionOrigin; + F32 mScale; }; class HydraulicErosionAction : public TerrainAction From 315f05ea47dadea6ba11f1d783ac560341ea08de Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 17 Feb 2025 19:55:23 -0600 Subject: [PATCH 03/10] revert portions to a previously demonstrated to work state... --- .../source/gui/worldEditor/terrainActions.cpp | 61 +++++-------------- .../source/gui/worldEditor/terrainActions.h | 6 -- Engine/source/util/noise2d.cpp | 2 +- 3 files changed, 15 insertions(+), 54 deletions(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index fb2ab86a7..f7c6101f1 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -752,49 +752,22 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo // If this is the ending // mouse down event, then // update the noise values. - U32 shift = getBinLog2(mNoiseSize); - TerrainBlock* tblock = mTerrainEditor->getActiveTerrain(); - if (!tblock) - return; - - mSelectionOrigin = Point2I(S32_MAX, S32_MAX); - - F32 height = 0; - F32 maxHeight = 0; - U32 i = 0; - for (i=0; i < sel->size(); i++) + if (type == Begin) { - mSelectionOrigin.x = S32(mMin(F32((*sel)[i].mGridPoint.gridPos.x), F32(mSelectionOrigin.x))); - mSelectionOrigin.y = S32(mMin(F32((*sel)[i].mGridPoint.gridPos.y), F32(mSelectionOrigin.y))); - height = fixedToFloat(tblock->getHeight((*sel)[i].mGridPoint.gridPos)); - if (height > maxHeight) - maxHeight = height; + mNoise.setSeed(Sim::getCurrentTime()); + mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); + Vector scratch = mNoiseData; + mNoise.rigidMultiFractal(&mNoiseData, &scratch, mNoiseSize, 12, 1.0f, 5.0f); + //erodeThermal(Vector *src, Vector *dst, F32 slope, F32 materialLoss, U32 iterations, U32 size, U32 squareSize, F32 maxHeight ); + mNoise.erodeThermal(&mNoiseData, &mNoiseData, 30.0f, 5.0f, 5, mNoiseSize, 1, 2000.0f); + mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); + + mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y); } - for (i = 0; i < mTerrainHeights.size(); i++) - { - mTerrainHeights[i] = 0; - } - - for (i = 0; i < sel->size(); i++) - { - mTerrainHeights[((*sel)[i].mGridPoint.gridPos.x - mSelectionOrigin.x) + (((*sel)[i].mGridPoint.gridPos.y - mSelectionOrigin.y) << shift)] = (*sel)[i].mHeight; - } - - mNoise.setSeed(Sim::getCurrentTime()); - //mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); - //generate noise based on terrain hieghts - mNoise.rigidMultiFractal( &mNoiseData, &mTerrainHeights, mNoiseSize, 12, 1.0f, 5.0f ); - //erode the noise - mNoise.erodeThermal(&mNoiseData, &mTerrainHeights, 45.0f, 0.5f, 12, mNoiseSize, 1, maxHeight); - - mNoise.getMinMax(&mTerrainHeights, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); - mScale = (mMinMaxNoise.x - mMinMaxNoise.y) / maxHeight; - if (selChanged) { - F32 heightDiff = 0; - for (i = 0; i < sel->size(); i++) + for (U32 i = 0; i < sel->size(); i++) { if (!isValid((*sel)[i])) continue; @@ -803,27 +776,21 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; - // Need to get the height difference - // between the current height and the - // erosion height to properly apply the - // softness and pressure settings of the brush - // for this selection. - heightDiff = ((*sel)[i].mHeight - mTerrainHeights[(gridPos.x - mSelectionOrigin.x) + ((gridPos.y-mSelectionOrigin.y) << shift)]) * mScale; + const F32 noiseVal = mNoiseData[(gridPos.x % mNoiseSize) + + ((gridPos.y % mNoiseSize) * mNoiseSize)]; - (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight * mTerrainEditor->getBrushPressure(); + (*sel)[i].mHeight -= (noiseVal - mMinMaxNoise.y * mScale) * (*sel)[i].mWeight * mTerrainEditor->mNoiseFactor; if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight) (*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight; if ((*sel)[i].mHeight < mTerrainEditor->mTileMinHeight) (*sel)[i].mHeight = mTerrainEditor->mTileMinHeight; - mTerrainEditor->setGridInfo((*sel)[i]); } mTerrainEditor->scheduleGridUpdate(); } - } void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) diff --git a/Engine/source/gui/worldEditor/terrainActions.h b/Engine/source/gui/worldEditor/terrainActions.h index 844e04d3d..9ac286ed6 100644 --- a/Engine/source/gui/worldEditor/terrainActions.h +++ b/Engine/source/gui/worldEditor/terrainActions.h @@ -312,12 +312,8 @@ class ThermalErosionAction : public TerrainAction { mNoise.setSeed( 1 );//Sim::getCurrentTime() ); mNoiseData.setSize(mNoiseSize * mNoiseSize); - mTerrainHeights.setSize(mNoiseSize * mNoiseSize); mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); - //Vector scratch = mNoiseData; - //mNoise.rigidMultiFractal( &mNoiseData, &scratch, TerrainBlock::BlockSize, 12, 1.0f, 5.0f ); mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); - mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y); } @@ -328,9 +324,7 @@ class ThermalErosionAction : public TerrainAction const U32 mNoiseSize; Noise2D mNoise; Vector mNoiseData; - Vector mTerrainHeights; Point2F mMinMaxNoise; - Point2I mSelectionOrigin; F32 mScale; }; diff --git a/Engine/source/util/noise2d.cpp b/Engine/source/util/noise2d.cpp index 34405bd56..24c1579dd 100644 --- a/Engine/source/util/noise2d.cpp +++ b/Engine/source/util/noise2d.cpp @@ -345,7 +345,7 @@ bool Noise2D::erodeThermal(Vector *src, Vector *dst, F32 slope, F32 ma //dMemset( r.address(), 0, r.memSize() ); F32 conservation = 1.0f - mClampF(materialLoss, 0.0f, 100.0f)/100.0f; - slope = mMin(slope, mClampF(conservation, 0.0f, 89.0f)); // clamp to 0-89 degrees + slope = mClampF(conservation, 0.0f, 89.0f); // clamp to 0-89 degrees F32 talusConst = mTan(mDegToRad(slope)) * squareSize; // in world units talusConst = talusConst * (fmax-fmin) / maxHeight; // scale to current height units From 262ff405fa60396b1a28146017c3a2c5cf6a5d80 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 17 Feb 2025 20:58:40 -0600 Subject: [PATCH 04/10] conform hydrolicErosion to the same spec as thermal --- .../source/gui/worldEditor/terrainActions.cpp | 92 ++++++++++--------- .../source/gui/worldEditor/terrainActions.h | 11 ++- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index f7c6101f1..e79712c3c 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -752,21 +752,30 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo // If this is the ending // mouse down event, then // update the noise values. + + TerrainBlock* tblock = mTerrainEditor->getActiveTerrain(); + if (!tblock) + return; + + Vector scratch = mNoiseData; if (type == Begin) { mNoise.setSeed(Sim::getCurrentTime()); mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); - Vector scratch = mNoiseData; + scratch = mNoiseData; mNoise.rigidMultiFractal(&mNoiseData, &scratch, mNoiseSize, 12, 1.0f, 5.0f); - //erodeThermal(Vector *src, Vector *dst, F32 slope, F32 materialLoss, U32 iterations, U32 size, U32 squareSize, F32 maxHeight ); - mNoise.erodeThermal(&mNoiseData, &mNoiseData, 30.0f, 5.0f, 5, mNoiseSize, 1, 2000.0f); mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); - - mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y); } + scratch = mNoiseData; + //erodeThermal(Vector *src, Vector *dst, F32 slope, F32 materialLoss, U32 iterations, U32 size, U32 squareSize, F32 maxHeight ); + mNoise.erodeThermal(&scratch, &mNoiseData, 30.0f, 5.0f, 5, mNoiseSize, 1, tblock->getObjBox().len_z()); + mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); + mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y + 0.0001); if (selChanged) { + F32 heightDiff = 0; + for (U32 i = 0; i < sel->size(); i++) { if (!isValid((*sel)[i])) @@ -777,9 +786,11 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; const F32 noiseVal = mNoiseData[(gridPos.x % mNoiseSize) + - ((gridPos.y % mNoiseSize) * mNoiseSize)]; + ((gridPos.y % mNoiseSize) * mNoiseSize)] + mMinMaxNoise.y; - (*sel)[i].mHeight -= (noiseVal - mMinMaxNoise.y * mScale) * (*sel)[i].mWeight * mTerrainEditor->mNoiseFactor; + heightDiff = (noiseVal * mTerrainEditor->mNoiseFactor - (*sel)[i].mHeight) / tblock->getObjBox().len_z(); + + (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight; if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight) (*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight; @@ -795,56 +806,55 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) { + // If this is the ending + // mouse down event, then + // update the noise values. + + TerrainBlock* tblock = mTerrainEditor->getActiveTerrain(); + if (!tblock) + return; + Vector scratch = mNoiseData; + if (type == Begin) + { + mNoise.setSeed(Sim::getCurrentTime()); + mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); + scratch = mNoiseData; + } + mNoise.erodeHydraulic(&scratch, &mNoiseData, 1, mNoiseSize); + mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); + mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y + 0.0001); + if (selChanged) { - TerrainBlock* tblock = mTerrainEditor->getActiveTerrain(); - if (!tblock) - return; - U32 size = tblock->getBlockSize(); - F32 height = 0; - F32 maxHeight = 0; - U32 shift = getBinLog2(size); - - mNoiseData.setSize(size * size); - mTerrainHeights.setSize(size * size); - mNoise.fBm(&mNoiseData, size, 12, 1.0f, 5.0f); - - for (U32 x = 0; x < size; x++) - { - for (U32 y = 0; y < size; y++) - { - height = fixedToFloat(tblock->getHeight(Point2I(x, y))); - mTerrainHeights[x + (y << shift)] = height * mNoiseData[x + (y << shift)]; - - if (height > maxHeight) - maxHeight = height; - } - } - - mNoise.erodeHydraulic(&mTerrainHeights, &mNoiseData, 1, size); - F32 heightDiff = 0; for (U32 i = 0; i < sel->size(); i++) { + if (!isValid((*sel)[i])) + continue; + mTerrainEditor->getUndoSel()->add((*sel)[i]); const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; - // Need to get the height difference - // between the current height and the - // erosion height to properly apply the - // softness and pressure settings of the brush - // for this selection. - heightDiff = (*sel)[i].mHeight - mNoiseData[gridPos.x + (gridPos.y << shift)]; + const F32 noiseVal = mNoiseData[(gridPos.x % mNoiseSize) + + ((gridPos.y % mNoiseSize) * mNoiseSize)] + mMinMaxNoise.y; - (*sel)[i].mHeight -= (heightDiff * (*sel)[i].mWeight) / maxHeight; + heightDiff = (noiseVal * mTerrainEditor->mNoiseFactor - (*sel)[i].mHeight) / tblock->getObjBox().len_z(); + (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight; + + if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight) + (*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight; + + if ((*sel)[i].mHeight < mTerrainEditor->mTileMinHeight) + (*sel)[i].mHeight = mTerrainEditor->mTileMinHeight; mTerrainEditor->setGridInfo((*sel)[i]); } - mTerrainEditor->gridUpdateComplete(); + mTerrainEditor->scheduleGridUpdate(); } + } IMPLEMENT_CONOBJECT( TerrainSmoothAction ); diff --git a/Engine/source/gui/worldEditor/terrainActions.h b/Engine/source/gui/worldEditor/terrainActions.h index 9ac286ed6..955314db0 100644 --- a/Engine/source/gui/worldEditor/terrainActions.h +++ b/Engine/source/gui/worldEditor/terrainActions.h @@ -332,16 +332,23 @@ class HydraulicErosionAction : public TerrainAction { public: HydraulicErosionAction(TerrainEditor* editor) - : TerrainAction(editor) + : TerrainAction(editor), + mNoiseSize(256) { mNoise.setSeed(1);//Sim::getCurrentTime() ); + mNoiseData.setSize(mNoiseSize * mNoiseSize); + mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); + mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); + mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y); } StringTableEntry getName() { return("hydraulicErode"); } void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type); + const U32 mNoiseSize; Noise2D mNoise; Vector mNoiseData; - Vector mTerrainHeights; + Point2F mMinMaxNoise; + F32 mScale; }; From 561c201b88b8d9d9c9388e4ae4ed17f284df49ad Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 17 Feb 2025 22:10:56 -0600 Subject: [PATCH 05/10] copy paste support for terrains --- .../source/gui/worldEditor/terrainActions.cpp | 29 +++++++++++++ .../source/gui/worldEditor/terrainActions.h | 41 +++++++++++++++++++ .../source/gui/worldEditor/terrainEditor.cpp | 2 + .../worldEditor/scripts/EditorGui.ed.tscript | 4 +- 4 files changed, 75 insertions(+), 1 deletion(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index e79712c3c..d0726057e 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -26,6 +26,7 @@ #include "gui/core/guiCanvas.h" +TerrainScratchPad gTerrainScratchPad; //------------------------------------------------------------------------------ bool TerrainAction::isValid(GridInfo tile) { @@ -857,6 +858,34 @@ void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, boo } +void copyAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) +{ + gTerrainScratchPad.clear(); + for (U32 i=0;isize();i++) + { + if (isValid((*sel)[i])) + gTerrainScratchPad.addTile((*sel)[i].mHeight, (*sel)[i].mMaterial); + else + gTerrainScratchPad.addTile(0, 0); + } +} + +void pasteAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) +{ + for (U32 i = 0; i < sel->size(); i++) + { + if (isValid((*sel)[i])) + { + mTerrainEditor->getUndoSel()->add((*sel)[i]); + (*sel)[i].mHeight = gTerrainScratchPad[i]->mHeight; + (*sel)[i].mMaterial = gTerrainScratchPad[i]->mMaterial; + mTerrainEditor->setGridInfo((*sel)[i]); + } + } + mTerrainEditor->scheduleGridUpdate(); + mTerrainEditor->scheduleMaterialUpdate(); +} + IMPLEMENT_CONOBJECT( TerrainSmoothAction ); ConsoleDocClass( TerrainSmoothAction, diff --git a/Engine/source/gui/worldEditor/terrainActions.h b/Engine/source/gui/worldEditor/terrainActions.h index 955314db0..cd8e5fb2f 100644 --- a/Engine/source/gui/worldEditor/terrainActions.h +++ b/Engine/source/gui/worldEditor/terrainActions.h @@ -351,6 +351,47 @@ public: F32 mScale; }; +class TerrainScratchPad +{ +public: + TerrainScratchPad() {}; + ~TerrainScratchPad() { mContents.clear(); }; + void clear() { for (U32 i = 0; i < mContents.size(); i++) delete(mContents[i]); mContents.clear(); }; + class gridStub + { + public: + gridStub(F32 height, U8 material) : mHeight(height), mMaterial(material) {}; + F32 mHeight; + U8 mMaterial; + }; + void addTile(F32 height, U8 material) { mContents.push_back(new gridStub(height, material)); }; + gridStub* operator [](U32 index) { return mContents[index]; }; +private: + Vector mContents; +}; + +class copyAction : public TerrainAction +{ +public: + copyAction(TerrainEditor* editor) + : TerrainAction(editor) + { + } + StringTableEntry getName() { return("copy"); } + void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type); +}; + +class pasteAction : public TerrainAction +{ +public: + pasteAction(TerrainEditor* editor) + : TerrainAction(editor) + { + } + StringTableEntry getName() { return("paste"); } + void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type); +}; + /// An undo action used to perform terrain wide smoothing. class TerrainSmoothAction : public UndoAction diff --git a/Engine/source/gui/worldEditor/terrainEditor.cpp b/Engine/source/gui/worldEditor/terrainEditor.cpp index 30ac24d28..2ee3f3716 100644 --- a/Engine/source/gui/worldEditor/terrainEditor.cpp +++ b/Engine/source/gui/worldEditor/terrainEditor.cpp @@ -714,6 +714,8 @@ TerrainEditor::TerrainEditor() : mActions.push_back(new PaintNoiseAction(this)); mActions.push_back(new ThermalErosionAction(this)); mActions.push_back(new HydraulicErosionAction(this)); + mActions.push_back(new copyAction(this)); + mActions.push_back(new pasteAction(this)); // set the default action diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript index 4aca0698c..a2a6f3896 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript @@ -1256,7 +1256,9 @@ function EditorGui::SetTerrainPalletBar() EWToolsPaletteWindow.addButton("FlattenHeight", "ToolsModule:flattenHeight_n_image", "ETerrainEditor.switchAction( flattenHeight );", "", "Flatten Height", "9"); EWToolsPaletteWindow.addButton("SetHeight", "ToolsModule:setHeight_n_image", "ETerrainEditor.switchAction( setHeight );", "", "Set Height", "0"); EWToolsPaletteWindow.addButton("SetEmpty", "ToolsModule:setEmpty_n_image", "ETerrainEditor.switchAction( setEmpty );", "", "Set Empty", "0"); - EWToolsPaletteWindow.addButton("ClearEmpty", "ToolsModule:clearEmpty_n_image", "ETerrainEditor.switchAction( clearEmpty );", "", "Clear Empty", "shift 0"); + EWToolsPaletteWindow.addButton("ClearEmpty", "ToolsModule:clearEmpty_n_image", "ETerrainEditor.switchAction( clearEmpty );", "", "Clear Empty", "shift 0"); + EWToolsPaletteWindow.addButton("Copy", "ToolsModule:setHeight_n_image", "ETerrainEditor.switchAction( copy );", "", "copy", "ctrl C"); + EWToolsPaletteWindow.addButton("Paste", "ToolsModule:setHeight_n_image", "ETerrainEditor.switchAction( paste );", "", "paste", "ctrl v"); EWToolsPaletteWindow.refresh(); } From 25ea164a1feb040dd3c972bacee821383de2a2fc Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Mon, 17 Feb 2025 23:42:19 -0600 Subject: [PATCH 06/10] add a pasteUp and pasteDown pallet --- .../source/gui/worldEditor/terrainActions.cpp | 86 +++++++++++++++++++ .../source/gui/worldEditor/terrainActions.h | 29 ++++++- .../source/gui/worldEditor/terrainEditor.cpp | 4 +- .../worldEditor/scripts/EditorGui.ed.tscript | 2 + .../worldEditor/scripts/buttonPalette.tscript | 2 +- 5 files changed, 118 insertions(+), 5 deletions(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index d0726057e..2d143b3e5 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -858,6 +858,23 @@ void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, boo } +void TerrainScratchPad::addTile(F32 height, U8 material) +{ + mContents.push_back(new gridStub(height, material)); + + mBottom = mMin(height, mBottom); + mTop = mMax(height, mTop); +}; + +void TerrainScratchPad::clear() +{ + for (U32 i = 0; i < mContents.size(); i++) + delete(mContents[i]); + mContents.clear(); + mBottom = F32_MAX; + mTop = F32_MIN; +} + void copyAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) { gTerrainScratchPad.clear(); @@ -872,6 +889,15 @@ void copyAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged void pasteAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) { + if (gTerrainScratchPad.size() == 0) + return; + + if (gTerrainScratchPad.size() != sel->size()) + return; + + if (type != Begin) + return; + for (U32 i = 0; i < sel->size(); i++) { if (isValid((*sel)[i])) @@ -886,6 +912,66 @@ void pasteAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChange mTerrainEditor->scheduleMaterialUpdate(); } +void pasteUpAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) +{ + if (gTerrainScratchPad.size() == 0) + return; + + if (gTerrainScratchPad.size() != sel->size()) + return; + + if (type != Begin) + return; + F32 floor = F32_MAX; + for (U32 i = 0; i < sel->size(); i++) + { + floor = mMin((*sel)[i].mHeight, floor); + } + for (U32 i = 0; i < sel->size(); i++) + { + if (isValid((*sel)[i])) + { + mTerrainEditor->getUndoSel()->add((*sel)[i]); + (*sel)[i].mHeight = gTerrainScratchPad[i]->mHeight - gTerrainScratchPad.mBottom + floor; + (*sel)[i].mMaterial = gTerrainScratchPad[i]->mMaterial; + mTerrainEditor->setGridInfo((*sel)[i]); + } + } + mTerrainEditor->scheduleGridUpdate(); + mTerrainEditor->scheduleMaterialUpdate(); +} + +void pasteDownAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) +{ + if (gTerrainScratchPad.size() == 0) + return; + + if (gTerrainScratchPad.size() != sel->size()) + return; + + if (type != Begin) + return; + + F32 ceiling = F32_MIN; + for (U32 i = 0; i < sel->size(); i++) + { + ceiling = mMax((*sel)[i].mHeight, ceiling); + } + + for (U32 i = 0; i < sel->size(); i++) + { + if (isValid((*sel)[i])) + { + mTerrainEditor->getUndoSel()->add((*sel)[i]); + (*sel)[i].mHeight = gTerrainScratchPad[i]->mHeight - gTerrainScratchPad.mTop + ceiling; + (*sel)[i].mMaterial = gTerrainScratchPad[i]->mMaterial; + mTerrainEditor->setGridInfo((*sel)[i]); + } + } + mTerrainEditor->scheduleGridUpdate(); + mTerrainEditor->scheduleMaterialUpdate(); +} + IMPLEMENT_CONOBJECT( TerrainSmoothAction ); ConsoleDocClass( TerrainSmoothAction, diff --git a/Engine/source/gui/worldEditor/terrainActions.h b/Engine/source/gui/worldEditor/terrainActions.h index cd8e5fb2f..51ff989d0 100644 --- a/Engine/source/gui/worldEditor/terrainActions.h +++ b/Engine/source/gui/worldEditor/terrainActions.h @@ -354,9 +354,10 @@ public: class TerrainScratchPad { public: - TerrainScratchPad() {}; + F32 mBottom, mTop; + TerrainScratchPad(): mBottom(FLT_MAX), mTop(F32_MIN){}; ~TerrainScratchPad() { mContents.clear(); }; - void clear() { for (U32 i = 0; i < mContents.size(); i++) delete(mContents[i]); mContents.clear(); }; + void clear(); class gridStub { public: @@ -364,7 +365,8 @@ public: F32 mHeight; U8 mMaterial; }; - void addTile(F32 height, U8 material) { mContents.push_back(new gridStub(height, material)); }; + void addTile(F32 height, U8 material); + U32 size() { return(mContents.size()); }; gridStub* operator [](U32 index) { return mContents[index]; }; private: Vector mContents; @@ -392,6 +394,27 @@ public: void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type); }; +class pasteUpAction : public TerrainAction +{ +public: + pasteUpAction(TerrainEditor* editor) + : TerrainAction(editor) + { + } + StringTableEntry getName() { return("pasteUp"); } + void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type); +}; + +class pasteDownAction : public TerrainAction +{ +public: + pasteDownAction(TerrainEditor* editor) + : TerrainAction(editor) + { + } + StringTableEntry getName() { return("pasteDown"); } + void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type); +}; /// An undo action used to perform terrain wide smoothing. class TerrainSmoothAction : public UndoAction diff --git a/Engine/source/gui/worldEditor/terrainEditor.cpp b/Engine/source/gui/worldEditor/terrainEditor.cpp index 2ee3f3716..00b93b455 100644 --- a/Engine/source/gui/worldEditor/terrainEditor.cpp +++ b/Engine/source/gui/worldEditor/terrainEditor.cpp @@ -716,7 +716,9 @@ TerrainEditor::TerrainEditor() : mActions.push_back(new HydraulicErosionAction(this)); mActions.push_back(new copyAction(this)); mActions.push_back(new pasteAction(this)); - + mActions.push_back(new pasteUpAction(this)); + mActions.push_back(new pasteDownAction(this)); + // set the default action mCurrentAction = mActions[0]; diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript index a2a6f3896..714e81b80 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.tscript @@ -1259,6 +1259,8 @@ function EditorGui::SetTerrainPalletBar() EWToolsPaletteWindow.addButton("ClearEmpty", "ToolsModule:clearEmpty_n_image", "ETerrainEditor.switchAction( clearEmpty );", "", "Clear Empty", "shift 0"); EWToolsPaletteWindow.addButton("Copy", "ToolsModule:setHeight_n_image", "ETerrainEditor.switchAction( copy );", "", "copy", "ctrl C"); EWToolsPaletteWindow.addButton("Paste", "ToolsModule:setHeight_n_image", "ETerrainEditor.switchAction( paste );", "", "paste", "ctrl v"); + EWToolsPaletteWindow.addButton("pasteUp", "ToolsModule:setHeight_n_image", "ETerrainEditor.switchAction( pasteUp );", "", "pasteUp", "ctrl b"); + EWToolsPaletteWindow.addButton("PasteDown", "ToolsModule:setHeight_n_image", "ETerrainEditor.switchAction( pasteDown );", "", "pasteDown", "ctrl n"); EWToolsPaletteWindow.refresh(); } diff --git a/Templates/BaseGame/game/tools/worldEditor/scripts/buttonPalette.tscript b/Templates/BaseGame/game/tools/worldEditor/scripts/buttonPalette.tscript index f401f939d..fd2322925 100644 --- a/Templates/BaseGame/game/tools/worldEditor/scripts/buttonPalette.tscript +++ b/Templates/BaseGame/game/tools/worldEditor/scripts/buttonPalette.tscript @@ -148,7 +148,7 @@ function ButtonPalette::refresh(%this) variable = getField(%buttonInfo, 3); }; - %extents.y += 23; + %extents.y += 25; if(isObject(%this.actionMap)) %this.actionMap.bindCmd( keyboard, getField(%buttonInfo, 5), %paletteButton @ ".performClick();", "" ); From 0d2f3e294d47d2a01db08c2889e0fec106595225 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Tue, 18 Feb 2025 01:09:09 -0600 Subject: [PATCH 07/10] use standard t3d maxes --- Engine/source/gui/worldEditor/terrainActions.cpp | 4 ++-- Engine/source/gui/worldEditor/terrainActions.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index 2d143b3e5..f390df22e 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -872,7 +872,7 @@ void TerrainScratchPad::clear() delete(mContents[i]); mContents.clear(); mBottom = F32_MAX; - mTop = F32_MIN; + mTop = F32_MIN_EX; } void copyAction::process(Selection* sel, const Gui3DMouseEvent&, bool selChanged, Type type) @@ -952,7 +952,7 @@ void pasteDownAction::process(Selection* sel, const Gui3DMouseEvent&, bool selCh if (type != Begin) return; - F32 ceiling = F32_MIN; + F32 ceiling = F32_MIN_EX; for (U32 i = 0; i < sel->size(); i++) { ceiling = mMax((*sel)[i].mHeight, ceiling); diff --git a/Engine/source/gui/worldEditor/terrainActions.h b/Engine/source/gui/worldEditor/terrainActions.h index 51ff989d0..68171c89d 100644 --- a/Engine/source/gui/worldEditor/terrainActions.h +++ b/Engine/source/gui/worldEditor/terrainActions.h @@ -355,7 +355,7 @@ class TerrainScratchPad { public: F32 mBottom, mTop; - TerrainScratchPad(): mBottom(FLT_MAX), mTop(F32_MIN){}; + TerrainScratchPad(): mBottom(F32_MAX), mTop(F32_MIN_EX){}; ~TerrainScratchPad() { mContents.clear(); }; void clear(); class gridStub From e1068713508cb3a753ceb910c0dea573a90cad07 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Tue, 18 Feb 2025 16:08:30 -0600 Subject: [PATCH 08/10] correct noise miltipliers. add biases for thermal (slope) and hydrolic (average) hieght changes --- .../source/gui/worldEditor/terrainActions.cpp | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index f390df22e..c81286324 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -773,6 +773,7 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y + 0.0001); + F32 selRange = sel->getMaxHeight()-sel->getMinHeight(); if (selChanged) { F32 heightDiff = 0; @@ -787,11 +788,20 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; const F32 noiseVal = mNoiseData[(gridPos.x % mNoiseSize) + - ((gridPos.y % mNoiseSize) * mNoiseSize)] + mMinMaxNoise.y; + ((gridPos.y % mNoiseSize) * mNoiseSize)]/(mMinMaxNoise.y-mMinMaxNoise.x) * selRange + mMinMaxNoise.y; - heightDiff = (noiseVal * mTerrainEditor->mNoiseFactor - (*sel)[i].mHeight) / tblock->getObjBox().len_z(); + heightDiff = (noiseVal * mTerrainEditor->mNoiseFactor - (*sel)[i].mHeight) / tblock->getObjBox().len_z() * 2.0; - (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight; + const F32 squareSize = tblock->getSquareSize(); + Point2F p; + Point3F norm; + + p.x = (*sel)[i].mGridPoint.gridPos.x * squareSize; + p.y = (*sel)[i].mGridPoint.gridPos.y * squareSize; + tblock->getNormal(p, &norm, true); + + F32 bias = 0.75f-norm.z; + (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight * bias; if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight) (*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight; @@ -825,6 +835,8 @@ void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, boo mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y + 0.0001); + F32 selRange = sel->getMaxHeight() - sel->getMinHeight(); + F32 avg = sel->getAvgHeight(); if (selChanged) { F32 heightDiff = 0; @@ -839,11 +851,12 @@ void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, boo const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; const F32 noiseVal = mNoiseData[(gridPos.x % mNoiseSize) + - ((gridPos.y % mNoiseSize) * mNoiseSize)] + mMinMaxNoise.y; + ((gridPos.y % mNoiseSize) * mNoiseSize)] / (mMinMaxNoise.y - mMinMaxNoise.x) * selRange + mMinMaxNoise.y; - heightDiff = (noiseVal * mTerrainEditor->mNoiseFactor - (*sel)[i].mHeight) / tblock->getObjBox().len_z(); + heightDiff = (noiseVal * mTerrainEditor->mNoiseFactor - (*sel)[i].mHeight) / tblock->getObjBox().len_z() * 2.0; - (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight; + F32 bias = ((*sel)[i].mHeight - avg)/ selRange; + (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight * bias; if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight) (*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight; From f9eeaf8869f66c22fac0b3c48ae1f22334202078 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Tue, 18 Feb 2025 19:58:48 -0600 Subject: [PATCH 09/10] simplify erosion calcs --- .../source/gui/worldEditor/terrainActions.cpp | 65 +++++-------------- .../source/gui/worldEditor/terrainActions.h | 31 +-------- 2 files changed, 20 insertions(+), 76 deletions(-) diff --git a/Engine/source/gui/worldEditor/terrainActions.cpp b/Engine/source/gui/worldEditor/terrainActions.cpp index c81286324..774e30fff 100644 --- a/Engine/source/gui/worldEditor/terrainActions.cpp +++ b/Engine/source/gui/worldEditor/terrainActions.cpp @@ -758,22 +758,8 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo if (!tblock) return; - Vector scratch = mNoiseData; - if (type == Begin) - { - mNoise.setSeed(Sim::getCurrentTime()); - mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); - scratch = mNoiseData; - mNoise.rigidMultiFractal(&mNoiseData, &scratch, mNoiseSize, 12, 1.0f, 5.0f); - mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); - } - scratch = mNoiseData; - //erodeThermal(Vector *src, Vector *dst, F32 slope, F32 materialLoss, U32 iterations, U32 size, U32 squareSize, F32 maxHeight ); - mNoise.erodeThermal(&scratch, &mNoiseData, 30.0f, 5.0f, 5, mNoiseSize, 1, tblock->getObjBox().len_z()); - mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); - mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y + 0.0001); - F32 selRange = sel->getMaxHeight()-sel->getMinHeight(); + F32 avg = sel->getAvgHeight(); if (selChanged) { F32 heightDiff = 0; @@ -785,23 +771,11 @@ void ThermalErosionAction::process(Selection * sel, const Gui3DMouseEvent &, boo mTerrainEditor->getUndoSel()->add((*sel)[i]); - const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; - - const F32 noiseVal = mNoiseData[(gridPos.x % mNoiseSize) + - ((gridPos.y % mNoiseSize) * mNoiseSize)]/(mMinMaxNoise.y-mMinMaxNoise.x) * selRange + mMinMaxNoise.y; - - heightDiff = (noiseVal * mTerrainEditor->mNoiseFactor - (*sel)[i].mHeight) / tblock->getObjBox().len_z() * 2.0; - - const F32 squareSize = tblock->getSquareSize(); - Point2F p; - Point3F norm; - - p.x = (*sel)[i].mGridPoint.gridPos.x * squareSize; - p.y = (*sel)[i].mGridPoint.gridPos.y * squareSize; - tblock->getNormal(p, &norm, true); - - F32 bias = 0.75f-norm.z; - (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight * bias; + F32 bias = ((*sel)[i].mHeight - avg) / selRange; + F32 nudge = mRandF(-mTerrainEditor->getBrushPressure(), mTerrainEditor->getBrushPressure()); + F32 heightTarg = mRoundF((*sel)[i].mHeight - bias * nudge, mTerrainEditor->getBrushPressure() * 2.0f) ; + heightDiff = heightTarg - (*sel)[i].mHeight; + (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight; if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight) (*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight; @@ -824,22 +798,13 @@ void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, boo TerrainBlock* tblock = mTerrainEditor->getActiveTerrain(); if (!tblock) return; - Vector scratch = mNoiseData; - if (type == Begin) - { - mNoise.setSeed(Sim::getCurrentTime()); - mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); - scratch = mNoiseData; - } - mNoise.erodeHydraulic(&scratch, &mNoiseData, 1, mNoiseSize); - mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); - mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y + 0.0001); F32 selRange = sel->getMaxHeight() - sel->getMinHeight(); F32 avg = sel->getAvgHeight(); if (selChanged) { F32 heightDiff = 0; + const F32 squareSize = tblock->getSquareSize(); for (U32 i = 0; i < sel->size(); i++) { @@ -848,15 +813,19 @@ void HydraulicErosionAction::process(Selection* sel, const Gui3DMouseEvent&, boo mTerrainEditor->getUndoSel()->add((*sel)[i]); - const Point2I& gridPos = (*sel)[i].mGridPoint.gridPos; + Point2F p; + Point3F norm; - const F32 noiseVal = mNoiseData[(gridPos.x % mNoiseSize) + - ((gridPos.y % mNoiseSize) * mNoiseSize)] / (mMinMaxNoise.y - mMinMaxNoise.x) * selRange + mMinMaxNoise.y; + p.x = (*sel)[i].mGridPoint.gridPos.x * squareSize; + p.y = (*sel)[i].mGridPoint.gridPos.y * squareSize; + tblock->getNormal(p, &norm, true); - heightDiff = (noiseVal * mTerrainEditor->mNoiseFactor - (*sel)[i].mHeight) / tblock->getObjBox().len_z() * 2.0; + F32 bias = mPow(norm.z,3.0f) * ((*sel)[i].mHeight - avg) / selRange; + F32 nudge = mRandF(-mTerrainEditor->getBrushPressure(), mTerrainEditor->getBrushPressure()); - F32 bias = ((*sel)[i].mHeight - avg)/ selRange; - (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight * bias; + heightDiff = bias * (-(*sel)[i].mHeight + bias * nudge) / tblock->getObjBox().len_z() * 2.0; + + (*sel)[i].mHeight += heightDiff * (*sel)[i].mWeight; if ((*sel)[i].mHeight > mTerrainEditor->mTileMaxHeight) (*sel)[i].mHeight = mTerrainEditor->mTileMaxHeight; diff --git a/Engine/source/gui/worldEditor/terrainActions.h b/Engine/source/gui/worldEditor/terrainActions.h index 68171c89d..18e0029ae 100644 --- a/Engine/source/gui/worldEditor/terrainActions.h +++ b/Engine/source/gui/worldEditor/terrainActions.h @@ -307,48 +307,23 @@ class ThermalErosionAction : public TerrainAction { public: ThermalErosionAction(TerrainEditor * editor) - : TerrainAction(editor), - mNoiseSize(256) + : TerrainAction(editor) { - mNoise.setSeed( 1 );//Sim::getCurrentTime() ); - mNoiseData.setSize(mNoiseSize * mNoiseSize); - mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); - mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); - mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y); - } - + } StringTableEntry getName(){return("thermalErode");} - void process(Selection * sel, const Gui3DMouseEvent & event, bool selChanged, Type type); - - const U32 mNoiseSize; - Noise2D mNoise; - Vector mNoiseData; - Point2F mMinMaxNoise; - F32 mScale; }; class HydraulicErosionAction : public TerrainAction { public: HydraulicErosionAction(TerrainEditor* editor) - : TerrainAction(editor), - mNoiseSize(256) + : TerrainAction(editor) { - mNoise.setSeed(1);//Sim::getCurrentTime() ); - mNoiseData.setSize(mNoiseSize * mNoiseSize); - mNoise.fBm(&mNoiseData, mNoiseSize, 12, 1.0f, 5.0f); - mNoise.getMinMax(&mNoiseData, &mMinMaxNoise.x, &mMinMaxNoise.y, mNoiseSize); - mScale = 1.5f / (mMinMaxNoise.x - mMinMaxNoise.y); } StringTableEntry getName() { return("hydraulicErode"); } void process(Selection* sel, const Gui3DMouseEvent& event, bool selChanged, Type type); - const U32 mNoiseSize; - Noise2D mNoise; - Vector mNoiseData; - Point2F mMinMaxNoise; - F32 mScale; }; class TerrainScratchPad From 1ac6ad08870c5ad63afdc2c2b4bd40b73586fee4 Mon Sep 17 00:00:00 2001 From: AzaezelX Date: Tue, 18 Feb 2025 20:41:26 -0600 Subject: [PATCH 10/10] icons --- .../game/tools/worldEditor/images/Copy_terr_d.png | Bin 0 -> 890 bytes .../images/Copy_terr_d_image.asset.taml | 3 +++ .../game/tools/worldEditor/images/Copy_terr_h.png | Bin 0 -> 741 bytes .../images/Copy_terr_h_image.asset.taml | 3 +++ .../game/tools/worldEditor/images/Copy_terr_n.png | Bin 0 -> 544 bytes .../images/Copy_terr_n_image.asset.taml | 3 +++ .../game/tools/worldEditor/images/erodeH_d.png | Bin 0 -> 729 bytes .../worldEditor/images/erodeH_d_image.asset.taml | 3 +++ .../game/tools/worldEditor/images/erodeH_h.png | Bin 0 -> 640 bytes .../worldEditor/images/erodeH_h_image.asset.taml | 3 +++ .../game/tools/worldEditor/images/erodeH_n.png | Bin 0 -> 509 bytes .../worldEditor/images/erodeH_n_image.asset.taml | 3 +++ .../game/tools/worldEditor/images/erodeT_d.png | Bin 0 -> 477 bytes .../worldEditor/images/erodeT_d_image.asset.taml | 3 +++ .../game/tools/worldEditor/images/erodeT_h.png | Bin 0 -> 468 bytes .../worldEditor/images/erodeT_h_image.asset.taml | 3 +++ .../game/tools/worldEditor/images/erodeT_n.png | Bin 0 -> 427 bytes .../worldEditor/images/erodeT_n_image.asset.taml | 3 +++ .../tools/worldEditor/images/pasteDown_terr_d.png | Bin 0 -> 898 bytes .../images/pasteDown_terr_d_image.asset.taml | 3 +++ .../tools/worldEditor/images/pasteDown_terr_h.png | Bin 0 -> 739 bytes .../images/pasteDown_terr_h_image.asset.taml | 3 +++ .../tools/worldEditor/images/pasteDown_terr_n.png | Bin 0 -> 633 bytes .../images/pasteDown_terr_n_image.asset.taml | 3 +++ .../tools/worldEditor/images/pasteUp_terr_d.png | Bin 0 -> 958 bytes .../images/pasteUp_terr_d_image.asset.taml | 3 +++ .../tools/worldEditor/images/pasteUp_terr_h.png | Bin 0 -> 776 bytes .../images/pasteUp_terr_h_image.asset.taml | 3 +++ .../tools/worldEditor/images/pasteUp_terr_n.png | Bin 0 -> 619 bytes .../images/pasteUp_terr_n_image.asset.taml | 3 +++ .../tools/worldEditor/images/paste_terr_d.png | Bin 0 -> 745 bytes .../images/paste_terr_d_image.asset.taml | 3 +++ .../tools/worldEditor/images/paste_terr_h.png | Bin 0 -> 661 bytes .../images/paste_terr_h_image.asset.taml | 3 +++ .../tools/worldEditor/images/paste_terr_n.png | Bin 0 -> 556 bytes .../images/paste_terr_n_image.asset.taml | 3 +++ 36 files changed, 54 insertions(+) create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_d.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_d_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_h.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_h_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_n.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_n_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeH_d.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeH_d_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeH_h.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeH_h_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeH_n.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeH_n_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeT_d.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeT_d_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeT_h.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeT_h_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeT_n.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/erodeT_n_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_d.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_d_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_h.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_h_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_n.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_n_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_d.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_d_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_h.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_h_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_n.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_n_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/paste_terr_d.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/paste_terr_d_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/paste_terr_h.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/paste_terr_h_image.asset.taml create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/paste_terr_n.png create mode 100644 Templates/BaseGame/game/tools/worldEditor/images/paste_terr_n_image.asset.taml diff --git a/Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_d.png b/Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_d.png new file mode 100644 index 0000000000000000000000000000000000000000..0182b6cd208033cf36964d0b561babc4ff6bb6aa GIT binary patch literal 890 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4uLSEsD@VqP*9@8HKHUqKdq!Zu_%=xATcwqM9$cc z0dZzK3s^i0$OeH=WsD3jm=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CZi?hjjbaFBK`d_wxG}NTNrfo7jR&krf@?c}jQ-+F!?Yh_4(iWR)=Nvd) z^0x1`p3cdCdhgFx&;65j%kP%J(vn7R1sBcO8{7USn$7+zG`r4YlE_TI<;Rom_Lo@w z)!|_{?P21pZFFp#L~_6G>8eu_)rTZ@AD8&8d-_vb#a@pHosJWm_8gQ5e)aViGsA6$ zJcbzzH&_bf4{#qgkW1TqQ@3#4^kUbx#5;@uj}K2jnpD^>@X2td&%VnhZ;cziGX%}` zTdwG1>$<=r^eR)lsn*m}dWtR^bAJmkEW7-2L@pxZh6wD9X6w z=;M6>`vn{qvGlV${dHpLRI}N2Xe)34Cch69Xg>HrVe-j0Og9)mv`>Fu)XDc?>Z(=q|ETCae|N&$LWWP!$xM0T z3DM()eKN-_h1OekFD-kLYByj1*yE4>r#Ic$BsBd(>fbqkSPKJpS)QnT2~2|w44$rj JF6*2UngC`aOTz#F literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_d_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_d_image.asset.taml new file mode 100644 index 000000000..ab710745d --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_d_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_h.png b/Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_h.png new file mode 100644 index 0000000000000000000000000000000000000000..40da96e30c02f500dd6e14d747b270c5ba4340a9 GIT binary patch literal 741 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjKtYKT*NBqf{Irtt#G+J&fW*wa59r`^%bvYPO|Dc&2%JYB6vCIjjs)jI0cdK$aH}OGDWp*Jv;@gTzyvgh z39K^6(gMhW>M}Gi0Lfl|wp(%Uv-mAQ+opKBIEHw5@4e>V;TtG(;N$t=^#VU@P4lK*wngjS!KYN^W?YFMW_3UU8GJwNisj2xHsJ!juv zElhiM=l8uM<)5v;f8V`--}2)3w$II?)?UlmeDjO`%db^ZZ_BE;-F};Qs#{d&c)!g~ zfw_L^Ri5*73WTnIWXk_26}+S4>d&*5r7qb8($fnivJIO>Z}b{hbnLB6_L9Bm`= diff --git a/Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_n.png b/Templates/BaseGame/game/tools/worldEditor/images/Copy_terr_n.png new file mode 100644 index 0000000000000000000000000000000000000000..c58a35e99863b2dad7c2487a0be655d271c921b2 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4uLSEsD@VqP*9@8HKHUqKdq!Zu_%=xATcwqM9$cc z0dZzK3s^i0$OeH=WsD3jm=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CZY4oqy)-oWIxOHV2x zb9S|#k$r}L?wc#~&I#A2#YOLp`oVHlbiwkd)P~-tK3BcHuHFt=xUh-+#qAGDVIum? zbBc9WTVGtP!JQR#)}?=u&WoI@?E73JFI-zyf9U+jsqx}WJR#m(1{=MfzEVAIFJBOR zUbIg9MB~D$t&Dt*3J0Wav^RZoVLsDXy~A<>V{+_obxr;VvlsihSwH*-dDGL?&t;uc GLK6UrGMk diff --git a/Templates/BaseGame/game/tools/worldEditor/images/erodeH_d.png b/Templates/BaseGame/game/tools/worldEditor/images/erodeH_d.png new file mode 100644 index 0000000000000000000000000000000000000000..c7f1eacd2bfaf85b9a79f71902edfb73a5ec8a5a GIT binary patch literal 729 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0WWg+Z8+Vb&Z8prAyFYeY$Kep*R+Vo@qXKw@TIiJqTph=Qq} zp`MA*{bkKSHQQ1nJkvZqwHP>n999M?Mpgz!Aj=DgrJ-z)Ycv>{!QxCnwjm=Eg8-0@ z0^-be7O;30kPQN!l8g*5m=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CXrXL#6k5$Ih|?gQdgM#WBRg`|UJ;Z)rz~_W3#2Jli`a328-6 zJHo+bxYlyX!U@e6=KU7jp{GSZPi=d9w&KT}8OwHl+Z5gTL9far-(kt? zDxy))*W4$tAwCyWes zz0MP1RGI8~_VXU$2jU+L=k;5x2wUBl8d+u|QM^2(N5IM4w|L#fj5o}g4>rZEzaDe_ xZRI?3!!NIQY=5zGkG-(}qpL2R*MH6V!@T%-mtxJ^y4Rri@pScbS?83{1OV>A0f7Jj literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/erodeH_d_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/erodeH_d_image.asset.taml new file mode 100644 index 000000000..ce3a0fab1 --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/erodeH_d_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/erodeH_h.png b/Templates/BaseGame/game/tools/worldEditor/images/erodeH_h.png new file mode 100644 index 0000000000000000000000000000000000000000..f16a42a244ce2e8a46f49f9bffc7963264a8f8fb GIT binary patch literal 640 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0WWg+Z8+Vb&Z8prAyFYeY$Kep*R+Vo@qXKw@TIiJqTph=Qq} zp`MA*{bkKSHQQ1nJkvZqwHP>n999M?Mpgz!Aj=DgrJ-z)Ycv>{!QxCnwjm=Eg8-0@ z0^-be7O;30kPQN!l8g*5m=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CXrXL#6k5$Ih|?gGJxd#WBRg`|Y*8+D8K=4tzWxYVM`u#%8R_ zeCm<@he^Jknk#4DiH;MCOi?g1*Z<$ZX}EC0S&inYu6J8EMO=}MIJfrp%Wt3a9$MR- zFP`__^1S6?&s3wC(@U)0s%wgM2i?s1raJ$;`LUDlRi>X7UG?aJ|402_CiTuCvg~#q z%(osV=&U-EcI}ERGn=yU;zkf+zJ#0?+b{gS>2o;^JXK2VEz`ES9XcIA)_}*ytCGy({1PbYP+5KdJ|c@d%xngR)d1k)78&qol`;+ E08L`XqW}N^ literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/erodeH_h_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/erodeH_h_image.asset.taml new file mode 100644 index 000000000..e6cfc5660 --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/erodeH_h_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/erodeH_n.png b/Templates/BaseGame/game/tools/worldEditor/images/erodeH_n.png new file mode 100644 index 0000000000000000000000000000000000000000..dce921b7f25e3296a916531732df4b5287e59c91 GIT binary patch literal 509 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0WWg+Z8+Vb&Z8prAyFYeY$Kep*R+Vo@qXKw@TIiJqTph=Qq} zp`MA*{bkKSHQQ1nJkvZqwHP>n999M?Mpgz!Aj=DgrJ-z)Ycv>{!QxCnwjm=Eg8-0@ z0^-be7O;30kPQN!l8g*5m=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CXrXL#6k5$Ih|?nQJ^<978<3-<~(*V@worefXPe>JhyuVhguP zXkYLWF-wpZ(!LOA(COv4FtjH{O3D49r`mam5|#hg&srBxmell|^q+N2L*br!t_Wt= zJ@$-xcYKqo*&}|G$w#X`c+;Gjvz|fvzD&|;);Tphy4UhZFznpFyZ7(GM+ST4C_gZ~aOMDl0W#W~KeTG5N{%I}A$U V9XoZp-+_Xc!PC{xWt~$(699^_g$n=x literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/erodeH_n_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/erodeH_n_image.asset.taml new file mode 100644 index 000000000..828e03cc3 --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/erodeH_n_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/erodeT_d.png b/Templates/BaseGame/game/tools/worldEditor/images/erodeT_d.png new file mode 100644 index 0000000000000000000000000000000000000000..31e3fae9cc2a7f78e1b2323115c50ec502d43566 GIT binary patch literal 477 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0WWg+Z8+Vb&Z8prAyFYeY$Kep*R+Vo@qXKw@TIiJqTph=Qq} zp`MA*{bkKSHQQ1nJkvZqwHP>n999M?Mpgz!Aj=DgrJ-z)Ycv>{!QxCnwjm=Eg8-0@ z0^-be7O;30kPQN!l8g*5m=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CXrXL#6k5$Ih|?nLVB^jv*f2N2fXRF$nUw&a`Ndz7cIP@$t?X z(q9;aHqT;_blSRS$?UR^m;SL{ikdw&sA=+)NfXZPlu71!J3%P9r~a0j_*4!C8-^d7 z+>g%fwb-fsYty1LZ^Dl_s$Pm}-*oDxUb)#T$B8$mbTlpOFxtGZLud-eWJ#} diff --git a/Templates/BaseGame/game/tools/worldEditor/images/erodeT_h.png b/Templates/BaseGame/game/tools/worldEditor/images/erodeT_h.png new file mode 100644 index 0000000000000000000000000000000000000000..003878a4c704fb95f9f9ded9bc49efd33f8807d3 GIT binary patch literal 468 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0WWg+Z8+Vb&Z8prAyFYeY$Kep*R+Vo@qXKw@TIiJqTph=Qq} zp`MA*{bkKSHQQ1nJkvZqwHP>n999M?Mpgz!Aj=DgrJ-z)Ycv>{!QxCnwjm=Eg8-0@ z0^-be7O;30kPQN!l8g*5m=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CXrXL#6k5$Ih|?na!Rqjv*f2Pp>KR9Z(Q(30(1n>y7~L@&|Kb z7`=V7)f7)3%JHpl$~@{V(d@6;E6}ug&G&aT=PIv6DgR3e^U4&j+rqW*n@knQ%&+n< z?sjdv$+M_Epv9S6adX(h$7g|9rDNMnmW#Jqugrey^lHn6Z)s5((<-Lwc)Srgw0ch5 d%Kxtli diff --git a/Templates/BaseGame/game/tools/worldEditor/images/erodeT_n.png b/Templates/BaseGame/game/tools/worldEditor/images/erodeT_n.png new file mode 100644 index 0000000000000000000000000000000000000000..86636a6534fa7a3dc095a9c51dbd38df003a9ef0 GIT binary patch literal 427 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3-o{hSjtKDaPU;cPEB*=VV?2IV|apzK#qG z8~eHcB(eheYymzYuK)l42QotsU9JOCOeH~n!T%YaZa44(@;D1TB8wRqxP?KOkzv*x z380`viEBhjaDG}zd16s2LqK9?UWuNcYlwoWo}r$J(EVl2KsDP^BRtbQJ+&A(fE-o^ zDMnTXMj#7hrZkida;*jpt($7l|hykKo(S&p@9KNR`8+H`@Cak z*?~+ePZ!4!jo{>jBb*W!SOppyM3~Der92xMcJU}`8u%^~X diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_d.png b/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_d.png new file mode 100644 index 0000000000000000000000000000000000000000..83bdb45af56336838d3df4b852ccdffced86d579 GIT binary patch literal 898 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4uLSEsD@VqP*9@8HKHUqKdq!Zu_%=xATcwqM9$cc z0dZzK3s^i0$OeH=WsD3jm=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CZW#TL5!v*(>&+RF0x1270D#hq=fyEimN4xYE=9pRMZH>~u^2Ek-X%N3( znWp=Uh>25*SnjYLi>u@L!!YY;(#M#+asS^~^u0D$7vem-X^nNe|K}6WKfm6VTmI+A z4$->|dW_TezUC?r-m!b*#=sY4yVH~=UYIg(WXce+o#VWsXF=O6DPgtyJwwEyBu_C^MT}sqMdtgW|%}R z%gkeHH(qL>C&D$gZ1>;0;#V4DS@L|h{7Ks$qIGj?RPJ%{B~#`%s83F1un~3A`Ejt2 z`SoVrH4NuZJ^j>PW4C`@=B?L@)fk*QOcuPGynfNe73(q@=jZuyJmgY57qa?l?(J>X zi!YuC>}E*X7$NbY{(JwdWq(Uzuirn!$7y60(5e6oipL*+gg@v_lqkEv%_`X&@-Ux= zt$CrqqO0$}vuB-CKauh7kNM&WLg#xql@(oLuYV0yJkq-Omkr0?)rU{&Yp|V7*4N%L Q7nG1ZUHx3vIVCg!09W@= diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_h.png b/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_h.png new file mode 100644 index 0000000000000000000000000000000000000000..993628bca3236be60066807eb143b4250b70d9ba GIT binary patch literal 739 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjKtYKT*NBqf{Irtt#G+J&fW*wa59r`^%bvYPO|Dc&2%JYB6vCIjjs)jI0cdK$aH}OGDWp*Jv;@gTzyvgh z39K^6(gMhW>M}Gi0Lfl|wp(%Uv-mAQ+a`IsIEHw5AH8aNM1w_|(Dikl~O)TZPmCaG=;nY?Mjr_DJj>B*~a&gjiCc~_7-FZlXn znex1MAJ*kR|57>cedT<=^R~~$&Zcd?o?)^^mh7FCmRCCWE$&_)aiCVF?^fCyzrV~Yg+o8G&3{~DbCu1ghr{kzVeTn*qn-@j zZO49E%{hATO7JH8SMH}1Brax(ym%<-cjQEPA;actB;ROMF1)_Eu-!m3xlYLb z(!NP@=N{%trUVKe-#gE%H>SsZi}A5N z^Q}d1#$3%`>-RZpM>8=7E;?l-0Y{9$zjnep>JQas9tJe^@r}3w|EZ@yr4gQ=YDVF6*2U FngGc52QUBt literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_h_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_h_image.asset.taml new file mode 100644 index 000000000..cae536982 --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_h_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_n.png b/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_n.png new file mode 100644 index 0000000000000000000000000000000000000000..d30b842847e0d386820dd75ea26aff847cc941a7 GIT binary patch literal 633 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4uLSEsD@VqP*9@8HKHUqKdq!Zu_%=xATcwqM9$cc z0dZzK3s^i0$OeH=WsD3jm=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CZ(Fp0ny(+_E1TuhV~083hy|c)_SD@rkl=P&$%ey9K&%9(WRlSgRk~Kq~N8avf vnyj^ziE=96_lRk-{gTe~DWM4fetEnW literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_n_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_n_image.asset.taml new file mode 100644 index 000000000..5c4c095e8 --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/pasteDown_terr_n_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_d.png b/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_d.png new file mode 100644 index 0000000000000000000000000000000000000000..cd6933501fe66106e8367857d7f80ed2796b9a08 GIT binary patch literal 958 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4uLSEsD@VqP*9@8HKHUqKdq!Zu_%=xATcwqM9$cc z0dZzK3s^i0$OeH=WsD3jm=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CZdikHwSDrkBThA*pIMJI-}^0S^K$tIVUDUE5q(?ESFZeRP1oX76x*K&bS#xPv8-8i zX=3^D(|NP~$_oWw^S7n`|7`R7_D%6J)7#rr6`U@BqBV9s#o{;gZPo?4uH zb?A^&)JxA6Ev`y4bMx(n_V)jcW}nSlw{~qUQvpZ9#;aMeVcnAj)IZsr|LneaVs$~m zht)T8%DRp|YEO7qWjFu4*4KI!zml%F_1D=I7!uOcm)qH;OSI{=B&-a{O0$ty->C5* zd&68VW~UA_37%yPcV3t6?w&k(^7Fpa{hm5TJkIO^3=Ks)YmCpdAAV@pzwZe zuzrwWSatPP`tibj&xw!%f%dkp6rn%&MYxpgjd?XfM)VOFX)h@6|(5YkH>m#MH=RfaJo|!r8^{xNE aEPwKPnF(_HsJ4FwB|=YEKbLh*2~7Z6-ey?< literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_d_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_d_image.asset.taml new file mode 100644 index 000000000..01feb1322 --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_d_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_h.png b/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_h.png new file mode 100644 index 0000000000000000000000000000000000000000..a32bc61f7382f55898dc9294dae793ee029ba255 GIT binary patch literal 776 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjKtYKT*NBqf{Irtt#G+J&fW*wa59r`^%bvYPO|Dc&2%JYB6vCIjjs)jI0cdK$aH}OGDWp*Jv;@gTzyvgh z39K^6(gMhW>M}Gi0Lfl|wp(%Uv-mAQ+qQeUIEHw5@4dD=TO?5A_{Z~7=3M_c9WRD{ zXl(6B(C^T&^Olduf2g;jLoiymiNEBaxyGU!ksU5gbNN5$ZxGxnD4qL8WnE$JIi1Iz zZFd)Z!LA zEB72*EusHWWZF5>-RMi&zF+=VFYu%JblM{_XFP*w`STaVxMQia(osfV~ z`^l}Vj?9l-k>DxT6lornYN8W*_JcNeeRfD`PRZs8y=i+dGD~zGpHgmcAtPRf_ivu$ qfs~qr>BlpU1b$LfzxMC?`IGrq5(EFcm*~2HqSMpW&t;ucLK6U#*A&PA literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_h_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_h_image.asset.taml new file mode 100644 index 000000000..32efa6b20 --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_h_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_n.png b/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_n.png new file mode 100644 index 0000000000000000000000000000000000000000..14acfdac48a9ef5530f6b97278b891723daa2637 GIT binary patch literal 619 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4uLSEsD@VqP*9@8HKHUqKdq!Zu_%=xATcwqM9$cc z0dZzK3s^i0$OeH=WsD3jm=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CZofU+^GAlo(F=9kCpRrmJvDRk)1eEI9@l|TOG%>Qd9 zi-=F+YfN=;Wt!Lcd&;G#FMLjyrlu9YuKs28+$qgo(t%mWOKSH{{;dnl#e=*)|13S} zwRZ*U)rv*3AKS!L=I$2znRUUrZrZyAyq1h%s&`%XdRg%7j$6FeUv;W*HV_j>A^wZc|brhnJeta~}R-_6Qr@q6J(>uTK}T->uh&meBmezRTH z4>)dchi4wNi9XPn+3Niu;?gql1-CDr$TnTWeeziJiqb1P45ma~IMTZCN>kmOcJ( literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_n_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_n_image.asset.taml new file mode 100644 index 000000000..c20b302c3 --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/pasteUp_terr_n_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_d.png b/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_d.png new file mode 100644 index 0000000000000000000000000000000000000000..75183a131e37a1a11bd2de981b823c9a55e84225 GIT binary patch literal 745 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4uLSEsD@VqP*9@8HKHUqKdq!Zu_%=xATcwqM9$cc z0dZzK3s^i0$OeH=WsD3jm=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CZ9WPsMfzWq z`XW~)si{FyA1nUcmOsWW&gjEDqAEY4`A&4tpx z2GdW=&RkZ>_<;35&EB~AkIn{i2<=?=x@vFS`Ilw8&u`1UFVcO~*go2TNBQ_KXHKEo z1y{4~GAl5w2wVN!hF^KpiRahuyGPhgIkCt^Nsv8&p`mE!o>QL~xkcaU+54O(yl54# z^O|ttVe5P$6)CI#YL{+QX7F^h2wdN_PM%9q?f&)l#&6;Mlf!@M_V5NJGwuV$m#3?r J%Q~loCIGD)`Hlbp literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_d_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_d_image.asset.taml new file mode 100644 index 000000000..9e578c7d4 --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_d_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_h.png b/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_h.png new file mode 100644 index 0000000000000000000000000000000000000000..cdb640408a9e24dca21854941d38aced7c95fbc2 GIT binary patch literal 661 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjKtYKT*NBqf{Irtt#G+J&fW*wa59r`^%bvYPO|Dc&2%JYB6vCIjjs)jI0cdK$aH}OGDWp*Jv;@gTzyvgh z39K^6(gMhW>M}Gi0Lfl|wp(%Uv-mAQ+gvj|EZK0HwT4MrPpEuGbaBfugI3m@ha8h1`nkIV&bH-wTw3*kORAz-f8$Q!PcGjx z9?7pO?C965?k-=re}c_LXPL)pbKRZ8Jj|7Lc>G=+pua@=qPNeI&ygp%Ub=1R;L)9P zWJ8BdpycHrE#H51EuFIVq0JX@A=k)T&p*h{{?QW|v()fDf4P-X*R45^q{}wWy2oXl zc}CuK-V60<8~d359Lmjk)n*f@ELNrJUn0)Ecar)m>+@<^{pI&N7ybN_d4u!oyp!`@ bJ%3{VbP0l+XkKm&4jE literal 0 HcmV?d00001 diff --git a/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_h_image.asset.taml b/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_h_image.asset.taml new file mode 100644 index 000000000..86434b8be --- /dev/null +++ b/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_h_image.asset.taml @@ -0,0 +1,3 @@ + diff --git a/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_n.png b/Templates/BaseGame/game/tools/worldEditor/images/paste_terr_n.png new file mode 100644 index 0000000000000000000000000000000000000000..b7cfccb3b02a58b557e824d2d7e8f47430ea386e GIT binary patch literal 556 zcmeAS@N?(olHy`uVBq!ia0vp^Qa~)m!3HGnb@XfnQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4uLSEsD@VqP*9@8HKHUqKdq!Zu_%=xATcwqM9$cc z0dZzK3s^i0$OeH=WsD3jm=QFZr3^r+3G56kK$QkY#s-WFAf|$BWL*F;X$p`H0!%=2 znZPQ8EG>X6s4hbT1CZATX;C*bH8tkD3R%e86nnBr*ZUT|zxVN}Q{RDjUqv~OC`M-o zSI!-b%LNW;yvudD6gFS>&8!gJ=o7lljCUI6E!msv_mI^#SFz>7x%}U0TAkugc23&+ zXysguVAB_K;=Avvu9h-UsO}ZE4pg)BxTIsxcXWAtr}&j#_DN<3X5^UPn^iKY?Arqu zy>0us-oNZSAQj=_zA|}sR(F}n_F~^k>s_~