1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | #include "../../client.h" |
27 | #include "../ui_main.h" |
28 | #include "../ui_data.h" |
29 | #include "../ui_windows.h" |
30 | #include "../ui_nodes.h" |
31 | #include "../ui_behaviour.h" |
32 | #include "../ui_actions.h" |
33 | #include "../ui_render.h" |
34 | #include "../ui_parse.h" |
35 | #include "ui_node_abstractnode.h" |
36 | #include "ui_node_abstractscrollable.h" |
37 | #include "../../cl_video.h" |
38 | #include "../../renderer/r_image.h" |
39 | #include "../../renderer/r_draw.h" |
40 | #include "../../renderer/r_model.h" |
41 | #include "ui_node_material_editor.h" |
42 | |
43 | #define EXTRADATA(node)(*((abstractScrollableExtraData_t*)((char*)node + sizeof(uiNode_t )))) UI_EXTRADATA(node, abstractScrollableExtraData_t)(*((abstractScrollableExtraData_t*)((char*)node + sizeof(uiNode_t )))) |
44 | |
45 | |
46 | |
47 | #define IMAGE_WIDTH64 64 |
48 | |
49 | typedef struct materialDescription_s { |
50 | const char *name; |
51 | const int stageFlag; |
52 | } materialDescription_t; |
53 | |
54 | static const materialDescription_t materialDescriptions[] = { |
55 | {"texture", STAGE_TEXTURE(1 << 0)}, |
56 | {"envmap", STAGE_ENVMAP(1 << 1)}, |
57 | {"blend", STAGE_BLEND(1 << 2)}, |
58 | {"color", STAGE_COLOR(1 << 3)}, |
59 | {"pulse", STAGE_PULSE(1 << 4)}, |
60 | {"stretch", STAGE_STRETCH(1 << 5)}, |
61 | {"rotate", STAGE_ROTATE(1 << 6)}, |
62 | {"scroll.s", STAGE_SCROLL_S(1 << 7)}, |
63 | {"scroll.t", STAGE_SCROLL_T(1 << 8)}, |
64 | {"scale.s", STAGE_SCALE_S(1 << 9)}, |
65 | {"scale.t", STAGE_SCALE_T(1 << 10)}, |
66 | {"terrain", STAGE_TERRAIN(1 << 11)}, |
67 | {"tape", STAGE_TAPE(1 << 12)}, |
68 | {"lightmap", STAGE_LIGHTMAP(1 << 13)}, |
69 | {"anim", STAGE_ANIM(1 << 14)}, |
70 | {"dirtmap", STAGE_DIRTMAP(1 << 15)}, |
71 | |
72 | {NULL__null, 0} |
73 | }; |
74 | |
75 | static materialStage_t *UI_MaterialEditorGetStage (material_t *material, int stageIndex) |
76 | { |
77 | materialStage_t *materialStage = material->stages; |
78 | while (stageIndex-- > 0) { |
79 | if (materialStage) |
80 | materialStage = materialStage->next; |
81 | else |
82 | break; |
83 | } |
84 | return materialStage; |
85 | } |
86 | |
87 | |
88 | |
89 | |
90 | static int UI_MaterialEditorNodeGetImageCount (uiNode_t *node) |
91 | { |
92 | int i; |
93 | int cnt = 0; |
94 | |
95 | for (i = 0; i < r_numImages; i++) { |
96 | #ifndef ANYIMAGES |
97 | const image_t *image = R_GetImageAtIndex(i); |
98 | |
99 | if (image->type != it_world) |
100 | continue; |
101 | |
102 | if (strstr(image->name, "tex_common")) |
103 | continue; |
104 | #endif |
105 | cnt++; |
106 | } |
107 | return cnt; |
108 | } |
109 | |
110 | |
111 | |
112 | |
113 | void uiMaterialEditorNode::updateView (uiNode_t *node, bool reset) |
114 | { |
115 | const int imageCount = UI_MaterialEditorNodeGetImageCount(node); |
116 | const int imagesPerLine = (node->box.size[0] - node->padding) / (IMAGE_WIDTH64 + node->padding); |
117 | const int imagesPerColumn = (node->box.size[1] - node->padding) / (IMAGE_WIDTH64 + node->padding); |
118 | |
119 | |
120 | if (imagesPerLine > 0 && imagesPerColumn > 0) { |
121 | const int pos = reset ? 0 : -1; |
122 | setScrollY(node, pos, imagesPerColumn, imageCount / imagesPerLine); |
123 | } else |
124 | setScrollY(node, 0, 0, 0); |
125 | } |
126 | |
127 | |
128 | |
129 | |
130 | void uiMaterialEditorNode::draw (uiNode_t *node) |
131 | { |
132 | int i; |
133 | vec2_t pos; |
134 | int cnt = 0; |
135 | int cntView = 0; |
136 | const int imagesPerLine = (node->box.size[0] - node->padding) / (IMAGE_WIDTH64 + node->padding); |
137 | |
138 | if (isSizeChange(node)) |
139 | updateView(node, false); |
140 | |
141 | |
142 | if (imagesPerLine <= 0) |
143 | return; |
144 | |
145 | UI_GetNodeAbsPos(node, pos); |
146 | |
147 | |
148 | for (i = 0; i < r_numImages; i++) { |
149 | image_t *image = R_GetImageAtIndex(i); |
150 | vec2_t imagepos; |
151 | |
152 | #ifndef ANYIMAGES |
153 | |
154 | if (image->type != it_world) |
155 | continue; |
156 | |
157 | if (strstr(image->name, "tex_common")) |
158 | continue; |
159 | #endif |
160 | |
161 | |
162 | if (cnt / imagesPerLine < EXTRADATA(node)(*((abstractScrollableExtraData_t*)((char*)node + sizeof(uiNode_t )))).scrollY.viewPos) { |
163 | cnt++; |
164 | continue; |
165 | } |
166 | |
167 | |
168 | imagepos[0] = pos[0] + node->padding + (cntView % imagesPerLine) * (IMAGE_WIDTH64 + node->padding); |
169 | imagepos[1] = pos[1] + node->padding + (cntView / imagesPerLine) * (IMAGE_WIDTH64 + node->padding); |
170 | |
171 | |
172 | if (imagepos[1] + IMAGE_WIDTH64 + node->padding >= pos[1] + node->box.size[1]) |
173 | break; |
174 | |
175 | if (i == node->num) { |
176 | #define MARGIN 3 |
177 | R_DrawRect(imagepos[0] - MARGIN, imagepos[1] - MARGIN, IMAGE_WIDTH64 + MARGIN * 2, IMAGE_WIDTH64 + MARGIN * 2, node->selectedColor, 2, 0xFFFF); |
178 | #undef MARGIN |
179 | } |
180 | |
181 | UI_DrawNormImage(false, imagepos[0], imagepos[1], IMAGE_WIDTH64, IMAGE_WIDTH64, 0, 0, 0, 0, image); |
182 | |
183 | cnt++; |
184 | cntView++; |
185 | } |
186 | } |
187 | |
188 | |
189 | |
190 | |
191 | static int UI_MaterialEditorNodeGetImageAtPosition (uiNode_t *node, int x, int y) |
192 | { |
193 | int i; |
194 | vec2_t pos; |
195 | int cnt = 0; |
196 | int cntView = 0; |
197 | const int imagesPerLine = (node->box.size[0] - node->padding) / (IMAGE_WIDTH64 + node->padding); |
198 | const int imagesPerColumn = (node->box.size[1] - node->padding) / (IMAGE_WIDTH64 + node->padding); |
199 | int columnRequested; |
200 | int lineRequested; |
201 | |
202 | UI_NodeAbsoluteToRelativePos(node, &x, &y); |
203 | |
204 | |
205 | if (((x % (IMAGE_WIDTH64 + node->padding)) < node->padding) |
206 | || ((y % (IMAGE_WIDTH64 + node->padding)) < node->padding)) |
207 | return -1; |
208 | |
209 | |
210 | columnRequested = x / (IMAGE_WIDTH64 + node->padding); |
211 | lineRequested = y / (IMAGE_WIDTH64 + node->padding); |
212 | |
213 | |
214 | if (columnRequested >= imagesPerLine || lineRequested >= imagesPerColumn) |
215 | return -1; |
216 | |
217 | UI_GetNodeAbsPos(node, pos); |
218 | |
219 | |
220 | for (i = 0; i < r_numImages; i++) { |
221 | #ifndef ANYIMAGES |
222 | |
223 | image_t *image = R_GetImageAtIndex(i); |
224 | if (image->type != it_world) |
225 | continue; |
226 | |
227 | if (strstr(image->name, "tex_common")) |
228 | continue; |
229 | #endif |
230 | |
231 | |
232 | if (cnt / imagesPerLine < EXTRADATA(node)(*((abstractScrollableExtraData_t*)((char*)node + sizeof(uiNode_t )))).scrollY.viewPos) { |
233 | cnt++; |
234 | continue; |
235 | } |
236 | |
237 | if (cntView % imagesPerLine == columnRequested && cntView / imagesPerLine == lineRequested) |
238 | return i; |
239 | |
240 | |
241 | if (cntView / imagesPerLine > lineRequested) |
242 | break; |
243 | |
244 | cnt++; |
245 | cntView++; |
246 | } |
247 | |
248 | return -1; |
249 | } |
250 | |
251 | static void UI_MaterialEditorStagesToName (const materialStage_t *stage, char *buf, size_t size) |
252 | { |
253 | const materialDescription_t *md = materialDescriptions; |
254 | |
255 | while (md->name) { |
256 | if (stage->flags & md->stageFlag) |
257 | Q_strcat(buf, va("%s ", md->name), size); |
258 | md++; |
259 | } |
260 | } |
261 | |
262 | |
263 | |
264 | |
265 | |
266 | |
267 | static void UI_MaterialEditorUpdate (image_t *image, materialStage_t *materialStage) |
268 | { |
269 | linkedList_t *materialStagesList = NULL__null; |
270 | |
271 | if (image->normalmap == NULL__null) |
| |
272 | UI_ExecuteConfunc("hideshaders true 0 0 0 0"); |
273 | else |
274 | UI_ExecuteConfunc("hideshaders false %f %f %f %f", image->material.bump, |
275 | image->material.hardness, image->material.parallax, image->material.specular); |
276 | |
277 | if (image->normalmap == NULL__null) |
| |
278 | Cvar_Set("me_imagename", image->name); |
279 | else |
280 | Cvar_Set("me_imagename", va("%s (nm)", image->name)); |
281 | |
282 | if (!image->material.num_stages) { |
| |
283 | UI_ExecuteConfunc("hidestages true"); |
284 | } else { |
285 | int i; |
286 | if (materialStage) { |
| |
287 | const char *stageType = Cvar_GetString("me_stagetype"); |
288 | if (stageType[0] == '\0') |
289 | stageType = "stretch"; |
290 | UI_ExecuteConfunc("hidestages false %s", stageType); |
291 | } else |
292 | Cvar_Set("me_stage_id", "-1"); |
293 | for (i = 0; i < image->material.num_stages; i++) { |
| 9 | Loop condition is true. Entering loop body |
|
294 | const materialStage_t *stage = UI_MaterialEditorGetStage(&image->material, i); |
295 | char stageName[MAX_VAR64] = "stage "; |
296 | if (stage == materialStage) { |
| |
297 | UI_ExecuteConfunc("updatestagevalues %f %f %f %f %f %f %f %f %f %f %f %f %f %f", |
298 | stage->rotate.hz, stage->rotate.deg, |
299 | stage->stretch.hz, stage->stretch.dhz, stage->stretch.amp, stage->stretch.damp, |
300 | stage->pulse.hz, stage->pulse.dhz, |
301 | stage->scroll.ds, stage->scroll.dt, stage->scroll.s, stage->scroll.t, |
302 | stage->scale.s, stage->scale.t); |
| 11 | Dereference of null pointer |
|
303 | } |
304 | UI_MaterialEditorStagesToName(stage, stageName, sizeof(stageName) - 1); |
305 | LIST_AddString(&materialStagesList, stageName); |
306 | } |
307 | } |
308 | UI_RegisterLinkedListText(TEXT_MATERIAL_STAGES, materialStagesList); |
309 | } |
310 | |
311 | |
312 | |
313 | |
314 | |
315 | |
316 | static int UI_MaterialEditorNameToStage (const char *stageName) |
317 | { |
318 | const materialDescription_t *md = materialDescriptions; |
319 | |
320 | while (md->name) { |
321 | if (!strncmp(md->name, stageName, strlen(md->name))) |
322 | return md->stageFlag; |
323 | md++; |
324 | } |
325 | return -1; |
326 | } |
327 | |
328 | void uiMaterialEditorNode::onMouseDown (uiNode_t *node, int x, int y, int button) |
329 | { |
330 | int id; |
331 | if (button != K_MOUSE1) |
| |
332 | return; |
333 | |
334 | id = UI_MaterialEditorNodeGetImageAtPosition(node, x, y); |
335 | if (id == -1) |
| |
336 | return; |
337 | |
338 | |
339 | |
340 | if (node->num != id) { |
| |
341 | image_t *image = R_GetImageAtIndex(id); |
342 | UI_MaterialEditorUpdate(image, NULL__null); |
| 4 | Calling 'UI_MaterialEditorUpdate' |
|
343 | |
344 | node->num = id; |
345 | |
346 | if (node->onChange) |
347 | UI_ExecuteEventActions(node, node->onChange); |
348 | } |
349 | } |
350 | |
351 | |
352 | |
353 | |
354 | void uiMaterialEditorNode::onWindowOpened (uiNode_t *node, linkedList_t *params) |
355 | { |
356 | node->num = -1; |
357 | updateView(node, true); |
358 | } |
359 | |
360 | |
361 | |
362 | |
363 | bool uiMaterialEditorNode::onScroll (uiNode_t *node, int deltaX, int deltaY) |
364 | { |
365 | bool down = deltaY > 0; |
366 | const int diff = (down) ? 1 : -1; |
367 | if (deltaY == 0) |
368 | return false; |
369 | return scrollY(node, diff); |
370 | } |
371 | |
372 | static void UI_MaterialEditorStart_f (void) |
373 | { |
374 | |
375 | #ifndef ANYIMAGES |
376 | if (cls.state != ca_active) { |
377 | Com_Printf("Material editor is only usable in battlescape mode\n"); |
378 | UI_PopWindow(false); |
379 | return; |
380 | } |
381 | #endif |
382 | } |
383 | |
384 | static const value_t materialValues[] = { |
385 | {"bump", V_FLOAT, offsetof(material_t, bump)__builtin_offsetof(material_t, bump), 0}, |
386 | {"parallax", V_FLOAT, offsetof(material_t, parallax)__builtin_offsetof(material_t, parallax), 0}, |
387 | {"specular", V_FLOAT, offsetof(material_t, specular)__builtin_offsetof(material_t, specular), 0}, |
388 | {"hardness", V_FLOAT, offsetof(material_t, hardness)__builtin_offsetof(material_t, hardness), 0}, |
389 | |
390 | {NULL__null, V_NULL, 0, 0}, |
391 | }; |
392 | |
393 | |
394 | static const value_t materialStageValues[] = { |
395 | {"rotate.hz", V_FLOAT, offsetof(materialStage_t, rotate.deg)__builtin_offsetof(materialStage_t, rotate.deg), 0}, |
396 | {"rotate.deg", V_FLOAT, offsetof(materialStage_t, rotate.hz)__builtin_offsetof(materialStage_t, rotate.hz), 0}, |
397 | {"stretch.hz", V_FLOAT, offsetof(materialStage_t, stretch.hz)__builtin_offsetof(materialStage_t, stretch.hz), 0}, |
398 | {"stretch.dhz", V_FLOAT, offsetof(materialStage_t, stretch.dhz)__builtin_offsetof(materialStage_t, stretch.dhz), 0}, |
399 | {"stretch.amp", V_FLOAT, offsetof(materialStage_t, stretch.amp)__builtin_offsetof(materialStage_t, stretch.amp), 0}, |
400 | {"stretch.damp", V_FLOAT, offsetof(materialStage_t, stretch.damp)__builtin_offsetof(materialStage_t, stretch.damp), 0}, |
401 | {"pulse.hz", V_FLOAT, offsetof(materialStage_t, pulse.hz)__builtin_offsetof(materialStage_t, pulse.hz), 0}, |
402 | {"pulse.dhz", V_FLOAT, offsetof(materialStage_t, pulse.dhz)__builtin_offsetof(materialStage_t, pulse.dhz), 0}, |
403 | {"scroll.s", V_FLOAT, offsetof(materialStage_t, scroll.s)__builtin_offsetof(materialStage_t, scroll.s), 0}, |
404 | {"scroll.t", V_FLOAT, offsetof(materialStage_t, scroll.t)__builtin_offsetof(materialStage_t, scroll.t), 0}, |
405 | {"scroll.ds", V_FLOAT, offsetof(materialStage_t, scroll.ds)__builtin_offsetof(materialStage_t, scroll.ds), 0}, |
406 | {"scroll.dt", V_FLOAT, offsetof(materialStage_t, scroll.dt)__builtin_offsetof(materialStage_t, scroll.dt), 0}, |
407 | {"scale.s", V_FLOAT, offsetof(materialStage_t, scale.s)__builtin_offsetof(materialStage_t, scale.s), 0}, |
408 | {"scale.t", V_FLOAT, offsetof(materialStage_t, scale.t)__builtin_offsetof(materialStage_t, scale.t), 0}, |
409 | {"terrain.floor", V_FLOAT, offsetof(materialStage_t, terrain.floor)__builtin_offsetof(materialStage_t, terrain.floor), 0}, |
410 | {"terrain.ceil", V_FLOAT, offsetof(materialStage_t, terrain.ceil)__builtin_offsetof(materialStage_t, terrain.ceil), 0}, |
411 | {"tape.floor", V_FLOAT, offsetof(materialStage_t, tape.floor)__builtin_offsetof(materialStage_t, tape.floor), 0}, |
412 | {"tape.ceil", V_FLOAT, offsetof(materialStage_t, tape.ceil)__builtin_offsetof(materialStage_t, tape.ceil), 0}, |
413 | {"tape.center", V_FLOAT, offsetof(materialStage_t, tape.center)__builtin_offsetof(materialStage_t, tape.center), 0}, |
414 | {"anim.frames", V_INT, offsetof(materialStage_t, anim.num_frames)__builtin_offsetof(materialStage_t, anim.num_frames), 0}, |
415 | {"anim.dframe", V_INT, offsetof(materialStage_t, anim.dframe)__builtin_offsetof(materialStage_t, anim.dframe), 0}, |
416 | {"anim.dtime", V_FLOAT, offsetof(materialStage_t, anim.dtime)__builtin_offsetof(materialStage_t, anim.dtime), 0}, |
417 | {"anim.fps", V_FLOAT, offsetof(materialStage_t, anim.fps)__builtin_offsetof(materialStage_t, anim.fps), 0}, |
418 | {"dirt.intensity", V_FLOAT, offsetof(materialStage_t, dirt.intensity)__builtin_offsetof(materialStage_t, dirt.intensity), 0}, |
419 | {"blend.src", V_INT, offsetof(materialStage_t, blend.src)__builtin_offsetof(materialStage_t, blend.src), 0}, |
420 | {"blend.dest", V_INT, offsetof(materialStage_t, blend.dest)__builtin_offsetof(materialStage_t, blend.dest), 0}, |
421 | |
422 | {NULL__null, V_NULL, 0, 0}, |
423 | }; |
424 | |
425 | static void UI_MaterialEditorChangeValue_f (void) |
426 | { |
427 | image_t *image; |
428 | int id, stageType; |
429 | const char *var, *value; |
430 | size_t bytes; |
431 | |
432 | if (Cmd_Argc() < 5) { |
433 | Com_Printf("Usage: %s <image index> <stage index> <variable> <value>\n", Cmd_Argv(0)); |
434 | return; |
435 | } |
436 | |
437 | id = atoi(Cmd_Argv(1)); |
438 | if (id < 0 || id >= r_numImages) { |
439 | Com_Printf("Given image index (%i) is out of bounds\n", id); |
440 | return; |
441 | } |
442 | |
443 | var = Cmd_Argv(3); |
444 | value = Cmd_Argv(4); |
445 | |
446 | image = R_GetImageAtIndex(id); |
447 | |
448 | stageType = UI_MaterialEditorNameToStage(var); |
449 | if (stageType == -1) { |
450 | const value_t *val = UI_FindPropertyByName(materialValues, var); |
451 | if (!val) { |
452 | Com_Printf("Could not find material variable for '%s'\n", var); |
453 | return; |
454 | } |
455 | Com_ParseValue(&image->material, value, val->type, val->ofs, val->size, &bytes); |
456 | } else { |
457 | materialStage_t *stage; |
458 | int stageID; |
459 | const value_t *val = UI_FindPropertyByName(materialStageValues, var); |
460 | |
461 | if (!val) { |
462 | Com_Printf("Could not find material stage variable for '%s'\n", var); |
463 | return; |
464 | } |
465 | |
466 | stageID = atoi(Cmd_Argv(2)); |
467 | if (stageID < 0 || stageID >= image->material.num_stages) { |
468 | Com_Printf("Given stage index (%i) is out of bounds\n", stageID); |
469 | return; |
470 | } |
471 | |
472 | stage = UI_MaterialEditorGetStage(&image->material, stageID); |
473 | assert(stage)(__builtin_expect(!(stage), 0) ? __assert_rtn(__func__, "src/client/ui/node/ui_node_material_editor.cpp" , 473, "stage") : (void)0); |
474 | |
475 | stage->flags |= stageType; |
476 | |
477 | Com_ParseValue(stage, value, val->type, val->ofs, val->size, &bytes); |
478 | |
479 | |
480 | if (stage->flags & (STAGE_TEXTURE(1 << 0) | STAGE_ENVMAP(1 << 1))) |
481 | stage->flags |= STAGE_RENDER(1 << 31); |
482 | |
483 | if (stage->flags & (STAGE_TAPE(1 << 12) | STAGE_TERRAIN(1 << 11) | STAGE_DIRTMAP(1 << 15))) |
484 | stage->flags |= STAGE_LIGHTING(1 << 30); |
485 | } |
486 | |
487 | R_ModReloadSurfacesArrays(); |
488 | } |
489 | |
490 | static void UI_MaterialEditorSelectStage_f (void) |
491 | { |
492 | image_t *image; |
493 | int id, stageID; |
494 | materialStage_t *materialStage; |
495 | |
496 | if (Cmd_Argc() < 3) { |
497 | Com_Printf("Usage: %s <image index> <stage index>\n", Cmd_Argv(0)); |
498 | return; |
499 | } |
500 | |
501 | id = atoi(Cmd_Argv(1)); |
502 | if (id < 0 || id >= r_numImages) { |
503 | Com_Printf("Given image index (%i) is out of bounds\n", id); |
504 | return; |
505 | } |
506 | |
507 | image = R_GetImageAtIndex(id); |
508 | |
509 | stageID = atoi(Cmd_Argv(2)); |
510 | if (stageID < 0 || stageID >= image->material.num_stages) { |
511 | Com_Printf("Given stage index (%i) is out of bounds\n", stageID); |
512 | return; |
513 | } |
514 | |
515 | materialStage = UI_MaterialEditorGetStage(&image->material, stageID); |
516 | UI_MaterialEditorUpdate(image, materialStage); |
517 | } |
518 | |
519 | static void UI_MaterialEditorRemoveStage_f (void) |
520 | { |
521 | image_t *image; |
522 | int id, stageID; |
523 | |
524 | if (Cmd_Argc() < 3) { |
525 | Com_Printf("Usage: %s <image index> <stage index>\n", Cmd_Argv(0)); |
526 | return; |
527 | } |
528 | |
529 | id = atoi(Cmd_Argv(1)); |
530 | if (id < 0 || id >= r_numImages) { |
531 | Com_Printf("Given image index (%i) is out of bounds\n", id); |
532 | return; |
533 | } |
534 | |
535 | image = R_GetImageAtIndex(id); |
536 | |
537 | stageID = atoi(Cmd_Argv(2)); |
538 | if (stageID < 0 || stageID >= image->material.num_stages) { |
539 | Com_Printf("Given stage index (%i) is out of bounds\n", stageID); |
540 | return; |
541 | } |
542 | |
543 | materialStage_t** const anchor = stageID == 0 ? &image->material.stages : &UI_MaterialEditorGetStage(&image->material, stageID - 1)->next; |
544 | materialStage_t* const s = *anchor; |
545 | *anchor = s->next; |
546 | Mem_Free(s)_Mem_Free((s),"src/client/ui/node/ui_node_material_editor.cpp" ,546); |
547 | |
548 | image->material.num_stages--; |
549 | |
550 | UI_MaterialEditorUpdate(image, NULL__null); |
551 | } |
552 | |
553 | static void UI_MaterialEditorNewStage_f (void) |
554 | { |
555 | material_t *m; |
556 | int id; |
557 | |
558 | if (Cmd_Argc() < 2) { |
559 | Com_Printf("Usage: %s <image index>\n", Cmd_Argv(0)); |
560 | return; |
561 | } |
562 | |
563 | id = atoi(Cmd_Argv(1)); |
564 | if (id < 0 || id >= r_numImages) { |
565 | Com_Printf("Given image index (%i) is out of bounds\n", id); |
566 | return; |
567 | } |
568 | |
569 | m = &R_GetImageAtIndex(id)->material; |
570 | materialStage_t* const s = Mem_PoolAllocType(materialStage_t, vid_imagePool)static_cast<materialStage_t*>(static_cast<materialStage_t *>(_Mem_Alloc((sizeof(materialStage_t) * (1)),true,(((vid_imagePool ))),(0),"src/client/ui/node/ui_node_material_editor.cpp",570) )); |
571 | m->num_stages++; |
572 | |
573 | |
574 | if (!m->stages) |
575 | m->stages = s; |
576 | else { |
577 | materialStage_t *ss = m->stages; |
578 | while (ss->next) |
579 | ss = ss->next; |
580 | ss->next = s; |
581 | } |
582 | |
583 | UI_MaterialEditorUpdate(R_GetImageAtIndex(id), s); |
584 | } |
585 | |
586 | void UI_RegisterMaterialEditorNode (uiBehaviour_t *behaviour) |
587 | { |
588 | behaviour->name = "material_editor"; |
589 | behaviour->extends = "abstractscrollable"; |
590 | behaviour->manager = new uiMaterialEditorNode(); |
591 | |
592 | |
593 | Cmd_AddCommand("ui_materialeditor_removestage", UI_MaterialEditorRemoveStage_f, "Removes the selected material stage"); |
594 | Cmd_AddCommand("ui_materialeditor_newstage", UI_MaterialEditorNewStage_f, "Creates a new material stage for the current selected material"); |
595 | Cmd_AddCommand("ui_materialeditor_selectstage", UI_MaterialEditorSelectStage_f, "Select a given material stage"); |
596 | Cmd_AddCommand("ui_materialeditor_changevalue", UI_MaterialEditorChangeValue_f, "Initializes the material editor window"); |
597 | Cmd_AddCommand("ui_materialeditor", UI_MaterialEditorStart_f, "Initializes the material editor window"); |
598 | } |