Author Topic: I'd like to help out  (Read 4569 times)

zombiepirate

  • Guest
I'd like to help out
« on: 22 February 2010, 06:32:12 »
Hi,

As you can probably tell I'm new around here, and I'd like to help out. The only problem is that I don't know where to start or what I could do. So far I've downloaded the 0.2.x branch from the svn and looked through some of the code. I've also played with some of the menu code a bit. I'm not the best C++ programmer in the world, but I do know my way around. I would be much obliged if someone could help me get started.

Cheers.

silnarm

  • Local Moderator
  • Behemoth
  • ********
  • Posts: 1,373
    • View Profile
Re: I'd like to help out
« Reply #1 on: 22 February 2010, 08:40:50 »
Hi zombiepirate,

  I'm not really sure where you could 'start' as such, there are numerous smallish things that need doing, but I think they probably all require some familiarisation with the code.

  Regarding the menus, we actually have plans to replace all the GUI stuff, but I'm not sure on an exact timeline for that, and there are a few tweaks I wouldn't mind making to the 'new game' and 'join game' MenuStates.

  All I could suggest for now is to keep poking around in the code, and perhaps check the open tickets on the tracker,
http://sourceforge.net/apps/trac/glestae/report/1
there are probably a bunch of things that need doing that aren't on the tracker though, we're about to release 0.2.13, after which I'll probably spend some time adding tickets for things that need fixing/restoring/adding.

  We can intermittently be found on the glest IRC channel (on the freenode network), typically weekends you'll be more likely to find us.

  If you have any queries about the code, you can ask here or on the dev mailing list (you can subscribe from our sourceforge project page), we'd be happy to help you out in any way we can :)

Cheers
Glest Advanced Engine - Code Monkey

Timeline | Downloads

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: I'd like to help out
« Reply #2 on: 22 February 2010, 09:34:35 »
Something useful would be a change in the glest editor:
All objects that are placed on the map have their specific color. A problem is that these colors are not shown in the corresponding menu entries. It would be cool if you can somehow show this color in the menu entries too. Maybe you can color the fonts or whatever....
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

zombiepirate

  • Guest
Re: I'd like to help out
« Reply #3 on: 22 February 2010, 20:01:48 »
I just installed Wx so I could compile the map editor and the compile failed. I'm not sure if it's because I have the wrong version or something else is wrong. I've tried with version 2.8 and 2.6 I get the same error.

C++ ./build/x86_64-unknown-linux-gnu/optimize/map_editor/main.o
In file included from map_editor/main.cpp:14:
map_editor/main.h:35: error: invalid use of incomplete type ‘struct wxFrame’
/usr/include/wx-2.8/wx/utils.h:50: error: forward declaration of ‘struct wxFrame’
map_editor/main.h:85: error: ISO C++ forbids declaration of ‘wxMenuBar’ with no type
map_editor/main.h:85: error: expected ‘;’ before ‘*’ token
map_editor/main.h:86: error: ISO C++ forbids declaration of ‘wxMenu’ with no type
...

EDIT: never mind it compiles now. I didn't have libwxgtk.
« Last Edit: 22 February 2010, 20:14:35 by zombiepirate »

zombiepirate

  • Guest
Re: I'd like to help out
« Reply #4 on: 26 February 2010, 05:18:03 »
I made a couple of patches for the map editor, I'm not really sure who I should be giving them to though.

Add a timer to the editor so it automatically renders every 50ms. The drop down menus weren't being erased when you moved to a new menu.
Code: [Select]
Index: source/map_editor/main.cpp
===================================================================
--- source/map_editor/main.cpp (revision 497)
+++ source/map_editor/main.cpp (working copy)
@@ -156,6 +156,9 @@
  menuBar->Append(menuRadius, wxT("Radius"));
 
  SetMenuBar(menuBar);
+
+ timer = new wxTimer(this);
+ timer->Start(50);
 }
 
 void MainWindow::init(string fname) {
@@ -423,6 +426,11 @@
  radius = event.GetId() - miRadius + 1;
 }
 
+void MainWindow::onTimer(wxTimerEvent &event) {
+ wxPaintEvent paintEvent;
+ onPaint(paintEvent);
+}
+
 void MainWindow::change(int x, int y) {
  switch (enabledGroup) {
  case 0:
@@ -468,6 +476,7 @@
 }
 
 BEGIN_EVENT_TABLE(MainWindow, wxFrame)
+ EVT_TIMER(-1, MainWindow::onTimer)
  EVT_CLOSE(MainWindow::onClose)
  EVT_LEFT_DOWN(MainWindow::onMouseDown)
  EVT_MOTION(MainWindow::onMouseMove)
Index: source/map_editor/main.h
===================================================================
--- source/map_editor/main.h (revision 497)
+++ source/map_editor/main.h (working copy)
@@ -82,6 +82,8 @@
  Program *program;
  int lastX, lastY;
 
+ wxTimer *timer;
+
  wxMenuBar *menuBar;
  wxMenu *menuFile;
  wxMenu *menuEdit;
@@ -142,6 +144,8 @@
  void onMenuBrushStartLocation(wxCommandEvent &event);
  void onMenuRadius(wxCommandEvent &event);
 
+ void onTimer(wxTimerEvent &event);
+
  void change(int x, int y);
 
  void uncheckBrush();

Change the changeHeight function so that it applies gradients from the real height rather than from the refAlt.
Code: [Select]
Index: source/map_editor/map.cpp
===================================================================
--- source/map_editor/map.cpp (revision 497)
+++ source/map_editor/map.cpp (working copy)
@@ -79,28 +79,64 @@
 }
 
 void Map::changeHeight(int x, int y, int height, int radius) {
+ // Make sure not to try and blanket change the height over the bounds
+ // Find our goal height for the centre of the brush
+ int goalAlt;
+ int overBounds = refAlt + height;
+ if (overBounds > 20) {
+ goalAlt = 20;
+ }
+ else if (overBounds < 0) {
+ goalAlt = 0;
+ } else {
+ goalAlt = overBounds;
+ }
 
- for (int i = x - radius + 1; i < x + radius; i++) {
- for (int j = y - radius + 1; j < y + radius; j++) {
+ // Get Old height reference points and compute gradients
+ // from the heights of the sides and corners of the brush to the centre goal height
+ float gradient[3][3]; // [i][j]
+ int indexI = 0;
+ for (int i = x - radius; i <= x + radius; i += radius) {
+ int indexJ = 0;
+ for (int j = y - radius; j <= y + radius; j += radius) {
+ int dist = get_dist(i - x, j - y);
+ if (inside(i, j) && dist != 0) {
+ gradient[indexI][indexJ] = (cells[i][j].height - goalAlt) / dist;
+ } else if (dist == 0) {
+ gradient[indexI][indexJ] = 0;
+ } else {
+ // assume outside the map bounds is height 10
+ gradient[indexI][indexJ] = (10.0 - goalAlt) / dist;
+ }
+ indexJ++;
+ }
+ indexI++;
+ }
+
+    // A brush with radius n cells should have a true radius of n-1 distance
+    radius -= 1;
+ for (int i = x - radius; i <= x + radius; i++) {
+ for (int j = y - radius; j <= y + radius; j++) {
  if (inside(i, j)) {
- int dist = get_dist(i - x, j - y);
- if (radius > dist) {
- int oldAlt = static_cast<int>(cells[i][j].height);
- int altInc = height * (radius - dist - 1) / radius;
- if (height > 0) {
- altInc++;
- }
- if (height < 0) {
- altInc--;
- }
- int newAlt = refAlt + altInc;
- if ((height > 0 && newAlt > oldAlt) || (height < 0 && newAlt < oldAlt) || height == 0) {
- if (newAlt >= 0 && newAlt <= 20) {
- cells[i][j].height = static_cast<float>(newAlt);
- }
- }
- }
- }
+ // Normalize di and dj and round them to an int so they can be used as indicies
+ // TODO find a weighted average of the near gradients to make some of the changes smoother?
+ float normIf = (float(i - x)/ radius);
+ float normJf = (float(j - y)/ radius);
+ int normI;
+ int normJ;
+ (normIf < -0.33)? normI = 0:normI = normIf + 1.66;
+ (normJf < -0.33)? normJ = 0:normJ = normJf + 1.66;
+
+ float newAlt = gradient[normI][normJ] * get_dist(i - x, j - y) + goalAlt;
+
+ // if the change in height and what is supposed to be the change in height
+ // are the same sign then we can change the height
+ if ( ((newAlt - cells[i][j].height) > 0 && height > 0) ||
+ ((newAlt - cells[i][j].height) < 0 && height < 0) ||
+ height == 0) {
+ cells[i][j].height = newAlt;
+ }
+ }
  }
  }
 }
« Last Edit: 26 February 2010, 05:56:00 by zombiepirate »

silnarm

  • Local Moderator
  • Behemoth
  • ********
  • Posts: 1,373
    • View Profile
Re: I'd like to help out
« Reply #5 on: 26 February 2010, 09:02:39 »
Interesting changes, I think I know what you were going for, but I'm not sure the result is quite right,



I haven't looked over the code in any detail as yet, but a few obvious things stand out ;)

First, the changes are applied to the entire 'square' of the brush, you should only apply changes where the distance of the cell to the centre is within the brush radius, then you get a nice round brush like the original.

Second, the corners look like they are raised compared to the 'sides', obviously the corners are further away than the cells to the sides (and this map was obviously blank and flat before hand), so I think your calculations must be off somewhere.

Interesting idea though, if you can get it fixed up re the above issues, it might be interesting to see if we can get master map maker trappin to have a play with it and get some feedback  :)
Glest Advanced Engine - Code Monkey

Timeline | Downloads

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: I'd like to help out
« Reply #6 on: 26 February 2010, 09:08:19 »
Is the first patch for the flickering due to the repaint problems in linux?
This would be great!
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

zombiepirate

  • Guest
Re: I'd like to help out
« Reply #7 on: 26 February 2010, 09:18:18 »
Yes, a single square is pretty bad right now. The algorithm is meant to smooth edges of a brush stroke if the change in terrain is extreme. For example the original function would cut away the terrain and make "cliffs" if refAlt + height was too far away from the actual height of the terrain in mid stroke.

My algorithm right now is more meant for large brushes and large changes to terrain.

I'll keep working on it and see if I can get the issues sorted out.

EDIT: I don't know if the "flickering" you're talking about is what I'm thinking, but the first patch puts the repaint on a timer so that repaint actually happens without mouse movement on the canvas. ie. mouse movement in the menus doesn't repaint the canvas even though the menus cover up areas of the canvas.
« Last Edit: 26 February 2010, 09:21:14 by zombiepirate »

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: I'd like to help out
« Reply #8 on: 26 February 2010, 09:26:02 »
I will try it ( the repaint thing )

For the brushes: There is really no need to smooth the terrain with the brushes. Glest itself smoothes the terrain when loading a map.
So cliffes are not a problem, its more a problem to create cliffs if we support them one day!
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

zombiepirate

  • Guest
Re: I'd like to help out
« Reply #9 on: 26 February 2010, 22:30:54 »
I think I got most of the issues sorted out. The code is insanely complicated now so if anyone notices anything redundant or unnecessary please speak up.

Code: [Select]
Index: source/map_editor/map.cpp
===================================================================
--- source/map_editor/map.cpp (revision 497)
+++ source/map_editor/map.cpp (working copy)
@@ -79,28 +79,140 @@
 }
 
 void Map::changeHeight(int x, int y, int height, int radius) {
+ // Make sure not to try and blanket change the height over the bounds
+ // Find our goal height for the centre of the brush
+ int goalAlt;
+ int overBounds = refAlt + height;
+ if (overBounds > 20) {
+ goalAlt = 20;
+ }
+ else if (overBounds < 0) {
+ goalAlt = 0;
+ } else {
+ goalAlt = overBounds;
+ }
 
- for (int i = x - radius + 1; i < x + radius; i++) {
- for (int j = y - radius + 1; j < y + radius; j++) {
+ // Get Old height reference points and compute gradients
+ // from the heights of the sides and corners of the brush to the centre goal height
+ float gradient[3][3]; // [i][j]
+ int indexI = 0;
+ for (int i = x - radius; i <= x + radius; i += radius) {
+ int indexJ = 0;
+ for (int j = y - radius; j <= y + radius; j += radius) {
+ // round off the corners
+ int ti, tj;
+ if (abs(i - x) == abs(j - y)) {
+ ti = (i - x) * 0.707 + x + 0.5;
+ tj = (j - y) * 0.707 + y + 0.5;
+ } else {
+ ti = i;
+ tj = j;
+ }
+ if (inside(ti, tj)) {
+ gradient[indexI][indexJ] = (cells[ti][tj].height - goalAlt) / radius;
+ //} else if (dist == 0) {
+ //gradient[indexI][indexJ] = 0;
+ } else {
+ // assume outside the map bounds is height 10
+ gradient[indexI][indexJ] = (10.0 - goalAlt) / radius;
+ }
+ //std::cout << "gradient[" << indexI << "][" << indexJ << "] = " << gradient[indexI][indexJ] << std::endl;
+ //std::cout << "derived from height " << cells[ti][tj].height << " at " << ti << " " << tj << std::endl;
+ indexJ++;
+ }
+ indexI++;
+ }
+ //std::cout << endl;
+
+ // A brush with radius n cells should have a true radius of n-1 distance
+ radius -= 1;
+ for (int i = x - radius; i <= x + radius; i++) {
+ for (int j = y - radius; j <= y + radius; j++) {
  if (inside(i, j)) {
- int dist = get_dist(i - x, j - y);
- if (radius > dist) {
- int oldAlt = static_cast<int>(cells[i][j].height);
- int altInc = height * (radius - dist - 1) / radius;
- if (height > 0) {
- altInc++;
+ // Normalize di and dj and round them to an int so they can be used as indicies
+ float normIf = (float(i - x)/ radius);
+ float normJf = (float(j - y)/ radius);
+ int normI[2];
+ int normJ[2];
+ float usedGrad;
+
+ // Build a search box to find the gradients we are concerned about
+ // Find the nearest i indices
+ if (normIf < -0.33) {
+ normI[0] = 0;
+ if (normIf == 0) {
+ normI[1] = 0;
+ } else {
+ normI[1] = 1;
+ }
+ } else if (normIf < 0.33) {
+ normI[0] = 1;
+ if (normIf > 0) {
+ normI[1] = 2;
+ } else if (normIf < 0) {
+ normI[1] = 0;
+ } else /*(normIf == 0)*/ {
+ normI[1] = 1;
+ }
+ } else {
+ normI[0] = 2;
+ if (normIf == 1) {
+ normI[1] = 2;
+ } else {
+ normI[1] = 1;
+ }
  }
- if (height < 0) {
- altInc--;
- }
- int newAlt = refAlt + altInc;
- if ((height > 0 && newAlt > oldAlt) || (height < 0 && newAlt < oldAlt) || height == 0) {
- if (newAlt >= 0 && newAlt <= 20) {
- cells[i][j].height = static_cast<float>(newAlt);
+ // find nearest j indices
+ if (normJf < -0.33) {
+ normJ[0] = 0;
+ if (normJf == 0) {
+ normJ[1] = 0;
+ } else {
+ normJ[1] = 1;
  }
+ } else if (normJf < 0.33) {
+ normJ[0] = 1;
+ if (normJf > 0) {
+ normJ[1] = 2;
+ } else if (normJf < 0) {
+ normJ[1] = 0;
+ } else /*(normJf == 0)*/ {
+ normJ[1] = 1;
+ }
+ } else {
+ normJ[0] = 2;
+ if (normJf == 1) {
+ normJ[1] = 2;
+ } else {
+ normJ[1] = 1;
+ }
  }
+
+ // Determine which gradients to use and take a weighted average
+ if (abs(normIf) > abs(normJf)) {
+ usedGrad =
+ gradient[normI[0]] [normJ[0]] * abs(normJf) +
+ gradient[normI[0]] [normJ[1]] * (1 - abs(normJf));
+ } else if (abs(normIf) < abs(normJf)) {
+ usedGrad =
+ gradient[normI[0]] [normJ[0]] * abs(normIf) +
+ gradient[normI[1]] [normJ[0]] * (1 - abs(normIf));
+ } else {
+ usedGrad =
+ gradient[normI[0]] [normJ[0]];
+ }
+
+
+ float newAlt = usedGrad * get_dist(i - x, j - y) + goalAlt;
+
+ // if the change in height and what is supposed to be the change in height
+ // are the same sign then we can change the height
+ if ( ((newAlt - cells[i][j].height) > 0 && height > 0) ||
+ ((newAlt - cells[i][j].height) < 0 && height < 0) ||
+ height == 0) {
+ cells[i][j].height = newAlt;
+ }
  }
- }
  }
  }
 }

@titi: Did the repaint thing work for you?

EDIT: fixed the brush a bit more
« Last Edit: 27 February 2010, 01:22:46 by zombiepirate »

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: I'd like to help out
« Reply #10 on: 27 February 2010, 01:13:26 »
No, the patch didn't really worked. Maybe its a bit better now, but now its always flickering, not only if I move the mouse like before :/
( I tried it in megaglest  were  I had to patch manually some of the things because GAE is already a bit different from original glest/megaglest )

I still don't really get why we need a new brush? Whats wrong with the old one?
« Last Edit: 27 February 2010, 01:19:20 by titi »
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

silnarm

  • Local Moderator
  • Behemoth
  • ********
  • Posts: 1,373
    • View Profile
Re: I'd like to help out
« Reply #11 on: 27 February 2010, 01:26:02 »
I still don't really get why we need a new brush? Whats wrong with the old one?

This is probably fair enough, I haven't used it heaps, but I've made a couple of maps for unfinished scenarios and didn't have much of a problem with it... once I got used to its quirks.

Didn't Trappin have a topic of sugggestions for improvements ??

I have to leave for a bbq now ;) Someone should probably dig around for that topic perhaps?
Glest Advanced Engine - Code Monkey

Timeline | Downloads

zombiepirate

  • Guest
Re: I'd like to help out
« Reply #12 on: 27 February 2010, 01:30:25 »
Nothing's "wrong" with the old one, but its gradients aren't from where the brush stroke actually is on the terrain so it has a tendency to "cut" into the terrain. My brush doesn't "cut", it applies a gradient.

If you really don't want a new one I won't be offended if nobody applies the patch... It was more of a thing to do so I could get a little bit of experience with the code. I'm more after feedback on my work rather then distribution with the map editor.

EDIT:
https://forum.megaglest.org/index.php?topic=3958.msg22840#msg22840
Is this what you were talking about?

EDIT 2:
How about something more useful? Renders water level on the map so there is less guess and check.

Code: [Select]
Index: source/map_editor/renderer.cpp
===================================================================
--- source/map_editor/renderer.cpp (revision 497)
+++ source/map_editor/renderer.cpp (working copy)
@@ -39,6 +39,7 @@
 
 void Renderer::renderMap(Map *map, int x, int y, int clientW, int clientH, int cellSize) {
  float alt;
+ float showWater;
 
  assertGl();
 
@@ -64,13 +65,15 @@
 
  //surface
  alt = map->getHeight(i, j) / 20.f;
+ showWater = map->getWaterLevel()/ 20.f - alt;
+ showWater = (showWater > 0)? showWater:0;
  Vec3f surfColor;
  switch (map->getSurface(i, j)) {
- case 1: surfColor = Vec3f(0.0, 0.8f * alt, 0.f); break;
- case 2: surfColor = Vec3f(0.4f * alt, 0.6f * alt, 0.f); break;
- case 3: surfColor = Vec3f(0.6f * alt, 0.3f * alt, 0.f); break;
- case 4: surfColor = Vec3f(0.7f * alt, 0.7f * alt, 0.7f * alt); break;
- case 5: surfColor = Vec3f(1.0f * alt, 0.f, 0.f); break;
+ case 1: surfColor = Vec3f(0.0, 0.8f * alt, 0.f + showWater); break;
+ case 2: surfColor = Vec3f(0.4f * alt, 0.6f * alt, 0.f + showWater); break;
+ case 3: surfColor = Vec3f(0.6f * alt, 0.3f * alt, 0.f + showWater); break;
+ case 4: surfColor = Vec3f(0.7f * alt, 0.7f * alt, 0.7f * alt + showWater); break;
+ case 5: surfColor = Vec3f(1.0f * alt, 0.f, 0.f + showWater); break;
  }
 
  glColor3fv(surfColor.ptr());
@@ -104,10 +107,10 @@
  glEnd();
  }
 
- bool found = false;
+// bool found = false;
 
  //height lines
- if (!found) {
+// if (!found) {
  glColor3fv((surfColor*0.5f).ptr());
  //left
  if (i > 0 && map->getHeight(i - 1, j) > map->getHeight(i, j)) {
@@ -138,7 +141,7 @@
  glVertex2i((i + 1) * cellSize, clientH - j * cellSize);
  glEnd();
  }
- }
+// }
 
  //resources
  switch (map->getResource(i, j)) {
« Last Edit: 27 February 2010, 05:50:13 by zombiepirate »

silnarm

  • Local Moderator
  • Behemoth
  • ********
  • Posts: 1,373
    • View Profile
Re: I'd like to help out
« Reply #13 on: 27 February 2010, 10:21:43 »
If you really don't want a new one I won't be offended if nobody applies the patch... It was more of a thing to do so I could get a little bit of experience with the code. I'm more after feedback on my work rather then distribution with the map editor.

I like the idea of your 'brush' and think it will be worthwhile adding as a alternative to the standard height brush.

Quote
EDIT:
https://forum.megaglest.org/index.php?topic=3958.msg22840#msg22840
Is this what you were talking about?

No... I thought there was a topic Trapping started about some "small" improvements to the existing map editor, but I can't find it now.

Quote
EDIT 2:
How about something more useful? Renders water level on the map so there is less guess and check.

Now you're talking ;D That is useful!

We should be getting more feedback here though, as I mentioned I've made all of two maps, so I'm not the best to be making suggestions.

Community?
Glest Advanced Engine - Code Monkey

Timeline | Downloads

wciow

  • Behemoth
  • *******
  • Posts: 968
    • View Profile
Re: I'd like to help out
« Reply #14 on: 27 February 2010, 10:49:46 »
Both of these patches sound useful. The 'cutting' effect that Zombiepirate was talking about is actually quite annoying. The water height thing is also needed.

My biggest request: right click to undo a placement. Currently the only way to unplace something is to select none and delete it then go back and replace. If you accidentally placed over another object its even worse.

Kudos to Zombiepirate for working on the mapper, but the community can't really give feedback until someone compiles for us.
Check out my new Goblin faction - https://forum.megaglest.org/index.php?topic=9658.0

silnarm

  • Local Moderator
  • Behemoth
  • ********
  • Posts: 1,373
    • View Profile
Re: I'd like to help out
« Reply #15 on: 27 February 2010, 13:00:12 »
Having had a bit of a play with the new version, I quite like it.  The 'zero' height should be handled the same as with the regular brush though, currently it gives somewhat odd behaviour ;)

My biggest request: right click to undo a placement. Currently the only way to unplace something is to select none and delete it then go back and replace. If you accidentally placed over another object its even worse.

Kudos to Zombiepirate for working on the mapper, but the community can't really give feedback until someone compiles for us.

Undo is a good request, so that's a start.

For feed-back on the work done so far, here's a win32 build, I added zombiepirate's brush as 'smooth' ... probably not the most appropriate name, but good enough for now ('height' == normal glest brush, 'smooth' == zombiepirate's new brush).

https://sourceforge.net/projects/glestae/files/glestae_snapshots/map_editor/map_editor_win32.7z/download
Glest Advanced Engine - Code Monkey

Timeline | Downloads

zombiepirate

  • Guest
Re: I'd like to help out
« Reply #16 on: 27 February 2010, 18:13:11 »
Thanks for the feedback guys, I do appreciate it. I'll see if I can fix up the zero height and also see if I can make an undo button, as it seems to be a desperately needed item.

-Archmage-

  • Moderator
  • Dragon
  • ********
  • Posts: 5,887
  • Make it so.
    • View Profile
    • My Website
Re: I'd like to help out
« Reply #17 on: 27 February 2010, 18:33:04 »
The undo button should be the traditional "Ctrl-Z". ;)
Egypt Remastered!

Proof: Owner of glest@mail.com

titi

  • MegaGlest Team
  • Airship
  • ********
  • Posts: 4,240
    • View Profile
    • http://www.titusgames.de
Re: I'd like to help out
« Reply #18 on: 28 February 2010, 00:53:57 »
Yes undo would be really great and the water level is good too! Maybe its possible to have a switch to switch on and off the water surface while editing?
For the new brush: I like the current brush and the fact that you can easily make cliffs with it ( although they are smoothed when loaded in glest).  I would still prefer the old brush .
What about colors in the menus showing the same color as shown in the map layout for every entry?
« Last Edit: 28 February 2010, 00:57:39 by titi »
Try Megaglest! Improved Engine / New factions / New tilesets / New maps / New scenarios

zombiepirate

  • Guest
Re: I'd like to help out
« Reply #19 on: 28 February 2010, 01:51:13 »
Well, here's a work-in-progress undo button and a small change to the brush to fix a bug (not the zero height one). The undo button currently only undoes one left-click worth of work so don't try and undo multiple clicks with it, and the redo button hasn't been implemented yet. But, I planned for both a length of undo history and a redo button in the code, I just got tired of coding for today.

@titi: I'll store the water level on/off switch in the back of my mind and see if I can add that in later. I don't know if it's possible to color the menu fonts, though I don't really have much experience with wx so I couldn't say for sure. Maybe there would be another way to make the colors more obvious? Also my brush isn't replacing the old one, it's in a new menu in the svn, so don't worry, your old brush is safe.

@-Archmage- and wciow: sorry no shortcut key yet, but the button is there.

Code: [Select]
Index: source/map_editor/map.h
===================================================================
--- source/map_editor/map.h (revision 498)
+++ source/map_editor/map.h (working copy)
@@ -105,6 +105,11 @@
  void changeResource(int x, int y, int resource, int radius);
  void changeStartLocation(int x, int y, int player);
 
+ void setHeight(int x, int y, float height);
+ void setSurface(int x, int y, int surface);
+ void setObject(int x, int y, int object);
+ void setResource(int x, int y, int resource);
+
  void flipX();
  void flipY();
  void reset(int w, int h, float alt, int surf);
Index: source/map_editor/main.cpp
===================================================================
--- source/map_editor/main.cpp (revision 498)
+++ source/map_editor/main.cpp (working copy)
@@ -52,7 +52,7 @@
  object = 0;
  resource = 0;
  startLocation = 1;
- enabledGroup = 0;
+ enabledGroup = ctLocation;
 
 
  //gl canvas
@@ -73,6 +73,8 @@
 
  //edit
  menuEdit = new wxMenu();
+ menuEdit->Append(miEditUndo, wxT("Undo"));
+ menuEdit->Append(miEditRedo, wxT("Redo"));
  menuEdit->Append(miEditReset, wxT("Reset"));
  menuEdit->Append(miEditResetPlayers, wxT("Reset Players"));
  menuEdit->Append(miEditResize, wxT("Resize"));
@@ -189,6 +191,7 @@
 
 void MainWindow::onMouseDown(wxMouseEvent &event) {
  if (event.LeftIsDown()) {
+ program->setUndoPoint(enabledGroup);
  program->setRefAlt(event.GetX(), event.GetY());
  change(event.GetX(), event.GetY());
  }
@@ -265,6 +268,16 @@
  Close();
 }
 
+void MainWindow::onMenuEditUndo(wxCommandEvent &event) {
+ std::cout << "Undo Pressed" << std::endl;
+ program->undo();
+}
+
+void MainWindow::onMenuEditRedo(wxCommandEvent &event) {
+ std::cout << "Redo Pressed" << std::endl;
+ program->redo();
+}
+
 void MainWindow::onMenuEditReset(wxCommandEvent &event) {
  SimpleDialog simpleDialog;
  simpleDialog.addValue("Altitude", "10");
@@ -395,14 +408,14 @@
  uncheckBrush();
  menuBrushHeight->Check(event.GetId(), true);
  height = event.GetId() - miBrushHeight - heightCount / 2 - 1;
- enabledGroup = 0;
+ enabledGroup = ctGlestHeight;
 }
 
 void MainWindow::onMenuPirateBrushHeight(wxCommandEvent &event) {
  uncheckBrush();
  menuPirateBrushHeight->Check(event.GetId(), true);
  height = event.GetId() - miPirateBrushHeight - heightCount / 2 - 1;
- enabledGroup = 5;
+ enabledGroup = ctPirateHeight;
 }
 
 
@@ -410,28 +423,28 @@
  uncheckBrush();
  menuBrushSurface->Check(event.GetId(), true);
  surface = event.GetId() - miBrushSurface;
- enabledGroup = 1;
+ enabledGroup = ctSurface;
 }
 
 void MainWindow::onMenuBrushObject(wxCommandEvent &event) {
  uncheckBrush();
  menuBrushObject->Check(event.GetId(), true);
  object = event.GetId() - miBrushObject - 1;
- enabledGroup = 2;
+ enabledGroup = ctObject;
 }
 
 void MainWindow::onMenuBrushResource(wxCommandEvent &event) {
  uncheckBrush();
  menuBrushResource->Check(event.GetId(), true);
  resource = event.GetId() - miBrushResource - 1;
- enabledGroup = 3;
+ enabledGroup = ctResource;
 }
 
 void MainWindow::onMenuBrushStartLocation(wxCommandEvent &event) {
  uncheckBrush();
  menuBrushStartLocation->Check(event.GetId(), true);
  startLocation = event.GetId() - miBrushStartLocation - 1;
- enabledGroup = 4;
+ enabledGroup = ctLocation;
 }
 
 void MainWindow::onMenuRadius(wxCommandEvent &event) {
@@ -442,22 +455,22 @@
 
 void MainWindow::change(int x, int y) {
  switch (enabledGroup) {
- case 0:
+ case ctGlestHeight:
  program->glestChangeMapHeight(x, y, height, radius);
  break;
- case 1:
+ case ctSurface:
  program->changeMapSurface(x, y, surface, radius);
  break;
- case 2:
+ case ctObject:
  program->changeMapObject(x, y, object, radius);
  break;
- case 3:
+ case ctResource:
  program->changeMapResource(x, y, resource, radius);
  break;
- case 4:
+ case ctLocation:
  program->changeStartLocation(x, y, startLocation);
  break;
- case 5:
+ case ctPirateHeight:
  program->pirateChangeMapHeight(x, y, height, radius);
  break;
  }
@@ -500,6 +513,8 @@
  EVT_MENU(miFileSaveAs, MainWindow::onMenuFileSaveAs)
  EVT_MENU(miFileExit, MainWindow::onMenuFileExit)
 
+ EVT_MENU(miEditUndo, MainWindow::onMenuEditUndo)
+ EVT_MENU(miEditRedo, MainWindow::onMenuEditRedo)
  EVT_MENU(miEditReset, MainWindow::onMenuEditReset)
  EVT_MENU(miEditResetPlayers, MainWindow::onMenuEditResetPlayers)
  EVT_MENU(miEditResize, MainWindow::onMenuEditResize)
Index: source/map_editor/program.cpp
===================================================================
--- source/map_editor/program.cpp (revision 498)
+++ source/map_editor/program.cpp (working copy)
@@ -18,16 +18,168 @@
 
 namespace MapEditor {
 
+////////////////////////////
+// class UndoPoint
+////////////////////////////
+int UndoPoint::undoCount = 0;
+int UndoPoint::w = 0;
+int UndoPoint::h = 0;
+UndoPoint *UndoPoint::current = NULL;
+
+UndoPoint::UndoPoint(ChangeType change) {
+ w = Program::map->getW();
+ h = Program::map->getH();
+
+ height = NULL;
+ surface = NULL;
+ object = NULL;
+ resource = NULL;
+
+ switch (change) {
+ case ctGlestHeight:
+ case ctPirateHeight:
+ // Build an array of heights from the map
+ std::cout << "Building an array of heights to use for our UndoPoint" << std::endl;
+ height = new float*[w];
+ for (int i = 0; i < w; i++) {
+ height[i] = new float [h];
+ for (int j = 0; j < h; j++) {
+ height[i][j] = Program::map->getHeight(i, j);
+ }
+ }
+ std::cout << "Built the array" << std::endl;
+ break;
+ case ctSurface:
+ surface = new int*[w];
+ for (int i = 0; i < w; i++) {
+ surface[i] = new int [h];
+ for (int j = 0; j < h; j++) {
+ surface[i][j] = Program::map->getSurface(i, j);
+ }
+ }
+ break;
+ case ctObject:
+ object = new int*[w];
+ for (int i = 0; i < w; i++) {
+ object[i] = new int [h];
+ for (int j = 0; j < h; j++) {
+ object[i][j] = Program::map->getObject(i, j);
+ }
+ }
+ break;
+ case ctResource:
+ resource = new int*[w];
+ for (int i = 0; i < w; i++) {
+ resource[i] = new int [h];
+ for (int j = 0; j < h; j++) {
+ resource[i][j] = Program::map->getResource(i, j);
+ }
+ }
+ break;
+ case ctLocation:
+ break;
+ case ctAll:
+ break;
+ }
+
+ this->change = change;
+
+ undoCount++;
+ std::cout << "Increased undoCount to " << undoCount << std::endl;
+ if (current != NULL) {
+ current->setNext(this);
+ previous = current;
+ }
+ current = this;
+ next = NULL;
+}
+
+UndoPoint::~UndoPoint() {
+ std::cout << "attempting to delete an UndoPoint" << std::endl;
+ if (height != NULL) {
+ std::cout << "deleting heights" << std::endl;
+ for (int i = 0; i < w; i++) {
+ delete height[i];
+ }
+ }
+ if (resource != NULL) {
+ std::cout << "deleting resources" << std::endl;
+ for (int i = 0; i < w; i++) {
+ delete resource[i];
+ }
+ }
+ if (object != NULL) {
+ std::cout << "deleting objects" << std::endl;
+ for (int i = 0; i < w; i++) {
+ delete object[i];
+ }
+ }
+ if (surface != NULL) {
+ std::cout << "deleting surfaces" << std::endl;
+ for (int i = 0; i < w; i++) {
+ delete surface[i];
+ }
+ }
+ // Make sure our links don't break
+ //std::cout << "fixing the list" << std::endl;
+ //if (previous != NULL) previous->setNext(next->getPrevious());
+ //if (next != NULL) next->setPrevious(previous->getNext());
+}
+
+void UndoPoint::revert() {
+ std::cout << "attempting to revert last changes to " << change << std::endl;
+ switch (change) {
+ case ctGlestHeight:
+ case ctPirateHeight:
+ // Restore the array of heights to the map
+ std::cout << "attempting to restore the height array" << std::endl;
+ for (int i = 0; i < w; i++) {
+ for (int j = 0; j < h; j++) {
+ Program::map->setHeight(i, j, height[i][j]);
+ }
+ }
+ break;
+ case ctSurface:
+ std::cout << "attempting to restore the surface array" << std::endl;
+ for (int i = 0; i < w; i++) {
+ for (int j = 0; j < h; j++) {
+ Program::map->setSurface(i, j, surface[i][j]);
+ }
+ }
+ break;
+ case ctObject:
+ for (int i = 0; i < w; i++) {
+ for (int j = 0; j < h; j++) {
+ Program::map->setObject(i, j, object[i][j]);
+ }
+ }
+ break;
+ case ctResource:
+ for (int i = 0; i < w; i++) {
+ for (int j = 0; j < h; j++) {
+ Program::map->setResource(i, j, resource[i][j]);
+ }
+ }
+ break;
+ case ctLocation:
+ break;
+ }
+ std::cout << "reverted changes (we hope)" << std::endl;
+}
+
 // ===============================================
 // class Program
 // ===============================================
 
+Map *Program::map = NULL;
+
 Program::Program(int w, int h) {
  cellSize = 6;
  ofsetX = 0;
  ofsetY = 0;
  map = new Map();
  renderer.init(w, h);
+ undoIterator = NULL;
 }
 
 Program::~Program() {
@@ -58,6 +210,21 @@
  map->changeStartLocation((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, player);
 }
 
+void Program::setUndoPoint(ChangeType change) {
+ std::cout << "attempting to set a new UndoPoint from change " << change << std::endl;
+ if (undoIterator != NULL )delete undoIterator; // TODO change... this is just for testing (we want multiple undo points)
+ undoIterator = new UndoPoint(change);
+ std::cout << "set a new UndoPoint" << std::endl;
+}
+
+void Program::undo() {
+ undoIterator->revert();
+}
+
+void Program::redo() {
+ std::cout << "not yet implamented" << std::endl;
+}
+
 void Program::renderMap(int w, int h) {
  renderer.renderMap(map, ofsetX, ofsetY, w, h, cellSize);
 }
Index: source/map_editor/main.h
===================================================================
--- source/map_editor/main.h (revision 498)
+++ source/map_editor/main.h (working copy)
@@ -53,6 +53,8 @@
  miFileSaveAs,
  miFileExit,
 
+ miEditUndo,
+ miEditRedo,
  miEditReset,
  miEditResetPlayers,
  miEditResize,
@@ -105,7 +107,7 @@
  int object;
  int resource;
  int startLocation;
- int enabledGroup;
+ ChangeType enabledGroup;
 
 public:
  MainWindow();
@@ -123,6 +125,8 @@
  void onMenuFileSaveAs(wxCommandEvent &event);
  void onMenuFileExit(wxCommandEvent &event);
 
+ void onMenuEditUndo(wxCommandEvent &event);
+ void onMenuEditRedo(wxCommandEvent &event);
  void onMenuEditReset(wxCommandEvent &event);
  void onMenuEditResetPlayers(wxCommandEvent &event);
  void onMenuEditResize(wxCommandEvent &event);
Index: source/map_editor/program.h
===================================================================
--- source/map_editor/program.h (revision 498)
+++ source/map_editor/program.h (working copy)
@@ -19,6 +19,56 @@
 
 class MainWindow;
 
+enum ChangeType {
+ ctGlestHeight,
+ ctSurface,
+ ctObject,
+ ctResource,
+ ctLocation,
+ ctPirateHeight,
+ ctAll
+};
+
+// =============================================
+// class Undo Point
+// A linked list class that is more of an extension / modification on
+// the already existing Cell struct in map.h
+// Provides the ability to only specify a certain property of the map to change
+// =============================================
+class UndoPoint {
+ private:
+ // Only keep a certain number of undo points in memory otherwise
+ // Big projects could hog a lot of memory
+ const static int MAX_UNDO_LIST_SIZE = 100; // TODO get feedback on this value
+ static int undoCount;
+
+ ChangeType change;
+
+ // Pointers to arrays of each property
+ int **surface;
+ int **object;
+ int **resource;
+ float **height;
+
+ // Map width and height
+ static int w;
+ static int h;
+
+ UndoPoint *next;
+ UndoPoint *previous;
+ static UndoPoint *current;
+
+ public:
+ UndoPoint(ChangeType change);
+ ~UndoPoint();
+ void revert();
+
+ inline UndoPoint* getNext() const { return next; }
+ inline UndoPoint* getPrevious() const { return previous; }
+ inline void setNext(UndoPoint *n) { this->next = n; }
+ inline void setPrevious(UndoPoint *p) { this->previous = p; }
+};
+
 // ===============================================
 // class Program
 // ===============================================
@@ -28,8 +78,12 @@
  Renderer renderer;
  int ofsetX, ofsetY;
  int cellSize;
- Map *map;
+ static Map *map;
+ friend class UndoPoint;
 
+// Every mouse click this will be changed
+ UndoPoint *undoIterator;
+
 public:
  Program(int w, int h);
  ~Program();
@@ -42,6 +96,10 @@
  void changeMapResource(int x, int y, int resource, int radius);
  void changeStartLocation(int x, int y, int player);
 
+ void setUndoPoint(ChangeType change);
+ void undo();
+ void redo();
+
  //map ops
  void reset(int w, int h, int alt, int surf);
  void resize(int w, int h, int alt, int surf);
@@ -67,7 +125,7 @@
  void incCellSize(int i);
  void resetOfset();
 
- const Map *getMap() {return map;}
+ static const Map *getMap() {return map;}
 };
 
 }// end namespace
Index: source/map_editor/map.cpp
===================================================================
--- source/map_editor/map.cpp (revision 498)
+++ source/map_editor/map.cpp (working copy)
@@ -120,6 +120,12 @@
  goalAlt = overBounds;
  }
 
+ // If the radius is 1 don't bother doing any calculations
+ if (radius == 1) {
+ cells[x][y].height = goalAlt;
+ return;
+ }
+
  // Get Old height reference points and compute gradients
  // from the heights of the sides and corners of the brush to the centre goal height
  float gradient[3][3]; // [i][j]
@@ -156,7 +162,8 @@
  radius -= 1;
  for (int i = x - radius; i <= x + radius; i++) {
  for (int j = y - radius; j <= y + radius; j++) {
- if (inside(i, j)) {
+ int dist = get_dist(i - x, j - y);
+ if (inside(i, j) && dist < radius) {
  // Normalize di and dj and round them to an int so they can be used as indicies
  float normIf = (float(i - x)/ radius);
  float normJf = (float(j - y)/ radius);
@@ -231,7 +238,7 @@
  }
 
 
- float newAlt = usedGrad * get_dist(i - x, j - y) + goalAlt;
+ float newAlt = usedGrad * dist + goalAlt;
 
  // if the change in height and what is supposed to be the change in height
  // are the same sign then we can change the height
@@ -245,6 +252,10 @@
  }
 }
 
+void Map::setHeight(int x, int y, float height) {
+ cells[x][y].height = height;
+}
+
 void Map::setRefAlt(int x, int y) {
  if (inside(x, y)) {
  refAlt = static_cast<int>(cells[x][y].height);
@@ -315,6 +326,10 @@
  }
 }
 
+void Map::setSurface(int x, int y, int surface) {
+ cells[x][y].surface = surface;
+}
+
 void Map::changeObject(int x, int y, int object, int radius) {
  int i, j;
  int dist;
@@ -332,6 +347,11 @@
  }
 }
 
+void Map::setObject(int x, int y, int object) {
+ cells[x][y].object = object;
+ cells[x][y].resource = 0;
+}
+
 void Map::changeResource(int x, int y, int resource, int radius) {
  int i, j;
  int dist;
@@ -349,6 +369,11 @@
  }
 }
 
+void Map::setResource(int x, int y, int resource) {
+ cells[x][y].resource = resource;
+ cells[x][y].object = 0;
+}
+
 void Map::changeStartLocation(int x, int y, int faction) {
  if ((faction - 1) < maxFactions && inside(x, y)) {
  startLocations[faction].x = x;

As always, I'd love any feedback about the features, or my code/implementation, etc.

EDIT: This patch is obsolete... see my next post for the actual release candidate undo/redo buttons.
« Last Edit: 1 March 2010, 01:15:45 by zombiepirate »

Trappin

  • Ornithopter
  • *****
  • Posts: 447
    • View Profile
    • MegaGlest Map Compendium
Re: I'd like to help out
« Reply #20 on: 28 February 2010, 08:54:45 »
Omega's map editing chart - thanks Omega! heh.


We need the surface5-custom map editor color changed. The surface5 - custom color, when applied to the map, obscures Object 1 - tree.



Quote
My algorithm right now is more meant for large brushes and large changes to terrain.

Maybe add a stylus selection for the new/old brush on the map editor toolbar menu? Colored fonts would be nice or add a color swatch to the drop-down list.

wish list:



Map editor to tileset XML associations. Select a tileset via the map editor menu bar and the map editor will display tileset-specific surfaces and objects on the radio button list(s). Note: slightly fudged the image - tilesets would be selected on the menu bar THEN the mapper would go to the "Brush" radio selection tab for the object list.

Water leveling brush - automatically sets the terrain to below the walkable threshold and, at the same time, colors the affected surface terrain. WISH GRANTED! heh.

EDIT: Playing with the pirate map editor. Right-click undo would be a nice feature.
« Last Edit: 28 February 2010, 10:27:16 by Trappin »

zombiepirate

  • Guest
Re: I'd like to help out
« Reply #21 on: 1 March 2010, 01:11:15 »
Well I'm happy to announce an actual release candidate for the undo/redo patch. Undo and Redo functions are both working and can be accessed via the edit menu. The patch includes the undo/redo functions and the bug fix to my brush that I mentioned in my previous post. I just finished sorting out about a million segmentation faults so it is still possible one or two are hiding somewhere and I haven't noticed yet but I think I got them all.

Most of the in code documentation is done with the std::cout statements I had in the code while debugging. I think I commented them all out but I might have missed one or two.

Code: [Select]
Index: source/map_editor/map.h
===================================================================
--- source/map_editor/map.h (revision 498)
+++ source/map_editor/map.h (working copy)
@@ -105,6 +105,11 @@
  void changeResource(int x, int y, int resource, int radius);
  void changeStartLocation(int x, int y, int player);
 
+ void setHeight(int x, int y, float height);
+ void setSurface(int x, int y, int surface);
+ void setObject(int x, int y, int object);
+ void setResource(int x, int y, int resource);
+
  void flipX();
  void flipY();
  void reset(int w, int h, float alt, int surf);
Index: source/map_editor/main.cpp
===================================================================
--- source/map_editor/main.cpp (revision 498)
+++ source/map_editor/main.cpp (working copy)
@@ -52,7 +52,7 @@
  object = 0;
  resource = 0;
  startLocation = 1;
- enabledGroup = 0;
+ enabledGroup = ctLocation;
 
 
  //gl canvas
@@ -73,6 +73,8 @@
 
  //edit
  menuEdit = new wxMenu();
+ menuEdit->Append(miEditUndo, wxT("Undo"));
+ menuEdit->Append(miEditRedo, wxT("Redo"));
  menuEdit->Append(miEditReset, wxT("Reset"));
  menuEdit->Append(miEditResetPlayers, wxT("Reset Players"));
  menuEdit->Append(miEditResize, wxT("Resize"));
@@ -189,6 +191,7 @@
 
 void MainWindow::onMouseDown(wxMouseEvent &event) {
  if (event.LeftIsDown()) {
+ program->setUndoPoint(enabledGroup);
  program->setRefAlt(event.GetX(), event.GetY());
  change(event.GetX(), event.GetY());
  }
@@ -265,6 +268,16 @@
  Close();
 }
 
+void MainWindow::onMenuEditUndo(wxCommandEvent &event) {
+ std::cout << "Undo Pressed" << std::endl;
+ program->undo();
+}
+
+void MainWindow::onMenuEditRedo(wxCommandEvent &event) {
+ std::cout << "Redo Pressed" << std::endl;
+ program->redo();
+}
+
 void MainWindow::onMenuEditReset(wxCommandEvent &event) {
  SimpleDialog simpleDialog;
  simpleDialog.addValue("Altitude", "10");
@@ -395,14 +408,14 @@
  uncheckBrush();
  menuBrushHeight->Check(event.GetId(), true);
  height = event.GetId() - miBrushHeight - heightCount / 2 - 1;
- enabledGroup = 0;
+ enabledGroup = ctGlestHeight;
 }
 
 void MainWindow::onMenuPirateBrushHeight(wxCommandEvent &event) {
  uncheckBrush();
  menuPirateBrushHeight->Check(event.GetId(), true);
  height = event.GetId() - miPirateBrushHeight - heightCount / 2 - 1;
- enabledGroup = 5;
+ enabledGroup = ctPirateHeight;
 }
 
 
@@ -410,28 +423,28 @@
  uncheckBrush();
  menuBrushSurface->Check(event.GetId(), true);
  surface = event.GetId() - miBrushSurface;
- enabledGroup = 1;
+ enabledGroup = ctSurface;
 }
 
 void MainWindow::onMenuBrushObject(wxCommandEvent &event) {
  uncheckBrush();
  menuBrushObject->Check(event.GetId(), true);
  object = event.GetId() - miBrushObject - 1;
- enabledGroup = 2;
+ enabledGroup = ctObject;
 }
 
 void MainWindow::onMenuBrushResource(wxCommandEvent &event) {
  uncheckBrush();
  menuBrushResource->Check(event.GetId(), true);
  resource = event.GetId() - miBrushResource - 1;
- enabledGroup = 3;
+ enabledGroup = ctResource;
 }
 
 void MainWindow::onMenuBrushStartLocation(wxCommandEvent &event) {
  uncheckBrush();
  menuBrushStartLocation->Check(event.GetId(), true);
  startLocation = event.GetId() - miBrushStartLocation - 1;
- enabledGroup = 4;
+ enabledGroup = ctLocation;
 }
 
 void MainWindow::onMenuRadius(wxCommandEvent &event) {
@@ -442,22 +455,22 @@
 
 void MainWindow::change(int x, int y) {
  switch (enabledGroup) {
- case 0:
+ case ctGlestHeight:
  program->glestChangeMapHeight(x, y, height, radius);
  break;
- case 1:
+ case ctSurface:
  program->changeMapSurface(x, y, surface, radius);
  break;
- case 2:
+ case ctObject:
  program->changeMapObject(x, y, object, radius);
  break;
- case 3:
+ case ctResource:
  program->changeMapResource(x, y, resource, radius);
  break;
- case 4:
+ case ctLocation:
  program->changeStartLocation(x, y, startLocation);
  break;
- case 5:
+ case ctPirateHeight:
  program->pirateChangeMapHeight(x, y, height, radius);
  break;
  }
@@ -500,6 +513,8 @@
  EVT_MENU(miFileSaveAs, MainWindow::onMenuFileSaveAs)
  EVT_MENU(miFileExit, MainWindow::onMenuFileExit)
 
+ EVT_MENU(miEditUndo, MainWindow::onMenuEditUndo)
+ EVT_MENU(miEditRedo, MainWindow::onMenuEditRedo)
  EVT_MENU(miEditReset, MainWindow::onMenuEditReset)
  EVT_MENU(miEditResetPlayers, MainWindow::onMenuEditResetPlayers)
  EVT_MENU(miEditResize, MainWindow::onMenuEditResize)
Index: source/map_editor/program.cpp
===================================================================
--- source/map_editor/program.cpp (revision 498)
+++ source/map_editor/program.cpp (working copy)
@@ -18,16 +18,176 @@
 
 namespace MapEditor {
 
+////////////////////////////
+// class UndoPoint
+////////////////////////////
+int UndoPoint::undoCount = 0;
+int UndoPoint::w = 0;
+int UndoPoint::h = 0;
+UndoPoint *UndoPoint::current = NULL;
+
+UndoPoint::UndoPoint(ChangeType change) {
+ w = Program::map->getW();
+ h = Program::map->getH();
+
+ undoID = undoCount;
+
+ height = NULL;
+ surface = NULL;
+ object = NULL;
+ resource = NULL;
+
+ switch (change) {
+ case ctGlestHeight:
+ case ctPirateHeight:
+ // Build an array of heights from the map
+ //std::cout << "Building an array of heights to use for our UndoPoint" << std::endl;
+ height = new float*[w];
+ for (int i = 0; i < w; i++) {
+ height[i] = new float [h];
+ for (int j = 0; j < h; j++) {
+ height[i][j] = Program::map->getHeight(i, j);
+ }
+ }
+ std::cout << "Built the array" << std::endl;
+ break;
+ case ctSurface:
+ surface = new int*[w];
+ for (int i = 0; i < w; i++) {
+ surface[i] = new int [h];
+ for (int j = 0; j < h; j++) {
+ surface[i][j] = Program::map->getSurface(i, j);
+ }
+ }
+ break;
+ case ctObject:
+ object = new int*[w];
+ for (int i = 0; i < w; i++) {
+ object[i] = new int [h];
+ for (int j = 0; j < h; j++) {
+ object[i][j] = Program::map->getObject(i, j);
+ }
+ }
+ break;
+ case ctResource:
+ resource = new int*[w];
+ for (int i = 0; i < w; i++) {
+ resource[i] = new int [h];
+ for (int j = 0; j < h; j++) {
+ resource[i][j] = Program::map->getResource(i, j);
+ }
+ }
+ break;
+ case ctLocation:
+ break;
+ case ctAll:
+ break;
+ }
+
+ this->change = change;
+
+ undoCount++;
+ //std::cout << "Increased undoCount to " << undoCount << std::endl;
+ //std::cout << "Appending new change to the list" << std::endl;
+ if (current != NULL) {
+ current->setNext(this);
+ previous = current;
+ } else {
+ previous = NULL;
+ }
+ current = this;
+ next = NULL;
+}
+
+UndoPoint::~UndoPoint() {
+ //std::cout << "attempting to delete an UndoPoint" << std::endl;
+ if (height != NULL) {
+ //std::cout << "deleting heights" << std::endl;
+ for (int i = 0; i < w; i++) {
+ delete height[i];
+ }
+ }
+ if (resource != NULL) {
+ //std::cout << "deleting resources" << std::endl;
+ for (int i = 0; i < w; i++) {
+ delete resource[i];
+ }
+ }
+ if (object != NULL) {
+ //std::cout << "deleting objects" << std::endl;
+ for (int i = 0; i < w; i++) {
+ delete object[i];
+ }
+ }
+ if (surface != NULL) {
+ //std::cout << "deleting surfaces" << std::endl;
+ for (int i = 0; i < w; i++) {
+ delete surface[i];
+ }
+ }
+ // Make sure our links don't break
+ //std::cout << "fixing the list" << std::endl;
+ if (previous != NULL) previous->setNext(next);
+ if (next != NULL) next->setPrevious(previous);
+ if (this == current) current = previous;
+ //std::cout << "Current id is now " << current->undoID << std::endl;
+}
+
+void UndoPoint::revert() {
+ //std::cout << "attempting to revert last changes to " << undoID << std::endl;
+ switch (change) {
+ case ctGlestHeight:
+ case ctPirateHeight:
+ // Restore the array of heights to the map
+ //std::cout << "attempting to restore the height array" << std::endl;
+ for (int i = 0; i < w; i++) {
+ for (int j = 0; j < h; j++) {
+ Program::map->setHeight(i, j, height[i][j]);
+ }
+ }
+ break;
+ case ctSurface:
+ //std::cout << "attempting to restore the surface array" << std::endl;
+ for (int i = 0; i < w; i++) {
+ for (int j = 0; j < h; j++) {
+ Program::map->setSurface(i, j, surface[i][j]);
+ }
+ }
+ break;
+ case ctObject:
+ for (int i = 0; i < w; i++) {
+ for (int j = 0; j < h; j++) {
+ Program::map->setObject(i, j, object[i][j]);
+ }
+ }
+ break;
+ case ctResource:
+ for (int i = 0; i < w; i++) {
+ for (int j = 0; j < h; j++) {
+ Program::map->setResource(i, j, resource[i][j]);
+ }
+ }
+ break;
+ case ctLocation:
+ break;
+ }
+ //std::cout << "reverted changes (we hope)" << std::endl;
+}
+
 // ===============================================
 // class Program
 // ===============================================
 
+Map *Program::map = NULL;
+
 Program::Program(int w, int h) {
  cellSize = 6;
  ofsetX = 0;
  ofsetY = 0;
  map = new Map();
  renderer.init(w, h);
+ undoIterator = NULL;
+ undoBase = NULL;
 }
 
 Program::~Program() {
@@ -58,6 +218,67 @@
  map->changeStartLocation((x - ofsetX) / cellSize, (y + ofsetY) / cellSize, player);
 }
 
+void Program::setUndoPoint(ChangeType change) {
+ std::cout << "attempting to set a new UndoPoint from change " << change << std::endl;
+ if (undoIterator != NULL && undoIterator->getNext() != NULL) {
+ //std::cout << "possibly deleting the head of the list" << std::endl;
+ //std::cout << "======================================" << std::endl;
+ //std::cout << "The head of the list is " << undoIterator->undoID << std::endl;
+ UndoPoint *undoTemp = undoIterator->getNext();
+ //std::cout << "undoTemp (undoIterator-next) is " << undoTemp->undoID << std::endl;
+ while (undoTemp != NULL && undoTemp->getNext() != NULL) {
+ undoTemp = undoTemp->getNext();
+ //std::cout << "undoTemp is now " << undoTemp->undoID << std::endl;
+ //std::cout << "deleted id " << undoTemp->getPrevious()->undoID << std::endl;
+ delete undoTemp->getPrevious();
+ if (undoTemp->getNext() == NULL) {
+ //std::cout << "deleted id " << undoTemp->undoID << std::endl;
+ delete undoTemp;
+ undoTemp = NULL;
+ //std::cout << "finished deleting the head of the list" << std::endl;
+ //std::cout << "======================================" << std::endl;
+ }
+ }
+ }
+ undoIterator = new UndoPoint(change);
+ if (undoBase == NULL) {
+ undoBase = undoIterator;
+ }
+ //std::cout << "set a new UndoPoint id " << undoIterator->undoID << std::endl;
+}
+
+void Program::undo() {
+ if (undoIterator != NULL) {
+ if (undoIterator->getNext() == NULL) {
+ //std::cout << "Backing up the newest change" << std::endl;
+ new UndoPoint(undoIterator->getChange());
+ }
+ //std::cout << "Undoing changes" << std::endl;
+ undoIterator->revert();
+ undoIterator = undoIterator->getPrevious();
+ //if (undoIterator != NULL) std::cout << "UndoIterator is now id " << undoIterator->undoID << std::endl;
+ //else std::cout << "UndoIterator is NULL" << std::endl;
+ } //else std::cout << "No changes to undo" << std::endl;
+}
+
+void Program::redo() {
+ if (undoIterator != NULL) {
+ if (undoIterator->getNext() != NULL && undoIterator->getNext()->getNext() != NULL) {
+ //std::cout << "Redoing changes" << std::endl;
+ undoIterator = undoIterator->getNext();
+ undoIterator->getNext()->revert();
+ //std::cout << "UndoIterator is now id " << undoIterator->undoID << std::endl;
+ } //else std::cout << "No changes to redo" << std::endl;
+ } else {
+ if (undoBase != NULL && undoBase->getNext() != NULL) {
+ //std::cout << "Redoing changes" << std::endl;
+ undoIterator = undoBase;
+ undoIterator->getNext()->revert();
+ //std::cout << "UndoIterator is now id " << undoIterator->undoID << std::endl;
+ } //else std::cout << "No changes to redo" << std::endl;
+ }
+}
+
 void Program::renderMap(int w, int h) {
  renderer.renderMap(map, ofsetX, ofsetY, w, h, cellSize);
 }
Index: source/map_editor/main.h
===================================================================
--- source/map_editor/main.h (revision 498)
+++ source/map_editor/main.h (working copy)
@@ -53,6 +53,8 @@
  miFileSaveAs,
  miFileExit,
 
+ miEditUndo,
+ miEditRedo,
  miEditReset,
  miEditResetPlayers,
  miEditResize,
@@ -105,7 +107,7 @@
  int object;
  int resource;
  int startLocation;
- int enabledGroup;
+ ChangeType enabledGroup;
 
 public:
  MainWindow();
@@ -123,6 +125,8 @@
  void onMenuFileSaveAs(wxCommandEvent &event);
  void onMenuFileExit(wxCommandEvent &event);
 
+ void onMenuEditUndo(wxCommandEvent &event);
+ void onMenuEditRedo(wxCommandEvent &event);
  void onMenuEditReset(wxCommandEvent &event);
  void onMenuEditResetPlayers(wxCommandEvent &event);
  void onMenuEditResize(wxCommandEvent &event);
Index: source/map_editor/program.h
===================================================================
--- source/map_editor/program.h (revision 498)
+++ source/map_editor/program.h (working copy)
@@ -19,6 +19,61 @@
 
 class MainWindow;
 
+enum ChangeType {
+ ctGlestHeight,
+ ctSurface,
+ ctObject,
+ ctResource,
+ ctLocation,
+ ctPirateHeight,
+ ctAll
+};
+
+// =============================================
+// class Undo Point
+// A linked list class that is more of an extension / modification on
+// the already existing Cell struct in map.h
+// Provides the ability to only specify a certain property of the map to change
+// =============================================
+class UndoPoint {
+ private:
+ // Only keep a certain number of undo points in memory otherwise
+ // Big projects could hog a lot of memory
+ const static int MAX_UNDO_LIST_SIZE = 100; // TODO get feedback on this value
+ static int undoCount;
+
+ ChangeType change;
+
+ // Pointers to arrays of each property
+ int **surface;
+ int **object;
+ int **resource;
+ float **height;
+
+ // Map width and height
+ static int w;
+ static int h;
+
+ // Pointers to the next and previous nodes of the list
+ // The current pointer is a static pointer to the front of the list
+ UndoPoint *next;
+ UndoPoint *previous;
+ static UndoPoint *current;
+
+ public:
+ UndoPoint(ChangeType change);
+ ~UndoPoint();
+ void revert();
+
+ int undoID;
+
+ inline UndoPoint* getNext() const { return next; }
+ inline UndoPoint* getPrevious() const { return previous; }
+ inline ChangeType getChange() const { return change; }
+ inline void setNext(UndoPoint *n) { this->next = n; }
+ inline void setPrevious(UndoPoint *p) { this->previous = p; }
+};
+
 // ===============================================
 // class Program
 // ===============================================
@@ -28,8 +83,15 @@
  Renderer renderer;
  int ofsetX, ofsetY;
  int cellSize;
- Map *map;
+ static Map *map;
+ friend class UndoPoint;
 
+ // Every mouse click this will be changed
+ UndoPoint *undoIterator;
+ // This pointer just holds the base of the list in case we want to
+ // Redo from the base or shorten the list from the base
+ UndoPoint *undoBase;
+
 public:
  Program(int w, int h);
  ~Program();
@@ -42,6 +104,10 @@
  void changeMapResource(int x, int y, int resource, int radius);
  void changeStartLocation(int x, int y, int player);
 
+ void setUndoPoint(ChangeType change);
+ void undo();
+ void redo();
+
  //map ops
  void reset(int w, int h, int alt, int surf);
  void resize(int w, int h, int alt, int surf);
@@ -67,7 +133,7 @@
  void incCellSize(int i);
  void resetOfset();
 
- const Map *getMap() {return map;}
+ static const Map *getMap() {return map;}
 };
 
 }// end namespace
Index: source/map_editor/map.cpp
===================================================================
--- source/map_editor/map.cpp (revision 498)
+++ source/map_editor/map.cpp (working copy)
@@ -120,6 +120,12 @@
  goalAlt = overBounds;
  }
 
+ // If the radius is 1 don't bother doing any calculations
+ if (radius == 1) {
+ cells[x][y].height = goalAlt;
+ return;
+ }
+
  // Get Old height reference points and compute gradients
  // from the heights of the sides and corners of the brush to the centre goal height
  float gradient[3][3]; // [i][j]
@@ -156,7 +162,8 @@
  radius -= 1;
  for (int i = x - radius; i <= x + radius; i++) {
  for (int j = y - radius; j <= y + radius; j++) {
- if (inside(i, j)) {
+ int dist = get_dist(i - x, j - y);
+ if (inside(i, j) && dist < radius) {
  // Normalize di and dj and round them to an int so they can be used as indicies
  float normIf = (float(i - x)/ radius);
  float normJf = (float(j - y)/ radius);
@@ -231,7 +238,7 @@
  }
 
 
- float newAlt = usedGrad * get_dist(i - x, j - y) + goalAlt;
+ float newAlt = usedGrad * dist + goalAlt;
 
  // if the change in height and what is supposed to be the change in height
  // are the same sign then we can change the height
@@ -245,6 +252,10 @@
  }
 }
 
+void Map::setHeight(int x, int y, float height) {
+ cells[x][y].height = height;
+}
+
 void Map::setRefAlt(int x, int y) {
  if (inside(x, y)) {
  refAlt = static_cast<int>(cells[x][y].height);
@@ -315,6 +326,10 @@
  }
 }
 
+void Map::setSurface(int x, int y, int surface) {
+ cells[x][y].surface = surface;
+}
+
 void Map::changeObject(int x, int y, int object, int radius) {
  int i, j;
  int dist;
@@ -332,6 +347,11 @@
  }
 }
 
+void Map::setObject(int x, int y, int object) {
+ cells[x][y].object = object;
+ cells[x][y].resource = 0;
+}
+
 void Map::changeResource(int x, int y, int resource, int radius) {
  int i, j;
  int dist;
@@ -349,6 +369,11 @@
  }
 }
 
+void Map::setResource(int x, int y, int resource) {
+ cells[x][y].resource = resource;
+ cells[x][y].object = 0;
+}
+
 void Map::changeStartLocation(int x, int y, int faction) {
  if ((faction - 1) < maxFactions && inside(x, y)) {
  startLocations[faction].x = x;

Little Helper

  • Guest
Re: I'd like to help out
« Reply #22 on: 1 March 2010, 01:37:22 »
Can you make the map editor have more object options/ brushes?

zombiepirate

  • Guest
Re: I'd like to help out
« Reply #23 on: 1 March 2010, 01:44:19 »
The objects aren't a map editor limitation it's a tileset/glest limitation. I did make a new height brush though...

If you want something in particular you're going to have to be much more specific.


Little Helper

  • Guest
Re: I'd like to help out
« Reply #24 on: 1 March 2010, 01:47:59 »
In the brush menu -> object there are only 10 objects I have 15 different objects, with the object limitation in the Glest Map editor I can't place my other 5 objects anywhere. No, I am not going to group all of those object together into one object.