static void UI_MaterialEditorNewStage_f (void) { material_t* m; int id; if (Cmd_Argc() < 2) { Com_Printf("Usage: %s <image index>\n", Cmd_Argv(0)); return; } id = atoi(Cmd_Argv(1)); if (id < 0 || id >= r_numImages) { Com_Printf("Given image index (%i) is out of bounds\n", id); return; } m = &R_GetImageAtIndex(id)->material; materialStage_t* const s = Mem_PoolAllocType(materialStage_t, vid_imagePool); m->num_stages++; /* append the stage to the chain */ if (!m->stages) m->stages = s; else { materialStage_t* ss = m->stages; while (ss->next) ss = ss->next; ss->next = s; } UI_MaterialEditorUpdate(R_GetImageAtIndex(id), s); }
static void UI_MaterialEditorSelectStage_f (void) { image_t* image; int id, stageID; materialStage_t* materialStage; if (Cmd_Argc() < 3) { Com_Printf("Usage: %s <image index> <stage index>\n", Cmd_Argv(0)); return; } id = atoi(Cmd_Argv(1)); if (id < 0 || id >= r_numImages) { Com_Printf("Given image index (%i) is out of bounds\n", id); return; } image = R_GetImageAtIndex(id); stageID = atoi(Cmd_Argv(2)); if (stageID < 0 || stageID >= image->material.num_stages) { Com_Printf("Given stage index (%i) is out of bounds\n", stageID); return; } materialStage = UI_MaterialEditorGetStage(&image->material, stageID); UI_MaterialEditorUpdate(image, materialStage); }
static void UI_MaterialEditorRemoveStage_f (void) { image_t* image; int id, stageID; if (Cmd_Argc() < 3) { Com_Printf("Usage: %s <image index> <stage index>\n", Cmd_Argv(0)); return; } id = atoi(Cmd_Argv(1)); if (id < 0 || id >= r_numImages) { Com_Printf("Given image index (%i) is out of bounds\n", id); return; } image = R_GetImageAtIndex(id); stageID = atoi(Cmd_Argv(2)); if (stageID < 0 || stageID >= image->material.num_stages) { Com_Printf("Given stage index (%i) is out of bounds\n", stageID); return; } materialStage_t** const anchor = stageID == 0 ? &image->material.stages : &UI_MaterialEditorGetStage(&image->material, stageID - 1)->next; materialStage_t* const s = *anchor; *anchor = s->next; Mem_Free(s); image->material.num_stages--; UI_MaterialEditorUpdate(image, nullptr); }
/** * @brief Return index of the image (r_images[i]) else NULL */ static int UI_MaterialEditorNodeGetImageAtPosition (uiNode_t *node, int x, int y) { int i; vec2_t pos; int cnt = 0; int cntView = 0; const int imagesPerLine = (node->box.size[0] - node->padding) / (IMAGE_WIDTH + node->padding); const int imagesPerColumn = (node->box.size[1] - node->padding) / (IMAGE_WIDTH + node->padding); int columnRequested; int lineRequested; UI_NodeAbsoluteToRelativePos(node, &x, &y); /* have we click between 2 images? */ if (((x % (IMAGE_WIDTH + node->padding)) < node->padding) || ((y % (IMAGE_WIDTH + node->padding)) < node->padding)) return -1; /* get column and line of the image */ columnRequested = x / (IMAGE_WIDTH + node->padding); lineRequested = y / (IMAGE_WIDTH + node->padding); /* have we click outside? */ if (columnRequested >= imagesPerLine || lineRequested >= imagesPerColumn) return -1; UI_GetNodeAbsPos(node, pos); /* check images */ for (i = 0; i < r_numImages; i++) { #ifndef ANYIMAGES /* filter */ image_t *image = R_GetImageAtIndex(i); if (image->type != it_world) continue; if (strstr(image->name, "tex_common")) continue; #endif /* skip images before the scroll position */ if (cnt / imagesPerLine < EXTRADATA(node).scrollY.viewPos) { cnt++; continue; } if (cntView % imagesPerLine == columnRequested && cntView / imagesPerLine == lineRequested) return i; /* vertical overflow */ if (cntView / imagesPerLine > lineRequested) break; cnt++; cntView++; } return -1; }
/** * @param node The node to draw */ void uiMaterialEditorNode::draw (uiNode_t *node) { int i; vec2_t pos; int cnt = 0; int cntView = 0; const int imagesPerLine = (node->box.size[0] - node->padding) / (IMAGE_WIDTH + node->padding); if (isSizeChange(node)) updateView(node, false); /* width too small to display anything */ if (imagesPerLine <= 0) return; UI_GetNodeAbsPos(node, pos); /* display images */ for (i = 0; i < r_numImages; i++) { image_t *image = R_GetImageAtIndex(i); vec2_t imagepos; #ifndef ANYIMAGES /* filter */ if (image->type != it_world) continue; if (strstr(image->name, "tex_common")) continue; #endif /* skip images before the scroll position */ if (cnt / imagesPerLine < EXTRADATA(node).scrollY.viewPos) { cnt++; continue; } /** @todo do it incremental. Don't need all this math */ imagepos[0] = pos[0] + node->padding + (cntView % imagesPerLine) * (IMAGE_WIDTH + node->padding); imagepos[1] = pos[1] + node->padding + (cntView / imagesPerLine) * (IMAGE_WIDTH + node->padding); /* vertical overflow */ if (imagepos[1] + IMAGE_WIDTH + node->padding >= pos[1] + node->box.size[1]) break; if (i == node->num) { #define MARGIN 3 UI_DrawRect(imagepos[0] - MARGIN, imagepos[1] - MARGIN, IMAGE_WIDTH + MARGIN * 2, IMAGE_WIDTH + MARGIN * 2, node->selectedColor, 2, 0xFFFF); #undef MARGIN } UI_DrawNormImage(false, imagepos[0], imagepos[1], IMAGE_WIDTH, IMAGE_WIDTH, 0, 0, 0, 0, image); cnt++; cntView++; } }
/** * @brief return the number of images we can display */ static int UI_MaterialEditorNodeGetImageCount (uiNode_t* node) { int cnt = 0; for (int i = 0; i < r_numImages; i++) { #ifndef ANYIMAGES const image_t* image = R_GetImageAtIndex(i); /* filter */ if (image->type != it_world) continue; if (strstr(image->name, "tex_common")) continue; #endif cnt++; } return cnt; }
void uiMaterialEditorNode::onMouseDown (uiNode_t* node, int x, int y, int button) { int id; if (button != K_MOUSE1) return; id = UI_MaterialEditorNodeGetImageAtPosition(node, x, y); if (id == -1) return; /** @note here we use "num" to cache the selected image id. We can reuse it on the script with "<num>" */ /* have we selected a new image? */ if (node->num != id) { image_t* image = R_GetImageAtIndex(id); UI_MaterialEditorUpdate(image, nullptr); node->num = id; if (node->onChange) UI_ExecuteEventActions(node, node->onChange); } }
static void UI_MaterialEditorRemoveStage_f (void) { image_t *image; int id, stageID; if (Cmd_Argc() < 3) { Com_Printf("Usage: %s <image index> <stage index>\n", Cmd_Argv(0)); return; } id = atoi(Cmd_Argv(1)); if (id < 0 || id >= r_numImages) { Com_Printf("Given image index (%i) is out of bounds\n", id); return; } image = R_GetImageAtIndex(id); stageID = atoi(Cmd_Argv(2)); if (stageID < 0 || stageID >= image->material.num_stages) { Com_Printf("Given stage index (%i) is out of bounds\n", stageID); return; } if (stageID == 0) { materialStage_t *s = image->material.stages; image->material.stages = s->next; Mem_Free(s); } else { materialStage_t *sParent = UI_MaterialEditorGetStage(&image->material, stageID - 1); materialStage_t *s = sParent->next; sParent->next = s->next; Mem_Free(s); } image->material.num_stages--; UI_MaterialEditorUpdate(image, NULL); }
static void UI_MaterialEditorChangeValue_f (void) { image_t* image; int id, stageType; const char* var, *value; size_t bytes; if (Cmd_Argc() < 5) { Com_Printf("Usage: %s <image index> <stage index> <variable> <value>\n", Cmd_Argv(0)); return; } id = atoi(Cmd_Argv(1)); if (id < 0 || id >= r_numImages) { Com_Printf("Given image index (%i) is out of bounds\n", id); return; } var = Cmd_Argv(3); value = Cmd_Argv(4); image = R_GetImageAtIndex(id); stageType = UI_MaterialEditorNameToStage(var); if (stageType == -1) { const value_t* val = UI_FindPropertyByName(materialValues, var); if (!val) { Com_Printf("Could not find material variable for '%s'\n", var); return; } Com_ParseValue(&image->material, value, val->type, val->ofs, val->size, &bytes); } else { materialStage_t* stage; int stageID; const value_t* val = UI_FindPropertyByName(materialStageValues, var); if (!val) { Com_Printf("Could not find material stage variable for '%s'\n", var); return; } stageID = atoi(Cmd_Argv(2)); if (stageID < 0 || stageID >= image->material.num_stages) { Com_Printf("Given stage index (%i) is out of bounds\n", stageID); return; } stage = UI_MaterialEditorGetStage(&image->material, stageID); assert(stage); stage->flags |= stageType; Com_ParseValue(stage, value, val->type, val->ofs, val->size, &bytes); /* a texture or envmap means render it */ if (stage->flags & (STAGE_TEXTURE | STAGE_ENVMAP)) stage->flags |= STAGE_RENDER; if (stage->flags & (STAGE_TAPE | STAGE_TERRAIN | STAGE_DIRTMAP)) stage->flags |= STAGE_LIGHTING; } R_ModReloadSurfacesArrays(); }