2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/editor/ged_undo.c,v 1.3 2000/02/19 13:10:48 toml Exp $
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
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
)
54 delta_code
-=_DELTA_TEXBASE
;
55 which_face
=(delta_code
/5);
57 *size
=2; // since i happen to know sizeof(fixang=short=ushort)==2
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
)
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
);
85 static int get_max_deltas(editBrush
*br
)
87 if (brushGetType(br
)!=brType_TERRAIN
)
88 return _DELTA_TEXBASE
-1;
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
;
100 offset
=get_delta_info(i
,&sz
,b1
);
101 if (memcmp(((uchar
*)b1
)+offset
,((uchar
*)b2
)+offset
,sz
)!=0)
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
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
;
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)
145 else if (new_ver
->txs
[i
].tx_id
!=old_ver
->txs
[i
].tx_id
)
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
);
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");
169 //#define UNDO_STACK_TRACE
170 #ifdef UNDO_STACK_TRACE
171 #define traceUndoStack() editUndoStackPrint()
173 #define traceUndoStack()
177 static void gedundo_undo(int count
)
180 if (temp_safety_hack_abort(vBrush_editBrush_Get()))
184 rv
&=editUndoDoUndo();
187 if (rv
) Status("Undo!");
188 else Status("No more Undo information.");
193 static void gedundo_redo(int count
)
196 if (temp_safety_hack_abort(vBrush_editBrush_Get()))
200 rv
&=editUndoDoRedo();
203 if (rv
) Status("Redo!");
204 else Status("No more Redo information.");
209 /////////////////////////////
210 // command declaration
213 static void gedit_undo_stack_trace(void) { editUndoStackPrint(); }
216 Command gedundo_keys
[] =
218 { "undo", FUNC_INT
, gedundo_undo
},
219 { "redo", FUNC_INT
, gedundo_redo
},
221 { "show_undo_stack", FUNC_VOID
, gedit_undo_stack_trace
},
225 void gedundoCommandRegister(void)
227 COMMANDS(gedundo_keys
, HK_BRUSH_EDIT
);