1 /*
2 C-Dogs SDL
3 A port of the legendary (and fun) action/arcade cdogs.
4 Copyright (c) 2013-2016, 2019-2021 Cong Xu
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 Redistributions of source code must retain the above copyright notice, this
11 list of conditions and the following disclaimer.
12 Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include "editor_ui_classic.h"
29
30 #include <cdogs/draw/draw_actor.h>
31 #include <cdogs/font.h>
32 #include <cdogs/gamedata.h>
33
34 #include "editor_ui_common.h"
35
MISSION_CHECK_TYPE_FUNC(MAPTYPE_INTERIOR)36 MISSION_CHECK_TYPE_FUNC(MAPTYPE_INTERIOR)
37 static const char *MissionGetCorridorWidthStr(UIObject *o, void *data)
38 {
39 static char s[128];
40 UNUSED(o);
41 Campaign *co = data;
42 if (!CampaignGetCurrentMission(co))
43 return NULL;
44 sprintf(
45 s, "CorridorWidth: %d",
46 CampaignGetCurrentMission(co)->u.Interior.CorridorWidth);
47 return s;
48 }
MissionGetRoomMinStr(UIObject * o,void * data)49 static const char *MissionGetRoomMinStr(UIObject *o, void *data)
50 {
51 static char s[128];
52 UNUSED(o);
53 Campaign *co = data;
54 if (!CampaignGetCurrentMission(co))
55 return NULL;
56 sprintf(
57 s, "RoomMin: %d", CampaignGetCurrentMission(co)->u.Interior.Rooms.Min);
58 return s;
59 }
MissionGetRoomMaxStr(UIObject * o,void * data)60 static const char *MissionGetRoomMaxStr(UIObject *o, void *data)
61 {
62 static char s[128];
63 UNUSED(o);
64 Campaign *co = data;
65 if (!CampaignGetCurrentMission(co))
66 return NULL;
67 sprintf(s, "RoomMax: %d", CampaignGetCurrentMission(co)->u.Interior.Rooms.Max);
68 return s;
69 }
MissionDrawExitEnabled(UIObject * o,GraphicsDevice * g,struct vec2i pos,void * data)70 static void MissionDrawExitEnabled(
71 UIObject *o, GraphicsDevice *g, struct vec2i pos, void *data)
72 {
73 UNUSED(o);
74 UNUSED(g);
75 Campaign *co = data;
76 if (!CampaignGetCurrentMission(co))
77 return;
78 DisplayFlag(
79 svec2i_add(pos, o->Pos), "Exit",
80 CampaignGetCurrentMission(co)->u.Interior.ExitEnabled,
81 UIObjectIsHighlighted(o));
82 }
MissionGetRoomWallCountStr(UIObject * o,void * data)83 static const char *MissionGetRoomWallCountStr(UIObject *o, void *data)
84 {
85 static char s[128];
86 UNUSED(o);
87 Campaign *co = data;
88 if (!CampaignGetCurrentMission(co))
89 return NULL;
90 sprintf(
91 s, "RoomWalls: %d", CampaignGetCurrentMission(co)->u.Interior.Rooms.Walls);
92 return s;
93 }
MissionGetRoomWallLenStr(UIObject * o,void * data)94 static const char *MissionGetRoomWallLenStr(UIObject *o, void *data)
95 {
96 static char s[128];
97 UNUSED(o);
98 Campaign *co = data;
99 if (!CampaignGetCurrentMission(co))
100 return NULL;
101 sprintf(
102 s, "RoomWallLen: %d",
103 CampaignGetCurrentMission(co)->u.Interior.Rooms.WallLength);
104 return s;
105 }
MissionGetRoomWallPadStr(UIObject * o,void * data)106 static const char *MissionGetRoomWallPadStr(UIObject *o, void *data)
107 {
108 static char s[128];
109 UNUSED(o);
110 Campaign *co = data;
111 if (!CampaignGetCurrentMission(co))
112 return NULL;
113 sprintf(
114 s, "RoomWallPad: %d",
115 CampaignGetCurrentMission(co)->u.Interior.Rooms.WallPad);
116 return s;
117 }
MissionDrawDoorEnabled(UIObject * o,GraphicsDevice * g,struct vec2i pos,void * data)118 static void MissionDrawDoorEnabled(
119 UIObject *o, GraphicsDevice *g, struct vec2i pos, void *data)
120 {
121 UNUSED(o);
122 UNUSED(g);
123 Campaign *co = data;
124 Mission *m = CampaignGetCurrentMission(co);
125 if (!m)
126 return;
127 DisplayFlag(
128 svec2i_add(pos, o->Pos), "Doors",
129 m->u.Interior.Doors.Enabled,
130 UIObjectIsHighlighted(o));
131 }
MissionGetDoorMinStr(UIObject * o,void * data)132 static const char *MissionGetDoorMinStr(UIObject *o, void *data)
133 {
134 static char s[128];
135 UNUSED(o);
136 Campaign *co = data;
137 if (!CampaignGetCurrentMission(co))
138 return NULL;
139 sprintf(
140 s, "DoorMin: %d", CampaignGetCurrentMission(co)->u.Interior.Doors.Min);
141 return s;
142 }
MissionGetDoorMaxStr(UIObject * o,void * data)143 static const char *MissionGetDoorMaxStr(UIObject *o, void *data)
144 {
145 static char s[128];
146 UNUSED(o);
147 Campaign *co = data;
148 if (!CampaignGetCurrentMission(co))
149 return NULL;
150 sprintf(
151 s, "DoorMax: %d", CampaignGetCurrentMission(co)->u.Interior.Doors.Max);
152 return s;
153 }
MissionDrawDoorRandomPos(UIObject * o,GraphicsDevice * g,struct vec2i pos,void * data)154 static void MissionDrawDoorRandomPos(
155 UIObject *o, GraphicsDevice *g, struct vec2i pos, void *data)
156 {
157 UNUSED(o);
158 UNUSED(g);
159 Campaign *co = data;
160 Mission *m = CampaignGetCurrentMission(co);
161 if (!m)
162 return;
163 DisplayFlag(
164 svec2i_add(pos, o->Pos), "DoorRandomPos",
165 m->u.Interior.Doors.RandomPos,
166 UIObjectIsHighlighted(o));
167 }
MissionGetPillarCountStr(UIObject * o,void * data)168 static const char *MissionGetPillarCountStr(UIObject *o, void *data)
169 {
170 static char s[128];
171 UNUSED(o);
172 Campaign *co = data;
173 if (!CampaignGetCurrentMission(co))
174 return NULL;
175 sprintf(
176 s, "Pillars: %d",
177 CampaignGetCurrentMission(co)->u.Interior.Pillars.Count);
178 return s;
179 }
180
MissionChangeCorridorWidth(void * data,int d)181 static EditorResult MissionChangeCorridorWidth(void *data, int d)
182 {
183 Campaign *co = data;
184 CampaignGetCurrentMission(co)->u.Interior.CorridorWidth = CLAMP(
185 CampaignGetCurrentMission(co)->u.Interior.CorridorWidth + d, 1, 5);
186 return EDITOR_RESULT_CHANGED;
187 }
MissionChangeRoomMin(void * data,int d)188 static EditorResult MissionChangeRoomMin(void *data, int d)
189 {
190 Campaign *co = data;
191 Mission *m = CampaignGetCurrentMission(co);
192 m->u.Interior.Rooms.Min = CLAMP(m->u.Interior.Rooms.Min + d, 5, 25);
193 m->u.Interior.Rooms.Max =
194 MAX(m->u.Interior.Rooms.Min * 2, m->u.Interior.Rooms.Max);
195 return EDITOR_RESULT_CHANGED;
196 }
MissionChangeRoomMax(void * data,int d)197 static EditorResult MissionChangeRoomMax(void *data, int d)
198 {
199 Campaign *co = data;
200 Mission *m = CampaignGetCurrentMission(co);
201 m->u.Interior.Rooms.Max = CLAMP(m->u.Interior.Rooms.Max + d, 10, 50);
202 m->u.Interior.Rooms.Min =
203 MIN(m->u.Interior.Rooms.Min, m->u.Interior.Rooms.Max / 2);
204 return EDITOR_RESULT_CHANGED;
205 }
MissionChangeExitEnabled(void * data,int d)206 static EditorResult MissionChangeExitEnabled(void *data, int d)
207 {
208 UNUSED(d);
209 Campaign *co = data;
210 Mission *m = CampaignGetCurrentMission(co);
211 m->u.Interior.ExitEnabled = !m->u.Interior.ExitEnabled;
212 return EDITOR_RESULT_CHANGED;
213 }
MissionChangeRoomWallCount(void * data,int d)214 static EditorResult MissionChangeRoomWallCount(void *data, int d)
215 {
216 Campaign *co = data;
217 Mission *m = CampaignGetCurrentMission(co);
218 m->u.Interior.Rooms.Walls = CLAMP(m->u.Interior.Rooms.Walls + d, 0, 50);
219 return EDITOR_RESULT_CHANGED;
220 }
MissionChangeRoomWallLen(void * data,int d)221 static EditorResult MissionChangeRoomWallLen(void *data, int d)
222 {
223 Campaign *co = data;
224 Mission *m = CampaignGetCurrentMission(co);
225 m->u.Interior.Rooms.WallLength = CLAMP(m->u.Interior.Rooms.WallLength + d, 1, 50);
226 return EDITOR_RESULT_CHANGED;
227 }
MissionChangeRoomWallPad(void * data,int d)228 static EditorResult MissionChangeRoomWallPad(void *data, int d)
229 {
230 Campaign *co = data;
231 Mission *m = CampaignGetCurrentMission(co);
232 m->u.Interior.Rooms.WallPad = CLAMP(m->u.Interior.Rooms.WallPad + d, 1, 10);
233 return EDITOR_RESULT_CHANGED;
234 }
MissionChangeDoorEnabled(void * data,int d)235 static EditorResult MissionChangeDoorEnabled(void *data, int d)
236 {
237 UNUSED(d);
238 Campaign *co = data;
239 Mission *m = CampaignGetCurrentMission(co);
240 m->u.Interior.Doors.Enabled = !m->u.Interior.Doors.Enabled;
241 return EDITOR_RESULT_CHANGED;
242 }
MissionChangeDoorMin(void * data,int d)243 static EditorResult MissionChangeDoorMin(void *data, int d)
244 {
245 Campaign *co = data;
246 Mission *m = CampaignGetCurrentMission(co);
247 m->u.Interior.Doors.Min = CLAMP(m->u.Interior.Doors.Min + d, 1, 6);
248 m->u.Interior.Doors.Max =
249 MAX(m->u.Interior.Doors.Min, m->u.Interior.Doors.Max);
250 return EDITOR_RESULT_CHANGED;
251 }
MissionChangeDoorMax(void * data,int d)252 static EditorResult MissionChangeDoorMax(void *data, int d)
253 {
254 Campaign *co = data;
255 Mission *m = CampaignGetCurrentMission(co);
256 m->u.Interior.Doors.Max = CLAMP(m->u.Interior.Doors.Max + d, 1, 6);
257 m->u.Interior.Doors.Min =
258 MIN(m->u.Interior.Doors.Min, m->u.Interior.Doors.Max);
259 return EDITOR_RESULT_CHANGED;
260 }
MissionChangeDoorRandomPos(void * data,int d)261 static EditorResult MissionChangeDoorRandomPos(void *data, int d)
262 {
263 UNUSED(d);
264 Campaign *co = data;
265 Mission *m = CampaignGetCurrentMission(co);
266 m->u.Interior.Doors.RandomPos = !m->u.Interior.Doors.RandomPos;
267 return EDITOR_RESULT_CHANGED;
268 }
MissionChangePillarCount(void * data,int d)269 static EditorResult MissionChangePillarCount(void *data, int d)
270 {
271 Campaign *co = data;
272 Mission *m = CampaignGetCurrentMission(co);
273 m->u.Interior.Pillars.Count = CLAMP(m->u.Interior.Pillars.Count + d, 0, 50);
274 return EDITOR_RESULT_CHANGED;
275 }
276
CreateInteriorMapObjs(struct vec2i pos,Campaign * co)277 UIObject *CreateInteriorMapObjs(struct vec2i pos, Campaign *co)
278 {
279 const int th = FontH();
280 UIObject *c = UIObjectCreate(UITYPE_NONE, 0, svec2i_zero(), svec2i_zero());
281 UIObject *o =
282 UIObjectCreate(UITYPE_LABEL, 0, svec2i_zero(), svec2i(50, th));
283 const int x = pos.x;
284 // Check whether the map type matches, and set visibility
285 c->CheckVisible = MissionCheckTypeFunc;
286 c->Data = co;
287
288 UIObject *o2 = CreateCampaignSeedObj(pos, co);
289 UIObjectAddChild(c, o2);
290
291 pos.x += o2->Size.x;
292 o2 = UIObjectCopy(o);
293 o2->u.LabelFunc = MissionGetCorridorWidthStr;
294 o2->Data = co;
295 o2->ChangeFunc = MissionChangeCorridorWidth;
296 o2->Pos = pos;
297 o2->Size.x = 60;
298 UIObjectAddChild(c, o2);
299
300 pos.x = x;
301 pos.y += th;
302 o2 = UIObjectCopy(o);
303 o2->u.LabelFunc = MissionGetRoomMinStr;
304 o2->Data = co;
305 o2->ChangeFunc = MissionChangeRoomMin;
306 o2->Pos = pos;
307 UIObjectAddChild(c, o2);
308 pos.x += o2->Size.x;
309 o2 = UIObjectCopy(o);
310 o2->u.LabelFunc = MissionGetRoomMaxStr;
311 o2->Data = co;
312 o2->ChangeFunc = MissionChangeRoomMax;
313 o2->Pos = pos;
314 UIObjectAddChild(c, o2);
315
316 pos.x = x;
317 pos.y += th;
318 o2 = UIObjectCreate(UITYPE_CUSTOM, 0, pos, o->Size);
319 o2->u.CustomDrawFunc = MissionDrawExitEnabled;
320 o2->Data = co;
321 o2->ChangeFunc = MissionChangeExitEnabled;
322 o2->Pos = pos;
323 UIObjectAddChild(c, o2);
324
325 pos.x = x;
326 pos.y += th;
327 o2 = UIObjectCopy(o);
328 o2->u.LabelFunc = MissionGetRoomWallCountStr;
329 o2->Data = co;
330 o2->ChangeFunc = MissionChangeRoomWallCount;
331 o2->Pos = pos;
332 UIObjectAddChild(c, o2);
333 pos.x += o2->Size.x;
334 o2 = UIObjectCopy(o);
335 o2->u.LabelFunc = MissionGetRoomWallLenStr;
336 o2->Data = co;
337 o2->ChangeFunc = MissionChangeRoomWallLen;
338 o2->Pos = pos;
339 o2->Size.x = 60;
340 UIObjectAddChild(c, o2);
341 pos.x += o2->Size.x;
342 o2 = UIObjectCopy(o);
343 o2->u.LabelFunc = MissionGetRoomWallPadStr;
344 o2->Data = co;
345 o2->ChangeFunc = MissionChangeRoomWallPad;
346 o2->Pos = pos;
347 o2->Size.x = 60;
348 UIObjectAddChild(c, o2);
349
350 pos.x = x;
351 pos.y += th;
352 o2 = UIObjectCreate(UITYPE_CUSTOM, 0, pos, o->Size);
353 o2->u.CustomDrawFunc = MissionDrawDoorEnabled;
354 o2->Data = co;
355 o2->ChangeFunc = MissionChangeDoorEnabled;
356 o2->Pos = pos;
357 UIObjectAddChild(c, o2);
358 pos.x += o2->Size.x;
359 o2 = UIObjectCopy(o);
360 o2->u.LabelFunc = MissionGetDoorMinStr;
361 o2->Data = co;
362 o2->ChangeFunc = MissionChangeDoorMin;
363 o2->Pos = pos;
364 UIObjectAddChild(c, o2);
365 pos.x += o2->Size.x;
366 o2 = UIObjectCopy(o);
367 o2->u.LabelFunc = MissionGetDoorMaxStr;
368 o2->Data = co;
369 o2->ChangeFunc = MissionChangeDoorMax;
370 o2->Pos = pos;
371 UIObjectAddChild(c, o2);
372 pos.x += o2->Size.x;
373 o2 = UIObjectCreate(UITYPE_CUSTOM, 0, pos, o->Size);
374 o2->u.CustomDrawFunc = MissionDrawDoorRandomPos;
375 o2->Data = co;
376 o2->ChangeFunc = MissionChangeDoorRandomPos;
377 o2->Pos = pos;
378 UIObjectAddChild(c, o2);
379
380 pos.x = x;
381 pos.y += th;
382 o2 = UIObjectCopy(o);
383 o2->u.LabelFunc = MissionGetPillarCountStr;
384 o2->Data = co;
385 o2->ChangeFunc = MissionChangePillarCount;
386 o2->Pos = pos;
387 UIObjectAddChild(c, o2);
388
389 UIObjectDestroy(o);
390 return c;
391 }
392