Game Development Community

dev|Pro Game Development Curriculum

Forest Editor - DropToGround Brush (Updated)

by Kevin Mitchell · 06/02/2013 (3:36 pm) · 5 comments

Just something I attempted to make that may help with readjustments to the forest elements after being placed. This will help all those who like me make terrain changes after placing everything and not wanting to manually drag all those objects out or erase and start again.




//game/tools/forestEditor/main.cs
//line: 50
   %map = new ActionMap();
   %map.bindCmd( keyboard, "1", "ForestEditorSelectModeBtn.performClick();", "" ); // Select
   %map.bindCmd( keyboard, "2", "ForestEditorMoveModeBtn.performClick();", "" );   // Move
   %map.bindCmd( keyboard, "3", "ForestEditorRotateModeBtn.performClick();", "" ); // Rotate
   %map.bindCmd( keyboard, "4", "ForestEditorScaleModeBtn.performClick();", "" );  // Scale
   %map.bindCmd( keyboard, "5", "ForestEditorPaintModeBtn.performClick();", "" );  // Paint
   %map.bindCmd( keyboard, "6", "ForestEditorEraseModeBtn.performClick();", "" );  // Erase
   %map.bindCmd( keyboard, "7", "ForestEditorEraseSelectedModeBtn.performClick();", "" );  // EraseSelected   
   //RPG Edit
   %map.bindCmd( keyboard, "8", "ForestEditorDropToGroundModeBtn.performClick();", "" );  // DropTheBeat   
	//END Editor



//game/tools/forestEditor/main.cs
//line: 172

      %mode = ForestTools->BrushTool.mode;
      switch$ (%mode)
      {
         case "Paint":
            ForestEditorPaintModeBtn.performClick();
         case "Erase":
            ForestEditorEraseModeBtn.performClick();
         case "EraseSelected":
            ForestEditorEraseSelectedModeBtn.performClick();

         //RPG Edit
         case "DropToGround":
            ForestEditorDropToGroundModeBtn.performClick();
         //RPG END
      }



//tools/worldEditor/gui/ToolsPaletteGroups/ForestEditorPalette.ed.gui
//line: append new button

   new GuiBitmapButtonCtrl(ForestEditorDropToGroundModeBtn) {
      canSaveDynamicFields = "0";
      internalName = "ForestEditorDropToGroundMode";
      Enabled = "1";
      isContainer = "0";
      Profile = "GuiButtonProfile";
      HorizSizing = "right";
      VertSizing = "bottom";
      Position = "0 0";
      Extent = "25 19";
      MinExtent = "8 2";
      canSave = "1";
      Visible = "1";
      Command = "ForestEditorGui.setActiveTool( ForestTools->BrushTool ); ForestTools->BrushTool.mode = "DropToGround";";  
      tooltipprofile = "GuiToolTipProfile";
      ToolTip = "Drop To Ground (8)";
      hovertime = "1000";
      bitmap = "tools/foresteditor/images/paint-forest-btn";
      buttonType = "RadioButton";
      useMouseEvents = "0";
   };





Code Changes:


//source/foresteditor/forestBrushTool.cpp
//line: 53

ImplementEnumType( ForestBrushMode,
   "Active brush mode type.n"
   "@internalnn")
   { ForestBrushTool::Paint, "Paint", "Creates Items based on the Elements you have selected.n" },
   { ForestBrushTool::Erase, "Erase", "Erases Items of any Mesh type.n" },
   { ForestBrushTool::EraseSelected, "EraseSelected", "Erases items of a specific type.n"  },
         //RPG Edit
   { ForestBrushTool::DropToGround, "DropToGround", "Drops items of a specific type to the ground.n"  },
EndImplementEnumType;
         //RPG End




//source/foresteditor/forestBrushTool.cpp
//line: 229


   if ( mMode == Paint )
      brushColor = ColorI::BLUE;
   else if ( mMode == Erase )
      brushColor = ColorI::RED;
         //RPG Edit
   else if ( mMode == DropToGround )
	   brushColor = ColorI::WHITE;   
         //RPG End
   else if ( mMode == EraseSelected )
      brushColor.set( 150, 0, 0 );

   if ( mMode == Paint || mMode == EraseSelected )
   {
      if ( mElements.empty() )
      {
         brushColor.set( 140, 140, 140 );
      }
   }






//source/foresteditor/forestBrushTool.cpp
//line: 269


   if ( mMode == Paint )
      text = "Forest Editor ( Paint Tool ) - This brush creates Items based on the Elements you have selected.";
   else if ( mMode == Erase )
      text = "Forest Editor ( Erase Tool ) - This brush erases Items of any Mesh type.";
         //RPG Edit
   else if ( mMode == DropToGround )
      text = "Forest Editor ( DropToGround Tool ) - This brush Drop To Ground Items of any Mesh type.";
         //RPG End
   else if ( mMode == EraseSelected )   
      text = "Forest Editor ( Erase Selected ) - This brush erases Items based on the Elements you have selected.";







//source/foresteditor/forestBrushTool.cpp
//line: 318

void ForestBrushTool::_action( const Point3F &point )
{
   if ( mMode == Paint )
      _paint( point );
   else if ( mMode == Erase || mMode == EraseSelected )
      _erase( point );
   else if ( mMode == DropToGround)
      _DropToGround( point );
   
}







//source/foresteditor/forestBrushTool.cpp
//line: 525

         //RPG Edit
void ForestBrushTool::_DropToGround( const Point3F &point )
{
   AssertFatal( mForest, "ForestBrushTool::_erase() - Can't erase without a Forest!" );

   // First grab all the forest items around the point.
   ForestItemVector trees;
   if ( mForest->getData()->getItems( point.asPoint2F(), mSize, &trees ) == 0 )
      return;
   
   if ( trees.empty() )
      return;

   // Number of trees to erase depending on pressure.
   S32 dropCount = getMax( (S32)mCeil( (F32)trees.size() * mPressure ), 0 );
   
   // Initialize an MRandomDeck with trees under the brush.
   MRandomDeck<ForestItem> deck(&mRandom);
   deck.addToPile( trees );
   deck.shuffle();

   ForestItem currentTree;
   
   // Draw eraseCount number of trees from MRandomDeck, adding them to our erase action.
   for ( U32 i = 0; i < dropCount; i++ )
   {
		deck.draw(&currentTree);
		
		//GetObject Data
		// Get current object transform matrix
		MatrixF SRC_xform = currentTree.getTransform();
		// Get rotations from transform matrix
		VectorF SRC_vec;
		SRC_xform.getColumn(1,&SRC_vec);
		// Get X-vector for roll calculation
		Point3F SRC_xv;
		SRC_xform.getColumn(0,&SRC_xv);
		// Get Position
		Point3F SRC_pos;
		SRC_xform.getColumn(3,&SRC_pos);
		Point3F mountpos;

		F32 contactZ;
		 // Look for the ground at this position.
         if ( !getGroundAt( Point3F( SRC_pos.x, SRC_pos.y , SRC_pos.z ), 
                                     &contactZ, 
                                     NULL ) )
         {
            break;
         }


		contactZ-=0.5;

		SRC_pos.z=contactZ;		
		SRC_xform.setColumn(3,SRC_pos);

	    currentTree = mForest->getData()->updateItem( currentTree.getKey(), currentTree.getPosition(), currentTree.getData(), SRC_xform, currentTree.getScale() );   

   }
}
         //RPG End









//source/foresteditor/forestBrushTool.h
//line: 39


   enum BrushMode
   {
      Paint = 0,
      Erase,
      EraseSelected,
         //RPG Edit
      DropToGround
         //RPG End
   };












//source/foresteditor/forestBrushTool.h
//line: 75

   virtual void _action( const Point3F &point );
   virtual void _paint( const Point3F &point );
   virtual void _erase( const Point3F &point );
         //RPG Edit
   virtual void _DropToGround( const Point3F &point );
         //RPG End





Notes:

I wanted to add an adjustable sink like in the orginal add code. Currently it's hard coded to 0.5.



Edit:

Forgot about my video obsession:

T3D Forest Editor - Drop To Ground


#1
06/03/2013 (9:11 am)
Cool! This is something that the editor has needed for a long time.

(Can we get the code re-posted without the HTML character tags?)
#2
06/03/2013 (10:43 am)
Awe that's not suppose to happen under code flags... I'll correct this when i get home.
#3
06/07/2013 (1:44 pm)
Much better. Thanks!
#4
07/08/2013 (12:27 am)
Very handy, thanks for sharing Kevin!
#5
10/06/2013 (9:59 am)
A wonderful concept Kevin, are you a mind reader? I've needed something like this forever. Thanks for thaking the time to do this and share it with us!