This sort of thing is easy enough in 3.6 but to make it undoable is a bit of a nightmare (or is quite inefficient).
For the next release (3.7), things are a lot better.
Here's the actual code that changes the surface shading (when 'Flat' or 'Smooth' is pressed).
Code:
class UndoableSurfacesSetShading : public Undoable
{
private:
List *surfaces;
List *oldshading;
int newshading;
public:
UndoableSurfacesSetShading(int col)
{
newshading = col;
surfaces = ac_selection_get_whole_surfaces_all();
oldshading = NULL;
}
void execute()
{
List *last = NULL;
int numdone = 0;
display_message("setting shading on surfaces...");
// save the old colours in a list
for (List *p = surfaces; p != NULL; p = p->next)
{
Surface *s = (Surface *)p->data;
last = list_add_item_fast(&oldshading, last, (void *)surface_get_shading(s));
surface_set_shading(s, newshading);
numdone++;
}
redraw_all();
display_message("new shading set on surfaces: %d", numdone);
}
void undo()
{
// restore the original types
display_message("restoring surface shading");
List *cl = oldshading;
int numdone = 0;
for (List *p = surfaces; p != NULL; p = p->next, cl = cl->next)
{
Surface *s = (Surface *)p->data;
int oldshadingt = (int)cl->data;
surface_set_shading(s, oldshadingt);
numdone++;
}
redraw_all();
display_message("shading set on surfaces: %d", numdone);
}
void redo()
{
for (List *p = surfaces; p != NULL; p = p->next)
{
Surface *s = (Surface *)p->data;
surface_set_shading(s, newshading);
}
redraw_all();
}
~UndoableSurfacesSetShading()
{
list_free(&surfaces);
list_free(&oldshading);
}
};
Prototype void selected_set_surface_shading(int indexc)
{
add_undoable("set surface shading", new UndoableSurfacesSetShading(indexc));
}