Jul 21, 2009 at 1:36 AM
Join Date: Apr 5, 2008
Location:
Posts: 776
Or an option for Expert / Noob mode?
No. The problem with noobs (as opposed to newbs) it that the have no capacity for learning or figuring anything out themselves.Schokobecher said:Or an option for Expert / Noob mode?
dooey100 said:An undo stack would be awesome, although I understand they are rather hard to implement, and would need a fairly significant rewrite for a lot of the map editing functions. (I've been poking around in the source a bit, although this is the first time I've really read someone else's code, and I must say I'm awful at it. Not to mention that I don't know that much C++ in the first place)
Creating a stack would be easy. Limiting the number of undos to the stack would also be easy. The hard part is writing every action to the stack with enough information to undo these actions, using this information to revert whatever you are working on to it's previous state with minimal consumption of resources, and writing specific code for each situation it is required for. Tile changed? Tile change undo code. Script changed? Text change undo code.dooey100 said:Hmmm, this got me thinking about easy ways to implement an undo stack, and since I've done all this thinking, I might as well post the results here. I don't know how much programming experience you have, Wistil, but it is almost certainly more then mine, so feel free to ignore this.
First, have a "change the map" function, which, as well as changing the map tile in location X, also writes the location and previous value to an undo stack. (and increases the stack pointer and all that other stuff needing stacks). Calling the "undo" function "pops" the last value off the stack, changing it back to what it was before, and decrementing the stack pointer. But what about functions that change multiple tiles? You could have a value you can put on the stack after each function that changes multiple tiles, and then when you press undo, it keeps "poping" values off the stack until it reaches this value.[/ramble]
[color=#7F7F7F]Public Class[/COLOR] MapUndo
[color=#7F7F7F]Public[/COLOR] Tiles()() [color=#7F7F7F]As Byte[/COLOR]
[color=#7F7F7F]Public Sub New[/COLOR]([color=#7F7F7F]ByVal[/COLOR] SourceTiles()()[color=#7F7F7F] As Byte[/COLOR])
Tiles()() = SourceTiles()()
[color=#7F7F7F]End Sub[/COLOR]
[color=#7F7F7F]ReadOnly Property[/COLOR] Width() [color=#7F7F7F]As UInt32[/COLOR]
[color=#7F7F7F]Get[/COLOR]
[color=#7F7F7F]Return[/COLOR] Tiles.GetUpperBound(0)
[color=#7F7F7F]End Get[/COLOR]
[color=#7F7F7F]End Property[/COLOR]
[color=#7F7F7F]ReadOnly Property[/COLOR] Height() [color=#7F7F7F]As UInt32[/COLOR]
[color=#7F7F7F]Get[/COLOR]
[color=#7F7F7F]Return[/COLOR] Tiles.GetUpperBound(1)
[color=#7F7F7F]End Get[/COLOR]
[color=#7F7F7F]End Property[/COLOR]
[color=#7F7F7F]End Class[/COLOR]
[color=#7F7F7F]Public Const[/COLOR] UndoSize [color=#7F7F7F]As Byte[/COLOR] = 16
[color=#7F7F7F]Public[/COLOR] MapBackup(UndoSize) [color=#7F7F7F]As[/COLOR] MapUndo
[color=#7F7F7F]Public Sub[/COLOR] InsertBackup([color=#7F7F7F]ByVal[/COLOR] SourceTiles()() [color=#7F7F7F]As Byte[/COLOR])
[color=#7F7F7F]Dim[/COLOR] Count [color=#7F7F7F]As Byte[/COLOR]
[color=#7F7F7F]If[/COLOR] MapBackup(UndoSize) <> [color=#7F7F7F]Null[/COLOR]
[color=#7F7F7F]For[/COLOR] Count = UndoSize - 1 [color=#7F7F7F]To[/COLOR] 0 [color=#7F7F7F]Step[/COLOR] -1
MapBackup(Count + 1) = MapBackup(Count)
[color=#7F7F7F]Next[/COLOR]
MapBackup(0) = [color=#7F7F7F]New[/COLOR] MapUndo(SourceTiles()())
[color=#7F7F7F]Else[/COLOR]
[color=#7F7F7F]For[/COLOR] Count = 0 [color=#7F7F7F]To[/COLOR] UndoSize
[color=#7F7F7F]If[/COLOR] MapBackup(Count) = [color=#7F7F7F]Null[/COLOR],
MapBackup(Count) = [color=#7F7F7F]New[/COLOR] MapUndo(SourceTiles()())
[color=#7F7F7F]End If[/COLOR]
[color=#7F7F7F]Next[/COLOR]
[color=#7F7F7F]End If[/COLOR]
[color=#7F7F7F]End Sub[/COLOR]
[color=#7F7F7F]Public Class[/COLOR] MapTiles
[color=#7F7F7F]Public[/COLOR] X [color=#7F7F7F]As UShort[/COLOR]
[color=#7F7F7F]Public[/COLOR] Y [color=#7F7F7F]As UShort[/COLOR]
[color=#7F7F7F]Public[/COLOR] Type [color=#7F7F7F]As Byte[/COLOR]
[color=#7F7F7F]Public Sub New[/COLOR]([color=#7F7F7F]ByVal[/COLOR] XPos[color=#7F7F7F] As UShort[/COLOR], [color=#7F7F7F]ByVal[/COLOR] YPos[color=#7F7F7F] As UShort[/COLOR], [color=#7F7F7F]ByVal[/COLOR] TileType[color=#7F7F7F] As Byte[/COLOR])
X = XPos
Y = YPos
Type = TileType
[color=#7F7F7F]End Sub[/COLOR]
[color=#7F7F7F]End Class[/COLOR]
S. P. Gardebiter said:It's way easier.
*snip
dooey100 said:Easier it may be, but memory efficient it is not
Which might not even be a problem, but I had more fun doing it my way anyway.
After every single change? Isn't that somewhat inefficient?S. P. Gardebiter said:That's all your undo function will need. It just backups all the tiles.
andwhyisit said:After every single change? Isn't that somewhat inefficient?
andwhyisit said:No. The problem with noobs (as opposed to newbs) it that the have no capacity for learning or figuring anything out themselves.
Newb mode is fine (maybe little ? icons that explain what each thing does when you roll over them so that you don't need separate "modes"), but noob mode sounds painful.
No, just add a Delete All Entities function. If you want to erase all the tiles, you can use the existing Fill function (at least, I think it already exists?).Mr. Fist said:Maybe an Empty Map feature?
Just click on it from a menu and the map turns into a black space devoid of entities or solid ground.
I'm not sure I agree with it being a stack, though. I've thought a little about a way to implement an undo list. The idea was to have an UndoList class (which would probably have only a single instance) containing an std::list (a doubly-linked list, in case you're unfamiliar with the STL) and an iterator pointing to the current element (an iterator is a pointer or a class that behaves like one; if you didn't use the STL you'd probably just use a pointer). If you haven't undone anything since your last action, the iterator would point at a null entry indicating the end of the list.dooey100 said:An undo stack would be awesome, although I understand they are rather hard to implement, and would need a fairly significant rewrite for a lot of the map editing functions.
Uh... I don't think I like this idea. I could accept the potential usefulness of a separate undo list for the script editor, but I think there should be a single list for anything else.dooey100 said:I was assuming each major area of the editor would have its own stack. EG the map editor would have a stack, the entity editor would have a stack, and the script editor would have a stack (although having a stack seems less necessary for scripting)
Creating an entity is not necessarily the action to take when undoing a delete entity action. If the structure storing an entity is complex enough, it would probably be better to not delete it at all, but simply store a pointer to it in the undo action.dooey100 said:Also you wouldn't need new functions for undos, as its always just the opposite of whatever was done. Deleted an entity here? Undo = create an entity. Create an entity? Undo = delete the entity. Change a map tile? Undo = change a map tile
That's not the sole exception. There are plenty of programs that support an unlimited undo list. Some of them allow you to choose the limit.dooey100 said:To limit the memory usage, limit the stack size. Yeah, that means you can only undo so far, but almost every program I've seen can only undo so far. (The sole exception being Paint.net)
As you can see, I quite agree. I'll even post the code I wrote for this (for a different program, but it work just as well here). Note that this code is still incomplete and untested.S. P. Gardebiter said:It's way easier.
Why don't you use classes for a undo function?
[color=#7F7F7F]// undo.h[/COLOR]
[color=#7F7F7F]#include[/COLOR] <list>
[color=#7F7F7F]class[/COLOR] cAction {
[color=#7F7F7F]public[/COLOR]:
[color=#7F7F7F]virtual void[/COLOR] undo() = 0; [color=#7F7F7F]// undoes this action if it has not already been undone[/COLOR]
[color=#7F7F7F]virtual void[/COLOR] redo() = 0; [color=#7F7F7F]// redoes this action if it has been undone[/COLOR]
[color=#7F7F7F]virtual bool[/COLOR] isDone() = 0; [color=#7F7F7F]// checks to see whether the action has been undone; returns false if it has[/COLOR]
[color=#7F7F7F]virtual[/COLOR] [color=#7F7F7F]std[/COLOR]::[color=#7F7F7F]string[/COLOR] getActionName() = 0; [color=#7F7F7F]// returns the name of this action for display in the Edit menu[/COLOR]
[color=#7F7F7F]virtual[/COLOR] ~cAction();
};
[color=#7F7F7F]class[/COLOR] cUndoList {
[color=#7F7F7F]std[/COLOR]::[color=#7F7F7F]list[/COLOR]<cAction*> theList;
[color=#7F7F7F]std[/COLOR]::[color=#7F7F7F]list[/COLOR]<cAction*>::[color=#7F7F7F]iterator[/COLOR] cur, lastSave;
[color=#7F7F7F]std[/COLOR]::[color=#7F7F7F]size_t[/COLOR] num_actions;
[color=#7F7F7F]public[/COLOR]:
cUndoList();
[color=#7F7F7F]void[/COLOR] undo(); [color=#7F7F7F]// undoes the current action and decrements the cur pointer[/COLOR]
[color=#7F7F7F]void[/COLOR] redo(); [color=#7F7F7F]// increments the cur pointer and redoes the current action[/COLOR]
[color=#7F7F7F]void[/COLOR] save(); [color=#7F7F7F]// sets the last saved action to the current action[/COLOR]
[color=#7F7F7F]void[/COLOR] revert(); [color=#7F7F7F]// undoes all actions back to (but excluding) the last saved action[/COLOR]
[color=#7F7F7F]void[/COLOR] add(cAction* what);
[color=#7F7F7F]static[/COLOR] [color=#7F7F7F]std[/COLOR]::[color=#7F7F7F]size_t[/COLOR] maxUndoSize;
};
[color=#7F7F7F]// undo.cpp[/COLOR]
[color=#7F7F7F]#include[/COLOR] "undo.h"
cUndoList::cUndoList(){
lastSave = cur = theList.[color=#7F7F7F]begin[/COLOR]();
}
[color=#7F7F7F]std[/COLOR]::[color=#7F7F7F]size_t[/COLOR] cUndoList::maxUndoSize = 0;
[color=#7F7F7F]// TODO: These functions should have error checking to ensure they do not access an out of bounds action; basically, if cur == theList.[color=#7F7F7F]end[/COLOR](), then there are no more actions to redo[/COLOR]
[color=#7F7F7F]void[/COLOR] cUndoList::undo(){
cur--;
(*cur)->undo();
}
[color=#7F7F7F]void[/COLOR] cUndoList::redo(){
(*cur)->redo();
cur++;
}
[color=#7F7F7F]void[/COLOR] cUndoList::save(){
lastSave = cur;
}
[color=#7F7F7F]void[/COLOR] cUndoList::revert(){
[color=#7F7F7F]while[/COLOR](cur != lastSave) undo();
}
[color=#7F7F7F]void[/COLOR] cUndoList::add(cAction* what){
theList.[color=#7F7F7F]push_back[/COLOR](what);
num_actions++;
[color=#7F7F7F]while[/COLOR](num_actions > maxUndoSize)
theList.[color=#7F7F7F]pop_front[/COLOR](), num_actions--;
}
If you're going to do that, why not allow the user to pick and choose which warnings are suppressed and which editing tools are available?Schokobecher said:I meant it like:
Normal (warnings, not all editing tools visible (like ASM and stuff))
Advanced (Everything visible, less warning, more powerful)
That would be the next levelIf you're going to do that, why not allow the user to pick and choose which warnings are suppressed and which editing tools are available?
GIRakaCHEEZER said:Was finally able to dl the newest version and... =D
The tile-type overlay display isn't working, and when I load scripts it doesn't load the commands. I think the executable is not loading the .txt and that .png file for some reason. Here's some pics.
I'm running xp, service pack 2 btw. At work though they force me to use a Vista =(.
DragonBoots said:
@ Gir: Make sure you have the CE_TSC_Info.txt file in the directory.
And if you've made any changes to it, make sure that there is no blank lines near the top, or attempts to include comments with a "<" or something.