Editor: Brush preview and Shift-Key for filling brush

Editor needs to render more often for the preview function.
This commit is contained in:
titison 2021-03-19 16:06:38 +01:00
parent 880730e5e1
commit 0201af7ccf
9 changed files with 83 additions and 38 deletions

View File

@ -105,6 +105,8 @@ MainWindow::MainWindow(string appPath)
resourceUnderMouse=0; resourceUnderMouse=0;
objectUnderMouse=0; objectUnderMouse=0;
shiftModifierKey = false;
// default values for random height calculation that turned out to be quite useful // default values for random height calculation that turned out to be quite useful
randomWithReset=true; randomWithReset=true;
randomMinimumHeight=-300; randomMinimumHeight=-300;
@ -157,8 +159,8 @@ void MainWindow::init(string fname) {
menuBar->Append(menuFile, wxT("&File")); menuBar->Append(menuFile, wxT("&File"));
//edit //edit
menuEdit = new wxMenu(); menuEdit = new wxMenu();
menuEdit->Append(miEditUndo, wxT("&Undo\tCTRL+Z")); menuEdit->Append(miEditUndo, wxT("&Undo\tCTRL+Z"));
menuEdit->Append(miEditRedo, wxT("&Redo\tCTRL+Y")); menuEdit->Append(miEditRedo, wxT("&Redo\tCTRL+Y"));
menuEdit->AppendSeparator(); menuEdit->AppendSeparator();
// menuEdit->Append(miEditReset, wxT("Rese&t...")); // menuEdit->Append(miEditReset, wxT("Rese&t..."));
@ -313,6 +315,7 @@ void MainWindow::init(string fname) {
SetStatusText(wxT(".mgm"), siFILE_TYPE); SetStatusText(wxT(".mgm"), siFILE_TYPE);
SetStatusText(wxT("Object: None (Erase)"), siCURR_OBJECT); SetStatusText(wxT("Object: None (Erase)"), siCURR_OBJECT);
SetStatusText(wxT("Brush: Height"), siBRUSH_TYPE); SetStatusText(wxT("Brush: Height"), siBRUSH_TYPE);
SetStatusText(wxT("Type: Overwrite"), siBRUSH_OVERWRITE);
SetStatusText(wxT("Value: 0"), siBRUSH_VALUE); SetStatusText(wxT("Value: 0"), siBRUSH_VALUE);
SetStatusText(wxT("Radius: 1"), siBRUSH_RADIUS); SetStatusText(wxT("Radius: 1"), siBRUSH_RADIUS);
SetStatusText(wxT("Pos (Ingame): 0"), siPOS_VALUE); SetStatusText(wxT("Pos (Ingame): 0"), siPOS_VALUE);
@ -606,20 +609,18 @@ void MainWindow::onMouseMove(wxMouseEvent &event, int x, int y) {
if(program == NULL) { if(program == NULL) {
return; return;
} }
bool repaint = false; mouse_pos.first = program->getCellX(x);
mouse_pos.second = program->getCellY(y);
if (event.LeftIsDown()) { if (event.LeftIsDown()) {
change(x, y); change(x, y);
repaint = true;
} else if (event.MiddleIsDown()) { } else if (event.MiddleIsDown()) {
int dif = (y - lastY); int dif = (y - lastY);
if (dif != 0) { if (dif != 0) {
program->incCellSize(dif / abs(dif)); program->incCellSize(dif / abs(dif));
repaint = true;
} }
} else if (event.RightIsDown()) { } else if (event.RightIsDown()) {
program->setOfset(x - lastX, y - lastY); program->setOfset(x - lastX, y - lastY);
repaint = true; } else {
} else {
int currResource = program->getResource(x, y); int currResource = program->getResource(x, y);
if (currResource > 0) { if (currResource > 0) {
SetStatusText(wxT("Resource: ") + ToUnicode(resource_descs[currResource]), siCURR_OBJECT); SetStatusText(wxT("Resource: ") + ToUnicode(resource_descs[currResource]), siCURR_OBJECT);
@ -648,10 +649,9 @@ void MainWindow::onMouseMove(wxMouseEvent &event, int x, int y) {
lastX = x; lastX = x;
lastY = y; lastY = y;
if (repaint) { wxPaintEvent ev;
wxPaintEvent ev; onPaint(ev);
onPaint(ev);
}
event.Skip(); event.Skip();
} }
@ -701,8 +701,12 @@ void MainWindow::onPaint(wxPaintEvent &event) {
void MainWindow::refreshMapRender() { void MainWindow::refreshMapRender() {
//printf("refreshMapRender map\n"); //printf("refreshMapRender map\n");
if(program && glCanvas) { if(program && glCanvas) {
program->renderMap(glCanvas->GetClientSize().x, glCanvas->GetClientSize().y); if(enabledGroup == ctLocation) {
program->renderMap(glCanvas->GetClientSize().x, glCanvas->GetClientSize().y);
} else {
program->renderMap(glCanvas->GetClientSize().x, glCanvas->GetClientSize().y, &mouse_pos, &radius);
}
glCanvas->SwapBuffers(); glCanvas->SwapBuffers();
} }
} }
@ -1245,6 +1249,7 @@ void MainWindow::onMenuViewHelp(wxCommandEvent &event) {
You can change brush in the same category with key 1-9\n\ You can change brush in the same category with key 1-9\n\
and change category with their first letter (keys S, R, O, G, H)\n\ and change category with their first letter (keys S, R, O, G, H)\n\
Press Space to set brush to the resource or object under the mouse cursor\n\ Press Space to set brush to the resource or object under the mouse cursor\n\
Hold Shift to fill only empty spaces with the current object or resource\ninstead of replacing everything under the brush.\n\
To center things in the map shift it with Shift-Up/Down/Left/Right keys\n\ To center things in the map shift it with Shift-Up/Down/Left/Right keys\n\
Height tool (blue) builds with integer height steps 0-20, \nwhile Gradient tool (red) uses any real number \n\ Height tool (blue) builds with integer height steps 0-20, \nwhile Gradient tool (red) uses any real number \n\
Units can go over water as long as it is less than 1.5 deep\n\n\ Units can go over water as long as it is less than 1.5 deep\n\n\
@ -1341,10 +1346,10 @@ void MainWindow::change(int x, int y) {
program->changeMapSurface(x, y, surface, radius); program->changeMapSurface(x, y, surface, radius);
break; break;
case ctObject: case ctObject:
program->changeMapObject(x, y, object, radius); program->changeMapObject(x, y, object, radius, !shiftModifierKey);
break; break;
case ctResource: case ctResource:
program->changeMapResource(x, y, resource, radius); program->changeMapResource(x, y, resource, radius, !shiftModifierKey);
break; break;
case ctLocation: case ctLocation:
program->changeStartLocation(x, y, startLocation - 1); program->changeStartLocation(x, y, startLocation - 1);
@ -1382,7 +1387,7 @@ void MainWindow::uncheckRadius() {
} }
} }
void MainWindow::onKeyDown(wxKeyEvent &e) { void MainWindow::onKeyDown(wxKeyEvent &e) {
if(program == NULL) { if(program == NULL) {
return; return;
} }
@ -1475,11 +1480,29 @@ void MainWindow::uncheckRadius() {
program->setUndoPoint(ctAll); program->setUndoPoint(ctAll);
program->shiftDown(); program->shiftDown();
setDirty(); setDirty();
} else { } else if (e.GetModifiers() == wxMOD_SHIFT) {
shiftModifierKey = true;
SetStatusText(wxT("Type: Fill"), siBRUSH_OVERWRITE);
} else {
e.Skip(); e.Skip();
} }
} }
void MainWindow::onKeyUp(wxKeyEvent &e) {
if(program == NULL) {
return;
}
if(e.GetModifiers() == wxMOD_CONTROL || e.GetModifiers() == wxMOD_ALT){
e.Skip();
}
// WARNING: don't add any Ctrl or ALt key shortcuts below those are reserved for internal menu use.
if (e.GetModifiers() != wxMOD_SHIFT) {
shiftModifierKey = false;
SetStatusText(wxT("Type: Overwrite"), siBRUSH_OVERWRITE);
}
}
BEGIN_EVENT_TABLE(MainWindow, wxFrame) BEGIN_EVENT_TABLE(MainWindow, wxFrame)
EVT_CLOSE(MainWindow::onClose) EVT_CLOSE(MainWindow::onClose)
@ -1614,6 +1637,11 @@ void GlCanvas::onKeyDown(wxKeyEvent &event) {
mainWindow->onKeyDown(event); mainWindow->onKeyDown(event);
} }
void GlCanvas::onKeyUp(wxKeyEvent &event) {
mainWindow->onKeyUp(event);
}
void GlCanvas::onPaint(wxPaintEvent &event) { void GlCanvas::onPaint(wxPaintEvent &event) {
// wxPaintDC dc(this); //N "In a paint event handler must always create a wxPaintDC object even if you do not use it. (?) // wxPaintDC dc(this); //N "In a paint event handler must always create a wxPaintDC object even if you do not use it. (?)
// mainWindow->program->renderMap(GetClientSize().x, GetClientSize().y); // mainWindow->program->renderMap(GetClientSize().x, GetClientSize().y);
@ -1625,6 +1653,7 @@ void GlCanvas::onPaint(wxPaintEvent &event) {
BEGIN_EVENT_TABLE(GlCanvas, wxGLCanvas) BEGIN_EVENT_TABLE(GlCanvas, wxGLCanvas)
EVT_KEY_DOWN(GlCanvas::onKeyDown) EVT_KEY_DOWN(GlCanvas::onKeyDown)
EVT_KEY_UP(GlCanvas::onKeyUp)
EVT_MOUSEWHEEL(GlCanvas::onMouseWheel) EVT_MOUSEWHEEL(GlCanvas::onMouseWheel)
EVT_LEFT_DOWN(GlCanvas::onMouseDown) EVT_LEFT_DOWN(GlCanvas::onMouseDown)
EVT_MOTION(GlCanvas::onMouseMove) EVT_MOTION(GlCanvas::onMouseMove)

View File

@ -51,6 +51,7 @@ enum StatusItems {
siFILE_TYPE, siFILE_TYPE,
siCURR_OBJECT, siCURR_OBJECT,
siBRUSH_TYPE, siBRUSH_TYPE,
siBRUSH_OVERWRITE,
siBRUSH_VALUE, siBRUSH_VALUE,
siBRUSH_RADIUS, siBRUSH_RADIUS,
siPOS_VALUE, siPOS_VALUE,
@ -197,6 +198,9 @@ private:
int startLocation; int startLocation;
int resourceUnderMouse; int resourceUnderMouse;
int objectUnderMouse; int objectUnderMouse;
pair<int,int> mouse_pos;
bool shiftModifierKey;
bool randomWithReset; bool randomWithReset;
int randomMinimumHeight; int randomMinimumHeight;
@ -231,6 +235,7 @@ public:
void onPaint(wxPaintEvent &event); void onPaint(wxPaintEvent &event);
void onKeyDown(wxKeyEvent &e); void onKeyDown(wxKeyEvent &e);
void onKeyUp(wxKeyEvent &e);
void onMenuFileLoad(wxCommandEvent &event); void onMenuFileLoad(wxCommandEvent &event);
void onMenuFileSave(wxCommandEvent &event); void onMenuFileSave(wxCommandEvent &event);
@ -308,6 +313,7 @@ public:
void onMouseMove(wxMouseEvent &event); void onMouseMove(wxMouseEvent &event);
void onMouseWheel(wxMouseEvent &event); void onMouseWheel(wxMouseEvent &event);
void onKeyDown(wxKeyEvent &event); void onKeyDown(wxKeyEvent &event);
void onKeyUp(wxKeyEvent &event);
void onPaint(wxPaintEvent &event); void onPaint(wxPaintEvent &event);
void setCurrentGLContext(); void setCurrentGLContext();

View File

@ -153,6 +153,7 @@ Program::Program(int w, int h, string playerName) {
ofsetY = 0; ofsetY = 0;
map = new MapPreview(); map = new MapPreview();
resetFactions(8); resetFactions(8);
renderer.initMapSurface(w, h); renderer.initMapSurface(w, h);
map->setAuthor(playerName); map->setAuthor(playerName);
@ -217,12 +218,12 @@ void Program::changeMapSurface(int x, int y, int surface, int radius) {
if(map) map->changeSurface((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, static_cast<MapSurfaceType>(surface), radius); if(map) map->changeSurface((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, static_cast<MapSurfaceType>(surface), radius);
} }
void Program::changeMapObject(int x, int y, int object, int radius) { void Program::changeMapObject(int x, int y, int object, int radius, bool overwrite) {
if(map) map->changeObject((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, object, radius); if(map) map->changeObject((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, object, radius, overwrite);
} }
void Program::changeMapResource(int x, int y, int resource, int radius) { void Program::changeMapResource(int x, int y, int resource, int radius, bool overwrite) {
if(map) map->changeResource((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, resource, radius); if(map) map->changeResource((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, resource, radius, overwrite);
} }
void Program::changeStartLocation(int x, int y, int player) { void Program::changeStartLocation(int x, int y, int player) {
@ -264,9 +265,9 @@ bool Program::redo() {
return true; return true;
} }
void Program::renderMap(int w, int h) { void Program::renderMap(int w, int h, pair<int,int>* mouse_pos, int* radius) {
//printf("Rendering map\n"); //printf("Rendering map\n");
if(map) renderer.renderMap(map, ofsetX, ofsetY, w, h, cellSize, grid,heightmap,hideWater); if(map) renderer.renderMap(map, ofsetX, ofsetY, w, h, cellSize, grid,heightmap,hideWater,mouse_pos,radius);
} }
void Program::setRefAlt(int x, int y) { void Program::setRefAlt(int x, int y) {

View File

@ -102,6 +102,7 @@ private:
bool hideWater; bool hideWater;
//static Map *map; //static Map *map;
static MapPreview *map; static MapPreview *map;
friend class UndoPoint; friend class UndoPoint;
ChangeStack undoStack, redoStack; ChangeStack undoStack, redoStack;
@ -123,8 +124,8 @@ public:
void glestChangeMapHeight(int x, int y, int Height, int radius); void glestChangeMapHeight(int x, int y, int Height, int radius);
void pirateChangeMapHeight(int x, int y, int Height, int radius); void pirateChangeMapHeight(int x, int y, int Height, int radius);
void changeMapSurface(int x, int y, int surface, int radius); void changeMapSurface(int x, int y, int surface, int radius);
void changeMapObject(int x, int y, int object, int radius); void changeMapObject(int x, int y, int object, int radius, bool overwrite);
void changeMapResource(int x, int y, int resource, int radius); void changeMapResource(int x, int y, int resource, int radius, bool overwrite);
void changeStartLocation(int x, int y, int player); void changeStartLocation(int x, int y, int player);
void setUndoPoint(ChangeType change); void setUndoPoint(ChangeType change);
@ -165,7 +166,7 @@ public:
void setMapAdvanced(int altFactor, int waterLevel, int minimumCliffHeight, int cameraHeight); void setMapAdvanced(int altFactor, int waterLevel, int minimumCliffHeight, int cameraHeight);
//misc //misc
void renderMap(int w, int h); void renderMap(int w, int h, pair<int,int>* mouse_pos=NULL, int* radius=NULL);
void setOfset(int x, int y); void setOfset(int x, int y);
void incCellSize(int i); void incCellSize(int i);
void resetOfset(); void resetOfset();

View File

@ -27,7 +27,7 @@ public:
virtual ~BaseRenderer() { } virtual ~BaseRenderer() { }
virtual void initMapSurface(int clientW, int clientH); virtual void initMapSurface(int clientW, int clientH);
virtual void renderMap(MapPreview *map, int x, int y, int clientW, int clientH, int cellSize, bool grid=false, bool heightMap=false, bool hideWater=false); virtual void renderMap(MapPreview *map, int x, int y, int clientW, int clientH, int cellSize, bool grid=false, bool heightMap=false, bool hideWater=false, pair<int, int>* mouse_pos=NULL, int* radius=NULL);
}; };
}} // end namespace }} // end namespace

View File

@ -43,7 +43,7 @@ public:
class RendererMapInterface { class RendererMapInterface {
public: public:
virtual void initMapSurface(int clientW, int clientH) = 0; virtual void initMapSurface(int clientW, int clientH) = 0;
virtual void renderMap(MapPreview *map, int x, int y, int clientW, int clientH, int cellSize, bool grid, bool heightMap, bool hideWater) = 0; virtual void renderMap(MapPreview *map, int x, int y, int clientW, int clientH, int cellSize, bool grid, bool heightMap, bool hideWater, pair<int, int>* mouse_pos=NULL, int* radius=NULL) = 0;
virtual ~RendererMapInterface() {} virtual ~RendererMapInterface() {}
}; };

View File

@ -174,6 +174,7 @@ public:
int getCameraHeight() const{return cameraHeight;} int getCameraHeight() const{return cameraHeight;}
bool inside(int x, int y); bool inside(int x, int y);
static int get_dist(int delta_x, int delta_y);
void setRefAlt(int x, int y); void setRefAlt(int x, int y);
void setAdvanced(int heightFactor, int waterLevel, int cliffLevel, int cameraHeight); void setAdvanced(int heightFactor, int waterLevel, int cliffLevel, int cameraHeight);
@ -191,8 +192,8 @@ public:
void glestChangeHeight(int x, int y, int height, int radius); void glestChangeHeight(int x, int y, int height, int radius);
void pirateChangeHeight(int x, int y, int height, int radius); void pirateChangeHeight(int x, int y, int height, int radius);
void changeSurface(int x, int y, MapSurfaceType surface, int radius); void changeSurface(int x, int y, MapSurfaceType surface, int radius);
void changeObject(int x, int y, int object, int radius); void changeObject(int x, int y, int object, int radius, bool overwrite);
void changeResource(int x, int y, int resource, int radius); void changeResource(int x, int y, int resource, int radius, bool overwrite);
void changeStartLocation(int x, int y, int player); void changeStartLocation(int x, int y, int player);
void setHeight(int x, int y, float height); void setHeight(int x, int y, float height);

View File

@ -36,7 +36,7 @@ void BaseRenderer::initMapSurface(int clientW, int clientH) {
} }
void BaseRenderer::renderMap(MapPreview *map, int x, int y, void BaseRenderer::renderMap(MapPreview *map, int x, int y,
int clientW, int clientH, int cellSize, bool grid, bool heightMap, bool hideWater) { int clientW, int clientH, int cellSize, bool grid, bool heightMap, bool hideWater, pair<int,int>* mouse_pos, int* radius) {
float alt=0; float alt=0;
float showWater=0; float showWater=0;
@ -78,7 +78,7 @@ void BaseRenderer::renderMap(MapPreview *map, int x, int y,
case st_Ground: surfColor = Vec3f(0.7f * alt, 0.5f * alt, 0.3f * alt + showWater); break; case st_Ground: surfColor = Vec3f(0.7f * alt, 0.5f * alt, 0.3f * alt + showWater); break;
} }
if(heightMap){ if(heightMap){
surfColor = Vec3f(1.f * alt, 1.f * alt, 1.f * alt + showWater); surfColor = Vec3f(1.f * alt, 1.f * alt, 1.f * alt + showWater);
} }
if(map->getCliffLevel()>0) if(map->getCliffLevel()>0)
{// we maybe need to render cliff surfColor {// we maybe need to render cliff surfColor
@ -87,6 +87,13 @@ void BaseRenderer::renderMap(MapPreview *map, int x, int y,
isCliff=true; isCliff=true;
} }
} }
//highlight under cusor
if(mouse_pos != NULL && radius != NULL) {
int dist = map->get_dist(i - mouse_pos->first, j - mouse_pos->second);
if (*radius > dist) {
surfColor += Vec3f(0.15f,0.15f,0.15f);
}
}
glColor3fv(surfColor.ptr()); glColor3fv(surfColor.ptr());
glBegin(GL_TRIANGLE_STRIP); glBegin(GL_TRIANGLE_STRIP);

View File

@ -112,8 +112,8 @@ int MapPreview::getStartLocationY(int index) const {
return startLocations[index].y; return startLocations[index].y;
} }
static int get_dist(int delta_x, int delta_y) { int MapPreview::get_dist(int delta_x, int delta_y) {
float dx = (float)delta_x; float dx = (float)delta_x;
float dy = (float)delta_y; float dy = (float)delta_y;
#ifdef USE_STREFLOP #ifdef USE_STREFLOP
return static_cast<int>(streflop::sqrtf(static_cast<streflop::Simple>(dx * dx + dy * dy))+0.5); // round correctly return static_cast<int>(streflop::sqrtf(static_cast<streflop::Simple>(dx * dx + dy * dy))+0.5); // round correctly
@ -462,7 +462,7 @@ void MapPreview::setSurface(int x, int y, MapSurfaceType surface) {
hasChanged = true; hasChanged = true;
} }
void MapPreview::changeObject(int x, int y, int object, int radius) { void MapPreview::changeObject(int x, int y, int object, int radius, bool overwrite) {
int i = 0, j = 0; int i = 0, j = 0;
int dist = 0; int dist = 0;
@ -470,7 +470,7 @@ void MapPreview::changeObject(int x, int y, int object, int radius) {
for (j = y - radius + 1; j < y + radius; j++) { for (j = y - radius + 1; j < y + radius; j++) {
if (inside(i, j)) { if (inside(i, j)) {
dist = get_dist(i - x, j - y); dist = get_dist(i - x, j - y);
if (radius > dist) { // was >= if (radius > dist && (overwrite || (cells[i][j].resource==0 && cells[i][j].object == 0 && !isCliff(i,j) && cells[i][j].height >= waterLevel-1.5f))) { // was >=
cells[i][j].object = object; cells[i][j].object = object;
cells[i][j].resource = 0; cells[i][j].resource = 0;
hasChanged = true; hasChanged = true;
@ -488,7 +488,7 @@ void MapPreview::setObject(int x, int y, int object) {
hasChanged = true; hasChanged = true;
} }
void MapPreview::changeResource(int x, int y, int resource, int radius) { void MapPreview::changeResource(int x, int y, int resource, int radius, bool overwrite) {
int i = 0, j = 0; int i = 0, j = 0;
int dist = 0; int dist = 0;
@ -496,7 +496,7 @@ void MapPreview::changeResource(int x, int y, int resource, int radius) {
for (j = y - radius + 1; j < y + radius; j++) { for (j = y - radius + 1; j < y + radius; j++) {
if (inside(i, j)) { if (inside(i, j)) {
dist = get_dist(i - x, j - y); dist = get_dist(i - x, j - y);
if (radius > dist) { // was >= if (radius > dist && (overwrite || (cells[i][j].resource==0 && cells[i][j].object == 0 && !isCliff(i,j) && cells[i][j].height >= waterLevel-1.5f))) { // was >=
cells[i][j].resource = resource; cells[i][j].resource = resource;
cells[i][j].object = 0; cells[i][j].object = 0;
hasChanged = true; hasChanged = true;