convert line ends
[canaan.git] / prj / cam / src / editor / ged_undo.c
blobabbd4c26eb0eaba13d79034811de9fb8912c8880
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 // $Header: r:/t2repos/thief2/src/editor/ged_undo.c,v 1.3 2000/02/19 13:10:48 toml Exp $
7 // undo support
9 #include <string.h>
10 #include <stdlib.h>
12 #include <lg.h>
14 #include <editbr.h>
15 #include <editbr_.h>
16 #include <undoredo.h>
17 #include <brinfo.h>
18 #include <brundo.h>
19 #include <gedit.h>
20 #include <ged_undo.h>
21 #include <vbrush.h>
23 #include <status.h>
24 #include <command.h>
25 #include <memall.h>
26 #include <dbmem.h> // must be last header!
28 /// absolutely hideous editbr_ specific craziness
30 #define _DELTA_TX_ID 0
31 #define _DELTA_POS_X 1
32 #define _DELTA_POS_Y 2
33 #define _DELTA_POS_Z 3
34 #define _DELTA_SZ_X 4
35 #define _DELTA_SZ_Y 5
36 #define _DELTA_SZ_Z 6
37 #define _DELTA_ANG_X 7
38 #define _DELTA_ANG_Y 8
39 #define _DELTA_ANG_Z 9
40 #define _DELTA_TEXBASE 10
41 #define _DELTA_TOFF_ID 0
42 #define _DELTA_TOFF_ROT 1
43 #define _DELTA_TOFF_SC 2
44 #define _DELTA_TOFF_X 3
45 #define _DELTA_TOFF_Y 4
46 #define _DELTA_TOFF_CNT 5
47 #define MAX_DELTAS (_DELTA_TEXBASE + (EDITBR_MAX_FACES*_DELTA_TOFF_CNT))
49 static int get_delta_info(int delta_code, int *size, editBrush *br)
51 if (delta_code>=_DELTA_TEXBASE)
53 int which_face;
54 delta_code-=_DELTA_TEXBASE;
55 which_face=(delta_code/5);
56 delta_code%=5;
57 *size=2; // since i happen to know sizeof(fixang=short=ushort)==2
58 switch (delta_code)
60 case _DELTA_TOFF_ID: return (int)(((uchar *)&br->txs[which_face].tx_id)-(uchar *)br);
61 case _DELTA_TOFF_ROT: return (int)(((uchar *)&br->txs[which_face].tx_rot)-(uchar *)br);
62 case _DELTA_TOFF_SC: return (int)(((uchar *)&br->txs[which_face].tx_scale)-(uchar *)br);
63 case _DELTA_TOFF_X: return (int)(((uchar *)&br->txs[which_face].tx_x)-(uchar *)br);
64 case _DELTA_TOFF_Y: return (int)(((uchar *)&br->txs[which_face].tx_y)-(uchar *)br);
67 else if (delta_code==_DELTA_TX_ID)
69 *size=sizeof(short);
70 return (int)((uchar *)&br->tx_id-(uchar *)br);
72 else if (delta_code<=_DELTA_SZ_Z)
74 *size=sizeof(mxs_real);
75 return (int)((uchar *)(((float *)(&br->pos.el[0]))+delta_code-_DELTA_POS_X)-(uchar *)br);
77 else // for now, this means an angle
79 *size=sizeof(mxs_ang);
80 return (int)((uchar *)(((mxs_ang *)(&br->ang.el[0]))+delta_code-_DELTA_ANG_X)-(uchar *)br);
82 return 0;
85 static int get_max_deltas(editBrush *br)
87 if (brushGetType(br)!=brType_TERRAIN)
88 return _DELTA_TEXBASE-1;
89 else
90 return _DELTA_TEXBASE-1+(br->num_faces*_DELTA_TOFF_CNT);
93 // returns number of entries it filled of buf, where each is a #def for which field is changed
94 static int get_delta_list(char *buf, editBrush *b1, editBrush *b2)
96 int max=get_max_deltas(b1), i;
97 int sz, cnt=0, offset;
98 for (i=0; i<max; i++)
100 offset=get_delta_info(i,&sz,b1);
101 if (memcmp(((uchar *)b1)+offset,((uchar *)b2)+offset,sz)!=0)
102 buf[cnt++]=(char)i;
104 return cnt;
107 // called from within undo/redo to make decisions about what to do
108 BOOL gedundo_check_brush_delta(editBrush *new_ver, editBrush *old_ver, editBrush *base_ver)
110 int real_size=sizeof(editBrush)-(EDITBR_MAX_FACES*sizeof(TexInfo));
111 char delta_1[MAX_DELTAS], delta_2[MAX_DELTAS];
112 int delta_1_cnt, delta_2_cnt;
113 editBrush tmp=*new_ver;
115 if (brushGetType(&tmp)==brType_TERRAIN)
116 real_size+=tmp.num_faces*(EDITBR_MAX_FACES*sizeof(TexInfo));
117 tmp.cur_face=old_ver->cur_face; // move across all data we dont care about diffs in
118 tmp.edge=old_ver->edge; tmp.point=old_ver->point; tmp.use_flg=old_ver->use_flg;
119 if (memcmp(&tmp,old_ver,real_size)==0) // for what we care about - these two brushes are the same
120 return FALSE;
121 if (base_ver==NULL) return TRUE; // w/o base, any diff is a real diff
122 if (base_ver->br_id!=new_ver->br_id) return TRUE; // different brush ids, any diff is a real diff
123 if (base_ver->num_faces!=new_ver->num_faces)
125 Warning(("Whoa! this shouldnt be different: faces %d %d %d\n",base_ver->num_faces,old_ver->num_faces,new_ver->num_faces));
126 return TRUE; // something
128 delta_1_cnt=get_delta_list(delta_1,base_ver,old_ver); // what diffs from base->old
129 delta_2_cnt=get_delta_list(delta_2,old_ver,new_ver); // what diffs from old->new
130 if (delta_1_cnt!=delta_2_cnt) return TRUE; // different number of them, bad day
131 // if (delta_1_cnt>1) return TRUE; // this would be for not allowing common multi-axis undo
132 return memcmp(delta_1,delta_2,delta_1_cnt)!=0; // if the delta are the same, punt
135 static BOOL tdelta_texture_only;
136 BOOL gedundo_check_texture_delta(editBrush *new_ver, editBrush *old_ver)
138 BOOL txt_diff, align_diff=FALSE;
139 int i;
141 txt_diff=(new_ver->tx_id!=old_ver->tx_id);
142 for (i=0; i<min(new_ver->num_faces,old_ver->num_faces); i++)
143 if (memcmp(&new_ver->txs[i].tx_rot,&old_ver->txs[i].tx_rot,sizeof(TexInfo)-sizeof(short))!=0)
144 align_diff=TRUE;
145 else if (new_ver->txs[i].tx_id!=old_ver->txs[i].tx_id)
146 txt_diff=TRUE;
147 tdelta_texture_only=!align_diff;
148 return (align_diff||txt_diff);
151 void gedundo_do_texture_delta(editBrush *us)
153 gedit_reassign_texture(us,tdelta_texture_only);
156 // utilities
157 static BOOL temp_safety_hack_abort(editBrush *p)
159 #ifdef NO_MBRUSH_UNDO
160 if (brSelect_Flag(p)&brSelect_VIRTUAL)
162 Status("Sorry, Multibrush Undo broken");
163 return TRUE;
165 #endif
166 return FALSE;
169 //#define UNDO_STACK_TRACE
170 #ifdef UNDO_STACK_TRACE
171 #define traceUndoStack() editUndoStackPrint()
172 #else
173 #define traceUndoStack()
174 #endif
176 // undo-redo UI
177 static void gedundo_undo(int count)
178 { // 0 or 1 means 1
179 bool rv=TRUE;
180 if (temp_safety_hack_abort(vBrush_editBrush_Get()))
181 return;
182 do {
183 traceUndoStack();
184 rv&=editUndoDoUndo();
185 traceUndoStack();
186 } while (--count>0);
187 if (rv) Status("Undo!");
188 else Status("No more Undo information.");
189 if (rv||(count>1))
190 gedit_full_redraw();
193 static void gedundo_redo(int count)
194 { // 0 or 1 means 1
195 bool rv=TRUE;
196 if (temp_safety_hack_abort(vBrush_editBrush_Get()))
197 return;
198 do {
199 traceUndoStack();
200 rv&=editUndoDoRedo();
201 traceUndoStack();
202 } while (--count>0);
203 if (rv) Status("Redo!");
204 else Status("No more Redo information.");
205 if (rv||(count>1))
206 gedit_full_redraw();
209 /////////////////////////////
210 // command declaration
212 #ifdef DBG_ON
213 static void gedit_undo_stack_trace(void) { editUndoStackPrint(); }
214 #endif
216 Command gedundo_keys[] =
218 { "undo", FUNC_INT, gedundo_undo },
219 { "redo", FUNC_INT, gedundo_redo },
220 #ifdef DBG_ON
221 { "show_undo_stack", FUNC_VOID, gedit_undo_stack_trace },
222 #endif
225 void gedundoCommandRegister(void)
227 COMMANDS(gedundo_keys, HK_BRUSH_EDIT);