Skip to content
91 changes: 91 additions & 0 deletions GeneralsMD/Code/Tools/WorldBuilder/include/BrushTool.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,40 @@ class WorldHeightMapEdit;
/// Height brush tool.
class BrushTool : public Tool
{
public:
enum {
MIN_RAISE_LOWER = 1,
MAX_RAISE_LOWER = 21,
MIN_SMOOTH_RADIUS = 1,
MAX_SMOOTH_RADIUS = 5,
MIN_SMOOTH_RATE = 1,
MAX_SMOOTH_RATE = 10
};

enum EBrushMode {
BRUSH_MODE_RAISE,
BRUSH_MODE_LOWER,
BRUSH_MODE_SET,
BRUSH_MODE_SMOOTH
};

protected:
enum {MIN_DELAY_TIME = 60};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this name is too generic. I would suggest to add what the delay time is for in the name.


WorldHeightMapEdit *m_htMapEditCopy; ///< ref counted.
WorldHeightMapEdit *m_htMapFeatherCopy; ///< ref counted.
WorldHeightMapEdit *m_htMapRateCopy; ///< ref counted (smooth mode).

static Int m_brushWidth;
static Int m_brushFeather;
static Bool m_brushSquare;
static Int m_brushHeight;
static Int m_raiseLowerAmount;
static Int m_smoothRadius;
static Int m_smoothRate;

EBrushMode m_activeMode;
Int m_lastMoveTime;

public:
BrushTool(void);
Expand All @@ -48,9 +74,68 @@ class BrushTool : public Tool
static Int getWidth(void) {return m_brushWidth;}; ///<Returns width.
static Int getFeather(void) {return m_brushFeather;}; ///<Returns feather.
static Int getHeight(void) {return m_brushHeight;}; ///<Returns height.
static Int getRaiseLowerAmount(void) {return m_raiseLowerAmount;};
static Int getSmoothRadius(void) {return m_smoothRadius;};
static Int getSmoothRate(void) {return m_smoothRate;};
static void setWidth(Int width);
static void setFeather(Int feather);
static void setHeight(Int height);
static void setRaiseLowerAmount(Int amount);
static void setSmoothRadius(Int radius);
static void setSmoothRate(Int rate);
static EBrushMode getModeFromModifiers(Bool shiftDown, Bool ctrlDown);
static EBrushMode getPreviewModeFromKeys();
static const char* getModeDisplayName(EBrushMode mode);
static void getModeHintStrings(char *primaryBuf, Int primaryBufSize, char *secondaryBuf, Int secondaryBufSize);

// Helper functions for brush hint drawing (shared between 2D and 3D views)
struct BrushHintInfo {
Bool shouldShow;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isVisible perhaps? The use of the word 'should' is too vague.

reading further, the only case it is used is !info.shouldShow, so maybe call it isHidden instead and avoid the logic inversion

Bool shouldClear;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the difference between shouldClear and shouldShow. both in the end call yield a call to clearBrushModeHintState.

shouldClear must be renamed e.g. isCleared

EBrushMode currentMode;
Int modeInt;
CPoint hintPos;
};
static Bool getBrushHintInfo(BrushHintInfo &info, char *hintTextBuf, Int hintTextBufSize, const CPoint &hintPos, Int lastBrushMode);

// Shared smoothing algorithm function (processes a single cell)
static void applySmoothingAlgorithm(
WorldHeightMapEdit *editMap,
WorldHeightMapEdit *featherMap,
Int i, Int j,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i and j needs explaining or better naming

I presume these are cell coordinates? Then cellX and cellY would be better.

Int rate,
Int smoothRadius,
Int minRadius,
Int maxRadius,
CWorldBuilderDoc *pDoc);

// Shared brush iteration with rate accumulation - returns true if rate buffer overflow occurred

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returning true while - what I presume is ` an error (buffer overflow) occurred is counterintuitive.

static Bool applyBrushWithRateAccumulation(
WorldHeightMapEdit *editMap,
WorldHeightMapEdit *featherMap,
WorldHeightMapEdit *rateMap,
const CPoint &ndx,
Int brushWidth,
Int rateMultiplier,
Int smoothRadius,
Int minRadius,
Int maxRadius,
CWorldBuilderDoc *pDoc);

// Shared rate buffer reset
static void resetSmoothingBuffers(
WorldHeightMapEdit *editMap,
WorldHeightMapEdit *featherMap,
WorldHeightMapEdit *rateMap);

// Helper to create a partial range for height map updates
static IRegion2D makePartialRange(const CPoint &ndx, Int brushWidth);

// Helper to calculate blend factor (square or round)
static Real calcBlendFactor(const CPoint &ndx, Int i, Int j, Int width, Int feather, Bool square);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would name it calculateBlendFactor for easier reading.
i and j is maybe cellX and cellY again?

A boolean should be named in a way that is clear it is a boolean, e.g. isSquare


// Helper to get effective brush width including feather
static Int getEffectiveBrushWidth(Int baseWidth, Int feather);

public:
virtual void mouseDown(TTrackingMode m, CPoint viewPt, WbView* pView, CWorldBuilderDoc *pDoc);
Expand All @@ -60,4 +145,10 @@ class BrushTool : public Tool
virtual void activate(); ///< Become the current tool.
virtual Bool followsTerrain(void) {return false;};

protected:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these can be made private

EBrushMode determineBrushMode() const;
void applySetHeightBrush(const CPoint &ndx, Int brushWidth, CWorldBuilderDoc *pDoc);
void applyRaiseLowerBrush(const CPoint &ndx, Int brushWidth, Bool raising, CWorldBuilderDoc *pDoc);
void applySmoothBrush(const CPoint &ndx, Int brushWidth, CWorldBuilderDoc *pDoc);
void resetSmoothRateBuffer();
};
1 change: 1 addition & 0 deletions GeneralsMD/Code/Tools/WorldBuilder/include/DrawObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class DrawObject : public RenderObjClass
static void enableFeedback(void) {m_disableFeedback = false;};
static Bool isFeedbackEnabled(void) { return !m_disableFeedback;};
static void setFeedbackPos(Coord3D pos);
static Coord3D getFeedbackPos() { return m_feedbackPoint; }

static void setWaypointDragFeedback(const Coord3D &start, const Coord3D &end);
static void setRampFeedbackParms(const Coord3D *start, const Coord3D *end, Real rampWidth);
Expand Down
7 changes: 7 additions & 0 deletions GeneralsMD/Code/Tools/WorldBuilder/include/WorldBuilderView.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class CWorldBuilderView : public WbView
CPoint m_scrollMin; ///< The minimum scrollbar positions.
CPoint m_scrollMax; ///< The maximum scroll bar positions.

HintDrawState m_brushHintState; ///< Flicker reduction state for brush mode hint

protected:

/// Draw a texture bitmap in a rectangle in the dc.
Expand All @@ -98,6 +100,11 @@ class CWorldBuilderView : public WbView
/// Draw the object's icon in the dc at a given point.
void drawObjectInView(CDC *pDc, MapObject *pMapObj);

/// Draw brush mode hint on canvas
void drawBrushModeHint(CDC *pDc, CRgn *pUpdateRgn = NULL);
/// Clears the brush mode hint state
void clearBrushModeHintState();

public:
/// Get the current draw size in pixels in the 2d window of one height map cell.
Int getCellSize(void) {return m_cellSize;}
Expand Down
21 changes: 20 additions & 1 deletion GeneralsMD/Code/Tools/WorldBuilder/include/brushoptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "WBPopupSlider.h"
#include "OptionsPanel.h"
#include "BrushTool.h"
/////////////////////////////////////////////////////////////////////////////
/// BrushOptions modeless (floating) dialog - allows entry and display of brush width and feather.

Expand All @@ -35,7 +36,13 @@ class BrushOptions : public COptionsPanel , public PopupSliderOwner
FREQ_BRUSH_TICKS=10,
MIN_FEATHER=0,
FREQ_FEATHER_TICKS=4,
MAX_FEATHER=20};
MAX_FEATHER=20,
MIN_RAISE_LOWER = BrushTool::MIN_RAISE_LOWER,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these even used anywhere? I can only find usage of BrushTool::

MAX_RAISE_LOWER = BrushTool::MAX_RAISE_LOWER,
MIN_SMOOTH_RADIUS = BrushTool::MIN_SMOOTH_RADIUS,
MAX_SMOOTH_RADIUS = BrushTool::MAX_SMOOTH_RADIUS,
MIN_SMOOTH_RATE = BrushTool::MIN_SMOOTH_RATE,
MAX_SMOOTH_RATE = BrushTool::MAX_SMOOTH_RATE};

BrushOptions(CWnd* pParent = NULL); // standard constructor

Expand Down Expand Up @@ -64,6 +71,9 @@ class BrushOptions : public COptionsPanel , public PopupSliderOwner
afx_msg void OnChangeFeatherEdit();
afx_msg void OnChangeSizeEdit();
afx_msg void OnChangeHeightEdit();
afx_msg void OnChangeRaiseLowerEdit();
afx_msg void OnChangeSmoothRadiusEdit();
afx_msg void OnChangeSmoothRateEdit();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()

Expand All @@ -72,16 +82,25 @@ class BrushOptions : public COptionsPanel , public PopupSliderOwner
static Int m_currentWidth; ///< current brush width in the ui.
static Int m_currentFeather; ///< current feather width in the ui.
static Int m_currentHeight;
static Int m_currentRaiseLower;
static Int m_currentSmoothRadius;
static Int m_currentSmoothRate;

Bool m_updating; ///<true if the ui is updating itself.
WBPopupSliderButton m_brushWidthPopup;
WBPopupSliderButton m_brushFeatherPopup;
WBPopupSliderButton m_brushHeightPopup;
WBPopupSliderButton m_raiseLowerPopup;
WBPopupSliderButton m_smoothRadiusPopup;
WBPopupSliderButton m_smoothRatePopup;

public:
static void setWidth(Int width);
static void setFeather(Int feather);
static void setHeight(Int height);
static void setRaiseLowerAmount(Int amount);
static void setSmoothRadius(Int radius);
static void setSmoothRate(Int rate);

public:

Expand Down
63 changes: 62 additions & 1 deletion GeneralsMD/Code/Tools/WorldBuilder/include/wbview.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,64 @@ enum RulerTypeEnum {
RULER_CIRCLE,
};

/////////////////////////////////////////////////////////////////////////////
// HintDrawState - reusable flicker reduction state for on-screen text hints
//
// Usage:
// 1. Call beginFrame() at start of each paint/render cycle
// 2. Call needsUpdate() to check if hint position changed significantly
// 3. Call commitUpdate() after drawing to store the new state
// 4. Call reset() when hint should be hidden

struct HintDrawState {
static const Int HINT_UPDATE_THRESHOLD = 15; ///< Pixel threshold for hint position updates
static const Int HINT_OFFSET_X = 20;
static const Int HINT_OFFSET_Y = 20;
static const Int HINT_PADDING = 6;

Int lastMode;
CRect lastRect;
CPoint lastPos;
Bool drawnThisFrame;

HintDrawState() : lastMode(-1), lastPos(-10000, -10000), drawnThisFrame(false) {}

void reset() {
if (!lastRect.IsRectEmpty()) {
lastRect.SetRectEmpty();
lastMode = -1;
lastPos = CPoint(-10000, -10000);
}
}

void beginFrame() { drawnThisFrame = false; }

bool needsUpdate(CPoint newPos, Int newMode, Int threshold = HINT_UPDATE_THRESHOLD) const {
if (newMode != lastMode) return true;
if (lastRect.IsRectEmpty()) return true;
Int dx = abs(newPos.x - lastPos.x);
Int dy = abs(newPos.y - lastPos.y);
return (dx > threshold || dy > threshold);
}

void commitUpdate(CPoint pos, const CRect& rect, Int mode) {
lastPos = pos;
lastRect = rect;
lastMode = mode;
drawnThisFrame = true;
}

/// Compute hint rect from position and text size
static CRect computeHintRect(CPoint pos, Int textWidth, Int textHeight) {
CRect rect;
rect.left = pos.x - HINT_PADDING;
rect.top = pos.y - textHeight - HINT_PADDING;
rect.right = pos.x + textWidth + HINT_PADDING;
rect.bottom = pos.y + HINT_PADDING;
return rect;
}
};

/////////////////////////////////////////////////////////////////////////////
// WbView view

Expand Down Expand Up @@ -241,10 +299,13 @@ class WbView : public CView
afx_msg void OnShowTerrain();
afx_msg void OnUpdateShowTerrain(CCmdUI* pCmdUI);
afx_msg int OnCreate(LPCREATESTRUCT lpcs);

afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint point);

//}}AFX_MSG
DECLARE_MESSAGE_MAP()

protected:
Bool handleBrushMouseWheel(UINT nFlags, short zDelta);
};

/////////////////////////////////////////////////////////////////////////////
Expand Down
5 changes: 5 additions & 0 deletions GeneralsMD/Code/Tools/WorldBuilder/include/wbview3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ class WbView3d : public WbView, public DX8_CleanupHook
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnPaint();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnDestroy();
Expand Down Expand Up @@ -216,6 +217,8 @@ class WbView3d : public WbView, public DX8_CleanupHook
Int m_pickPixels;
Int m_partialMapSize;

HintDrawState m_brushHintState; ///< Flicker reduction state for brush mode hint

protected:

UINT getLastDrawTime();
Expand All @@ -225,6 +228,8 @@ class WbView3d : public WbView, public DX8_CleanupHook
void drawCircle( HDC hdc, const Coord3D & centerPoint, Real radius, COLORREF color );
void drawLabels(HDC hdc);
void drawLabels(void);
void drawBrushModeHint(HDC hdc);
void clearBrushModeHintState();
void shutdownWW3D();
void killTheTimer();
void render();
Expand Down
33 changes: 25 additions & 8 deletions GeneralsMD/Code/Tools/WorldBuilder/res/WorldBuilder.rc
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ BEGIN
CONTROL "",ID_SLIDER,"Static",SS_BLACKFRAME,0,1,19,62
END

IDD_BRUSH_OPTIONS DIALOG DISCARDABLE 0, 0, 118, 138
IDD_BRUSH_OPTIONS DIALOG DISCARDABLE 0, 0, 118, 300
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Height Brush Options"
FONT 8, "MS Sans Serif"
Expand All @@ -504,16 +504,33 @@ BEGIN
EDITTEXT IDC_FEATHER_EDIT,71,55,17,12,ES_AUTOHSCROLL
RTEXT "Size in cells:",IDC_STATIC,24,56,39,10
PUSHBUTTON "1",IDC_SIZE_POPUP,93,11,8,12,BS_BITMAP
GROUPBOX "Brush Width:",IDC_STATIC,1,1,113,34
GROUPBOX "Brush Feather Width:",IDC_STATIC,1,43,113,39
GROUPBOX "Brush Width (Shift + Scroll Wheel):",IDC_STATIC,1,1,113,34
GROUPBOX "Brush Feather Width (Ctrl + Scroll Wheel):",IDC_STATIC,1,43,113,39
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect there is no other way to tell about key mappings other than hard coding into strings? How do we know to update these strings when changing key mappings?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don' think so. This is also consistent with the rest of the file. Lots of hardcoded key mappings.

PUSHBUTTON "1",IDC_FEATHER_POPUP,93,55,8,12,BS_BITMAP
LTEXT "35 FT.",IDC_WIDTH_LABEL,71,24,43,8
LTEXT "35 FT.",IDC_HEIGHT_LABEL,71,120,36,8
GROUPBOX "Brush Height:",IDC_STATIC,1,90,113,45
EDITTEXT IDC_HEIGHT_EDIT,71,105,17,12,ES_AUTOHSCROLL
RTEXT "Size in 1/8 cells:",IDC_STATIC,0,107,63,10
PUSHBUTTON "1",IDC_HEIGHT_POPUP,93,106,8,12,BS_BITMAP
LTEXT "35 FT.",IDC_FEATHER_LABEL,71,68,41,8
GROUPBOX "Raise / Lower Amount (LMB / Shift+LMB):",IDC_STATIC,1,90,113,34
EDITTEXT IDC_RAISELOWER_EDIT,71,105,17,12,ES_AUTOHSCROLL
RTEXT "Amount:",IDC_STATIC,23,106,40,8
PUSHBUTTON "1",IDC_RAISELOWER_POPUP,93,105,8,12,BS_BITMAP
LTEXT "0.0 FEET.",IDC_RAISELOWER_LABEL,71,118,43,8
GROUPBOX "Set Height (Ctrl + LMB):",IDC_STATIC,1,132,113,34
EDITTEXT IDC_HEIGHT_EDIT,71,147,17,12,ES_AUTOHSCROLL
RTEXT "Size in 1/8 cells:",IDC_STATIC,0,149,63,10
PUSHBUTTON "1",IDC_HEIGHT_POPUP,93,148,8,12,BS_BITMAP
LTEXT "35 FT.",IDC_HEIGHT_LABEL,71,160,36,8
GROUPBOX "Smooth (Ctrl + Shift + LMB):",IDC_STATIC,1,174,113,50
EDITTEXT IDC_RADIUS_EDIT,71,189,17,12,ES_AUTOHSCROLL
RTEXT "Radius:",IDC_STATIC,23,190,40,8
PUSHBUTTON "1",IDC_RADIUS_POPUP,93,189,8,12,BS_BITMAP
EDITTEXT IDC_RATE_EDIT,71,205,17,12,ES_AUTOHSCROLL
RTEXT "Rate:",IDC_STATIC,23,206,40,8
PUSHBUTTON "1",IDC_RATE_POPUP,93,205,8,12,BS_BITMAP
GROUPBOX "Brush Modes:",IDC_STATIC,1,232,113,65
LTEXT "LMB - Raise Height",IDC_STATIC,5,242,108,8
LTEXT "Shift + LMB - Lower Height",IDC_STATIC,5,252,108,8
LTEXT "Ctrl + LMB - Set Height",IDC_STATIC,5,262,108,8
LTEXT "Ctrl + Shift + LMB - Smooth",IDC_STATIC,5,272,108,8
END

IDD_TERRAIN_MATERIAL DIALOG DISCARDABLE 0, 0, 200, 286
Expand Down
4 changes: 4 additions & 0 deletions GeneralsMD/Code/Tools/WorldBuilder/res/resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,10 @@
#define IDC_PSEd_Color1 1031
#define IDC_FEATHER_LABEL 1032
#define IDC_WIDTH_LABEL3 1032
#define IDC_RAISELOWER_EDIT 1800

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Place them in order of number.

Also, why 1800? something like 2000 + comment would be more clear that this is custom superhackers stuff

#define IDC_RAISELOWER_POPUP 1801
#define IDC_RAISELOWER_LABEL 1802
#define IDC_MODE_LEGEND 1803
#define IDC_TERRAIN_TREEVIEW 1033
#define IDC_SLIDER3 1034
#define IDC_SWAP_TEXTURES 1035
Expand Down
Loading