]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/orienteditor.cpp
The Great Newline Fix
[taylor/freespace2.git] / src / fred2 / orienteditor.cpp
1 /*
2  * $Logfile: /Freespace2/code/FRED2/OrientEditor.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Object orientation editor (or just object editor) dialog box handling code
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:44  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:08  root
14  * Initial import.
15  *
16  * 
17  * 2     10/07/98 6:28p Dave
18  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
19  * Fred. Globalized mission and campaign file extensions. Removed Silent
20  * Threat specific code.
21  * 
22  * 1     10/07/98 3:02p Dave
23  * 
24  * 1     10/07/98 3:00p Dave
25  * 
26  * 18    7/13/98 10:04a Hoffoss
27  * Fixed bug where jump nodes in mission would screw up indexing.
28  * 
29  * 17    3/12/98 2:21p Johnson
30  * Fixed some Fred bugs related to jump nodes.
31  * 
32  * 16    9/16/97 9:41p Hoffoss
33  * Changed Fred code around to stop using Parse_player structure for
34  * player information, and use actual ships instead.
35  * 
36  * 15    8/16/97 2:02a Hoffoss
37  * Made docked objects move together in Fred.
38  * 
39  * 14    8/15/97 8:24p Hoffoss
40  * Fixed bug with orient editor.
41  * 
42  * 13    8/14/97 3:14p Hoffoss
43  * Fixed name displayed for players.
44  * 
45  * 12    7/29/97 2:20p Hoffoss
46  * Fixed some minor bugs.
47  * 
48  * 11    6/26/97 11:18a Hoffoss
49  * Fixed bug in orient editor.  OBJ_POINT type wasn't accounted for.
50  * 
51  * 10    5/20/97 2:28p Hoffoss
52  * Added message box queries for close window operation on all modal
53  * dialog boxes.
54  * 
55  * 9     5/14/97 4:08p Lawrance
56  * removing my_index from game arrays
57  * 
58  * 8     4/17/97 2:01p Hoffoss
59  * All dialog box window states are saved between sessions now.
60  * 
61  * 7     3/12/97 4:33p Hoffoss
62  * added spin controls to orient editor, light intensity level can be
63  * specified in BG editor.
64  * 
65  * 6     2/28/97 11:31a Hoffoss
66  * Implemented modeless dialog saving and restoring, and changed some
67  * variables names.
68  * 
69  * 5     2/21/97 5:34p Hoffoss
70  * Added extensive modification detection and fixed a bug in initial
71  * orders editor.
72  * 
73  * 4     2/17/97 5:28p Hoffoss
74  * Checked RCS headers, added them were missing, changing description to
75  * something better, etc where needed.
76  *
77  * $NoKeywords: $
78  */
79
80 #include "stdafx.h"
81 #include "fred.h"
82 #include "orienteditor.h"
83 #include "management.h"
84 #include "linklist.h"
85 #include "fredview.h"
86
87 #ifdef _DEBUG
88 #define new DEBUG_NEW
89 #undef THIS_FILE
90 static char THIS_FILE[] = __FILE__;
91 #endif
92
93 #define PREC    0.0001f
94
95 /////////////////////////////////////////////////////////////////////////////
96 // orient_editor dialog
97
98 orient_editor::orient_editor(CWnd* pParent /*=NULL*/)
99         : CDialog(orient_editor::IDD, pParent)
100 {
101         vector pos;
102
103         //{{AFX_DATA_INIT(orient_editor)
104         m_object_index = 0;
105         m_point_to = FALSE;
106         m_position_z = _T("");
107         m_position_y = _T("");
108         m_position_x = _T("");
109         m_location_x = _T("0.0");
110         m_location_y = _T("0.0");
111         m_location_z = _T("0.0");
112         //}}AFX_DATA_INIT
113         Assert(query_valid_object());
114         pos = Objects[cur_object_index].pos;
115         m_position_x.Format("%.1f", pos.x);
116         m_position_y.Format("%.1f", pos.y);
117         m_position_z.Format("%.1f", pos.z);
118 }
119
120 void orient_editor::DoDataExchange(CDataExchange* pDX)
121 {
122         CDialog::DoDataExchange(pDX);
123         //{{AFX_DATA_MAP(orient_editor)
124         DDX_Control(pDX, IDC_SPIN6, m_spin6);
125         DDX_Control(pDX, IDC_SPIN5, m_spin5);
126         DDX_Control(pDX, IDC_SPIN4, m_spin4);
127         DDX_Control(pDX, IDC_SPIN3, m_spin3);
128         DDX_Control(pDX, IDC_SPIN2, m_spin2);
129         DDX_Control(pDX, IDC_SPIN1, m_spin1);
130         DDX_CBIndex(pDX, IDC_OBJECT_LIST, m_object_index);
131         DDX_Check(pDX, IDC_POINT_TO_CHECKBOX, m_point_to);
132         DDX_Text(pDX, IDC_POSITION_Z, m_position_z);
133         DDX_Text(pDX, IDC_POSITION_Y, m_position_y);
134         DDX_Text(pDX, IDC_POSITION_X, m_position_x);
135         DDX_Text(pDX, IDC_LOCATION_X, m_location_x);
136         DDX_Text(pDX, IDC_LOCATION_Y, m_location_y);
137         DDX_Text(pDX, IDC_LOCATION_Z, m_location_z);
138         //}}AFX_DATA_MAP
139 }
140
141 BEGIN_MESSAGE_MAP(orient_editor, CDialog)
142         //{{AFX_MSG_MAP(orient_editor)
143         ON_WM_CLOSE()
144         //}}AFX_MSG_MAP
145 END_MESSAGE_MAP()
146
147 /////////////////////////////////////////////////////////////////////////////
148 // orient_editor message handlers
149
150 BOOL orient_editor::OnInitDialog() 
151 {
152         char text[80];
153         int type;
154         CComboBox *box;
155         object *ptr;
156
157         CDialog::OnInitDialog();
158         theApp.init_window(&Object_wnd_data, this);
159         ((CButton *) GetDlgItem(IDC_POINT_TO_OBJECT))->SetCheck(1);
160         box = (CComboBox *) GetDlgItem(IDC_OBJECT_LIST);
161         box->ResetContent();
162
163         total = 0;
164         ptr = GET_FIRST(&obj_used_list);
165         while (ptr != END_OF_LIST(&obj_used_list)) {
166                 if (Marked != 1 || OBJ_INDEX(ptr) != cur_object_index) {
167                         if ((ptr->type == OBJ_START) || (ptr->type == OBJ_SHIP)) {
168                                 box->AddString(Ships[ptr->instance].ship_name);
169                                 index[total++] = OBJ_INDEX(ptr);
170
171                         } else if (ptr->type == OBJ_WAYPOINT) {
172                                 sprintf(text, "%s:%d", Waypoint_lists[ptr->instance / 65536].name,
173                                         (ptr->instance & 0xffff) + 1);
174
175                                 box->AddString(text);
176                                 index[total++] = OBJ_INDEX(ptr);
177
178                         } else if ((ptr->type == OBJ_POINT) || (ptr->type == OBJ_JUMP_NODE)) {
179                         } else
180                                 Assert(0);  // unknown object type.
181                 }
182
183                 ptr = GET_NEXT(ptr);
184         }
185
186         type = Objects[cur_object_index].type;
187         if (Marked == 1 && type == OBJ_WAYPOINT) {
188                 GetDlgItem(IDC_POINT_TO_CHECKBOX)->EnableWindow(0);
189                 GetDlgItem(IDC_POINT_TO_OBJECT)->EnableWindow(0);
190                 GetDlgItem(IDC_POINT_TO_LOCATION)->EnableWindow(0);
191                 GetDlgItem(IDC_OBJECT_LIST)->EnableWindow(0);
192                 GetDlgItem(IDC_LOCATION_X)->EnableWindow(0);
193                 GetDlgItem(IDC_LOCATION_Y)->EnableWindow(0);
194                 GetDlgItem(IDC_LOCATION_Z)->EnableWindow(0);
195                 m_object_index = -1;
196
197         } else {
198                 m_object_index = 0;
199         }
200
201         m_spin1.SetRange(99999, -99999);
202         m_spin1.SetPos((int) convert(m_position_x));
203         m_spin2.SetRange(99999, -99999);
204         m_spin2.SetPos((int) convert(m_position_y));
205         m_spin3.SetRange(99999, -99999);
206         m_spin3.SetPos((int) convert(m_position_z));
207         m_spin4.SetRange(99999, -99999);
208         m_spin5.SetRange(99999, -99999);
209         m_spin6.SetRange(99999, -99999);
210         UpdateData(FALSE);
211         return TRUE;
212 }
213
214 int orient_editor::query_modified()
215 {
216         float dif;
217
218         dif = Objects[cur_object_index].pos.x - convert(m_position_x);
219         if ((dif > PREC) || (dif < -PREC))
220                 return 1;
221         dif = Objects[cur_object_index].pos.y - convert(m_position_y);
222         if ((dif > PREC) || (dif < -PREC))
223                 return 1;
224         dif = Objects[cur_object_index].pos.z - convert(m_position_z);
225         if ((dif > PREC) || (dif < -PREC))
226                 return 1;
227
228         if (((CButton *) GetDlgItem(IDC_POINT_TO_CHECKBOX))->GetCheck() == 1)
229                 return 1;
230
231         return 0;
232 }
233
234 void orient_editor::OnOK()
235 {
236         vector delta, pos;
237         object *ptr;
238
239         UpdateData(TRUE);
240         pos.x = convert(m_position_x);
241         pos.y = convert(m_position_y);
242         pos.z = convert(m_position_z);
243
244         if ((((CButton *) GetDlgItem(IDC_POINT_TO_OBJECT))->GetCheck() == 1) ||
245                 (((CButton *) GetDlgItem(IDC_POINT_TO_LOCATION))->GetCheck() == 1))
246                         set_modified();
247
248         vm_vec_sub(&delta, &pos, &Objects[cur_object_index].pos);
249         if (delta.x || delta.y || delta.z)
250                 set_modified();
251
252         ptr = GET_FIRST(&obj_used_list);
253         while (ptr != END_OF_LIST(&obj_used_list)) {
254                 if (ptr->flags & OF_MARKED) {
255                         vm_vec_add2(&ptr->pos, &delta);
256                         update_object(ptr);
257                 }
258
259                 ptr = GET_NEXT(ptr);
260         }
261
262         ptr = GET_FIRST(&obj_used_list);
263         while (ptr != END_OF_LIST(&obj_used_list)) {
264                 if (ptr->flags & OF_MARKED)
265                         object_moved(ptr);
266
267                 ptr = GET_NEXT(ptr);
268         }
269
270         theApp.record_window_data(&Object_wnd_data, this);
271         CDialog::OnOK();
272 }
273
274 void orient_editor::update_object(object *ptr)
275 {
276         if (ptr->type != OBJ_WAYPOINT && m_point_to) {
277                 vector v, loc;
278                 matrix m;
279
280                 memset(&v, 0, sizeof(vector));
281                 loc.x = convert(m_location_x);
282                 loc.y = convert(m_location_y);
283                 loc.z = convert(m_location_z);
284                 if (((CButton *) GetDlgItem(IDC_POINT_TO_OBJECT))->GetCheck() == 1) {
285                         v = Objects[index[m_object_index]].pos;
286                         vm_vec_sub2(&v, &ptr->pos);
287
288                 } else if (((CButton *) GetDlgItem(IDC_POINT_TO_LOCATION))->GetCheck() == 1) {
289                         vm_vec_sub(&v, &loc, &ptr->pos);
290
291                 } else {
292                         Assert(0);  // neither radio button is checked.
293                 }
294
295                 if (!v.x && !v.y && !v.z){
296                         return;  // can't point to itself.
297                 }
298
299                 vm_vector_2_matrix(&m, &v, NULL, NULL);
300                 ptr->orient = m;
301         }
302 }
303
304 float orient_editor::convert(CString &str)
305 {
306         char buf[256];
307         int i, j, len;
308
309         string_copy(buf, str, 255);
310         len = strlen(buf);
311         for (i=j=0; i<len; i++)
312                 if (buf[i] != ',')
313                         buf[j++] = buf[i];
314
315         buf[j] = 0;
316         return (float) atof(buf);
317 }
318
319 void orient_editor::OnCancel()
320 {
321         theApp.record_window_data(&Object_wnd_data, this);
322         CDialog::OnCancel();
323 }
324
325 void orient_editor::OnClose() 
326 {
327         int z;
328
329         if (query_modified()) {
330                 z = MessageBox("Do you want to keep your changes?", "Close", MB_ICONQUESTION | MB_YESNOCANCEL);
331                 if (z == IDCANCEL)
332                         return;
333
334                 if (z == IDYES) {
335                         OnOK();
336                         return;
337                 }
338         }
339
340         CDialog::OnClose();
341 }
342