void uiSequenceNode::onWindowOpened (uiNode_t* node, linkedList_t* params) { if (EXTRADATA(node).context == nullptr) EXTRADATA(node).context = SEQ_AllocContext(); if (EXTRADATA(node).source != nullptr) { SEQ_InitContext(EXTRADATA(node).context, EXTRADATA(node).source); EXTRADATA(node).playing = true; } }
void uiBaseInventoryNode::onMouseDown (uiNode_t* node, int x, int y, int button) { switch (button) { case K_MOUSE1: { /* start drag and drop */ int fromX, fromY; dragInfoIC = UI_BaseInventoryNodeGetItem(node, x, y, &fromX, &fromY); if (dragInfoIC) { dragInfoFromX = fromX; dragInfoFromY = fromY; oldMouseX = x; oldMouseY = y; UI_SetMouseCapture(node); EXTRADATA(node).super.lastSelectedId = dragInfoIC->def()->idx; if (EXTRADATA(node).super.onSelect) { UI_ExecuteEventActions(node, EXTRADATA(node).super.onSelect); } if (EXTRADATA(node).super.lua_onSelect != LUA_NOREF) { UI_ExecuteLuaEventScript(node, EXTRADATA(node).super.lua_onSelect); } } break; } case K_MOUSE2: if (UI_DNDIsDragging()) { UI_DNDAbort(); } else { /* auto place */ UI_ContainerNodeAutoPlace(node, x, y); } break; default: break; } }
/** * Update the client zone */ static void UI_ClientLayout (uiNode_t *node) { int width = 0; int height = 0; uiNode_t *child; qboolean updated; for (child = node->firstChild; child; child = child->next) { int value; value = child->pos[0] + child->size[0]; if (value > width) width = value; value = child->pos[1] + child->size[1]; if (value > height) height = value; } width += node->padding; height += node->padding; updated = UI_SetScroll(&EXTRADATA(node).super.scrollX, -1, node->size[0], width); updated = UI_SetScroll(&EXTRADATA(node).super.scrollY, -1, node->size[1], height) || updated; if (updated && EXTRADATA(node).super.onViewChange) UI_ExecuteEventActions(node, EXTRADATA(node).super.onViewChange); }
/** * @brief Draw a small square with the layout of the given base */ static void UI_BaseLayoutNodeDraw (uiNode_t * node) { base_t *base; int height, width, y; int row, col; const vec4_t c_gray = {0.5, 0.5, 0.5, 1.0}; vec2_t nodepos; int totalMarge; if (EXTRADATA(node).baseid >= MAX_BASES || EXTRADATA(node).baseid < 0) return; totalMarge = node->padding * (BASE_SIZE + 1); width = (node->size[0] - totalMarge) / BASE_SIZE; height = (node->size[1] - totalMarge) / BASE_SIZE; UI_GetNodeAbsPos(node, nodepos); base = B_GetBaseByIDX(EXTRADATA(node).baseid); y = nodepos[1] + node->padding; for (row = 0; row < BASE_SIZE; row++) { int x = nodepos[0] + node->padding; for (col = 0; col < BASE_SIZE; col++) { if (B_IsTileBlocked(base, col, row)) { UI_DrawFill(x, y, width, height, c_gray); } else if (B_GetBuildingAt(base, col, row) != NULL) { /* maybe destroyed in the meantime */ if (base->founded) UI_DrawFill(x, y, width, height, node->color); } x += width + node->padding; } y += height + node->padding; } }
/** * @brief Handles selectboxes clicks */ void uiSelectBoxNode::onLeftClick (uiNode_t* node, int x, int y) { /* dropdown the node */ if (UI_GetMouseCapture() == nullptr) { UI_SetMouseCapture(node); return; } vec2_t pos; UI_GetNodeAbsPos(node, pos); int clickedAtOption = (y - pos[1]); /* we click outside */ if (x < pos[0] || y < pos[1] || x >= pos[0] + node->box.size[0] || y >= pos[1] + node->box.size[1] * (EXTRADATA(node).count + 1)) { UI_MouseRelease(); return; } /* we click on the head */ if (clickedAtOption < node->box.size[1]) { UI_MouseRelease(); return; } clickedAtOption = (clickedAtOption - node->box.size[1]) / node->box.size[1]; if (clickedAtOption < 0 || clickedAtOption >= EXTRADATA(node).count) return; if (UI_AbstractOptionGetCurrentValue(node) == nullptr) return; /* select the right option */ uiNode_t* option = UI_AbstractOptionGetFirstOption(node); for (; option; option = option->next) { if (option->invis) continue; if (clickedAtOption == 0) break; clickedAtOption--; } /* update the status */ if (option) UI_AbstractOptionSetCurrentValue(node, OPTIONEXTRADATA(option).value); /* close the dropdown */ UI_MouseRelease(); }
static qboolean UI_RadioButtonNodeIsSelected (uiNode_t *node) { if (EXTRADATA(node).string == NULL) { const float current = UI_GetReferenceFloat(node, EXTRADATA(node).cvar); return current > EXTRADATA(node).value - EPSILON && current < EXTRADATA(node).value + EPSILON; } else { const char *current = UI_GetReferenceString(node, EXTRADATA(node).cvar); return Q_streq(current, EXTRADATA(node).string); } }
/** * @brief Draws a base. */ void uiBaseMapNode::draw (uiNode_t * node) { int col, row; bool hover = node->state; getCellAtPos(node, mousePosX, mousePosY, &col, &row); if (col == -1) hover = false; const int width = node->box.size[0] / BASE_SIZE; const int height = node->box.size[1] / BASE_SIZE + BASE_IMAGE_OVERLAY; vec2_t nodePos; UI_GetNodeAbsPos(node, nodePos); GAME_DrawBase(EXTRADATA(node).baseid, nodePos[0], nodePos[1], width, height, col, row, hover, BASE_IMAGE_OVERLAY); }
/** * @brief Called when the node lost the focus */ void uiTextEntryNode::onFocusLost (uiNode_t* node) { /* already aborted/changed with the keyboard */ if (editedCvar == nullptr) return; /* release the keyboard */ if (isAborted || EXTRADATA(node).clickOutAbort) { UI_TextEntryNodeAbortEdition(node); } else { UI_TextEntryNodeValidateEdition(node); } #if SDL_VERSION_ATLEAST(2,0,0) SDL_StopTextInput(); #endif }
void uiTextNode::onLoaded (uiNode_t* node) { int lineheight = EXTRADATA(node).lineHeight; /* auto compute lineheight */ /* we don't overwrite EXTRADATA(node).lineHeight, because "0" is dynamically replaced by font height on draw function */ if (lineheight == 0) { /* the font is used */ const char* font = UI_GetFontFromNode(node); lineheight = UI_FontGetHeight(font); } /* auto compute rows (super.viewSizeY) */ if (EXTRADATA(node).super.scrollY.viewSize == 0) { if (node->box.size[1] != 0 && lineheight != 0) { EXTRADATA(node).super.scrollY.viewSize = node->box.size[1] / lineheight; } else { EXTRADATA(node).super.scrollY.viewSize = 1; Com_Printf("UI_TextNodeLoaded: node '%s' has no rows value\n", UI_GetPath(node)); } } /* auto compute height */ if (node->box.size[1] == 0) { node->box.size[1] = EXTRADATA(node).super.scrollY.viewSize * lineheight; } /* is text slot exists */ if (EXTRADATA(node).dataID >= UI_MAX_DATAID) Com_Error(ERR_DROP, "Error in node %s - max shared data id num exceeded (num: %i, max: %i)", UI_GetPath(node), EXTRADATA(node).dataID, UI_MAX_DATAID); #ifdef DEBUG if (EXTRADATA(node).super.scrollY.viewSize != (int)(node->box.size[1] / lineheight)) { Com_Printf("UI_TextNodeLoaded: rows value (%i) of node '%s' differs from size (%.0f) and format (%i) values\n", EXTRADATA(node).super.scrollY.viewSize, UI_GetPath(node), node->box.size[1], lineheight); } #endif if (node->text == nullptr && EXTRADATA(node).dataID == TEXT_NULL) Com_Printf("UI_TextNodeLoaded: 'textid' property of node '%s' is not set\n", UI_GetPath(node)); }
/** * @brief Called when the node is captured by the mouse */ void uiVScrollbarNode::onCapturedMouseMove (uiNode_t* node, int x, int y) { if (capturedElement != 2) return; const int posSize = EXTRADATA(node).fullsize; const int graphicSize = node->box.size[1] - (4 * ELEMENT_HEIGHT); /* compute mouse mouse */ y -= oldMouseY; /* compute pos projection */ const int pos = oldPos + (((float)y * (float)posSize) / (float)graphicSize); UI_VScrollbarNodeSet(node, pos); }
/** * @brief Draw the inventory of the base */ static void UI_BaseInventoryNodeDraw2 (uiNode_t* node, const objDef_t* highlightType) { bool updateScroll = false; int visibleHeight = 0; int needHeight = 0; vec2_t screenPos; UI_GetNodeScreenPos(node, screenPos); UI_PushClipRect(screenPos[0], screenPos[1], node->box.size[0], node->box.size[1]); needHeight = UI_BaseInventoryNodeDrawItems(node, highlightType); UI_PopClipRect(); visibleHeight = node->box.size[1]; #if 0 R_FontDrawString("f_verysmall", ALIGN_UL, node->box.pos[0], node->box.pos[1], node->box.pos[0], node->box.pos[1], 0, 0, /* maxWidth/maxHeight */ 0, va("%i %i/%i", EXTRADATA(node).scrollCur, visibleRows, totalRows), 0, 0, nullptr, false, 0); #endif /* Update display of scroll buttons if something changed. */ if (visibleHeight != EXTRADATA(node).scrollY.viewSize || needHeight != EXTRADATA(node).scrollY.fullSize) { EXTRADATA(node).scrollY.fullSize = needHeight; EXTRADATA(node).scrollY.viewSize = visibleHeight; updateScroll = true; } if (EXTRADATA(node).scrollY.viewPos > needHeight - visibleHeight) { EXTRADATA(node).scrollY.viewPos = needHeight - visibleHeight; updateScroll = true; } if (EXTRADATA(node).scrollY.viewPos < 0) { EXTRADATA(node).scrollY.viewPos = 0; updateScroll = true; } if (updateScroll) UI_BaseInventoryNodeUpdateScroll(node); }
/** * @brief Draw a grip container */ static void UI_ContainerNodeDrawGrid (uiNode_t *node, const objDef_t *highlightType) { const invList_t *ic; vec3_t pos; UI_GetNodeAbsPos(node, pos); pos[2] = 0; for (ic = ui_inventory->c[EXTRADATA(node).container->id]; ic; ic = ic->next) { assert(ic->item.item); if (highlightType && INVSH_LoadableInWeapon(highlightType, ic->item.item)) UI_DrawItem(node, pos, &ic->item, ic->x, ic->y, scale, colorLoadable); else UI_DrawItem(node, pos, &ic->item, ic->x, ic->y, scale, colorDefault); } }
/** * @brief Called before loading. Used to set default attribute values */ void uiGeoscapeNode::onLoading (uiNode_t* node) { Vector4Set(node->color, 1, 1, 1, 1); OBJZERO(EXTRADATA(node)); EXTRADATA(node).angles[YAW] = GLOBE_ROTATE; EXTRADATA(node).center[0] = EXTRADATA(node).center[1] = 0.5; EXTRADATA(node).zoom = 1.0; Vector2Set(EXTRADATA(node).smoothFinal2DGeoscapeCenter, 0.5, 0.5); VectorSet(EXTRADATA(node).smoothFinalGlobeAngle, 0, GLOBE_ROTATE, 0); /* @todo: allocate this on a per node basis - and remove the global variable geoscapeData */ EXTRADATA(node).geoscapeData = &geoscapeData; /* EXTRADATA(node).geoscapeData = Mem_AllocType(geoscapeData_t); */ /** this is the data that is used with r_dayandnightTexture */ EXTRADATA(node).r_dayandnightAlpha = Mem_AllocTypeN(byte, DAN_WIDTH * DAN_HEIGHT); r_dayandnightTexture = R_LoadImageData("***r_dayandnighttexture***", nullptr, DAN_WIDTH, DAN_HEIGHT, it_effect); r_radarTexture = R_LoadImageData("***r_radarTexture***", nullptr, RADAR_WIDTH, RADAR_HEIGHT, it_effect); r_xviTexture = R_LoadImageData("***r_xvitexture***", nullptr, XVI_WIDTH, XVI_HEIGHT, it_effect); }
/** * @brief call when the mouse move is the node is captured * @todo we can remove the loop if we save the current element in the node */ void uiSelectBoxNode::onCapturedMouseMove (uiNode_t* node, int x, int y) { UI_NodeAbsoluteToRelativePos(node, &x, &y); /* test bounded box */ if (x < 0 || y < 0 || x > node->box.size[0] || y > node->box.size[1] * (EXTRADATA(node).count + 1)) { return; } int posy = node->box.size[1]; for (uiNode_t* option = UI_AbstractOptionGetFirstOption(node); option; option = option->next) { if (option->invis) continue; OPTIONEXTRADATA(option).hovered = (posy <= y && y < posy + node->box.size[1]); posy += node->box.size[1]; } }
void uiModelNode::onCapturedMouseMove (uiNode_t* node, int x, int y) { float* rotateAngles = EXTRADATA(node).angles; /* rotate a model */ rotateAngles[YAW] -= ROTATE_SPEED * (x - oldMousePosX); rotateAngles[ROLL] += ROTATE_SPEED * (y - oldMousePosY); /* clamp the angles */ rotateAngles[YAW] -= floor(rotateAngles[YAW] / 360.0) * 360.0; if (rotateAngles[ROLL] < 0.0) rotateAngles[ROLL] = 0.0; else if (rotateAngles[ROLL] > 180.0) rotateAngles[ROLL] = 180.0; oldMousePosX = x; oldMousePosY = y; }
/** * @brief Main function to draw a container node */ void uiBaseInventoryNode::draw (uiNode_t* node) { const objDef_t* highlightType = nullptr; if (!EXTRADATA(node).super.container) return; if (!ui_inventory) return; /* is container invisible */ if (node->color[3] < 0.001) return; /* Highlight weapons that the dragged ammo (if it is one) can be loaded into. */ if (UI_DNDIsDragging() && UI_DNDGetType() == DND_ITEM) { highlightType = UI_DNDGetItem()->def(); } UI_BaseInventoryNodeDraw2(node, highlightType); }
void uiSpinnerNode::draw (uiNode_t *node) { vec2_t pos; const float delta = getDelta(node); const bool disabled = node->disabled || node->parent->disabled; UI_GetNodeAbsPos(node, pos); uiSpriteStatus_t status; uiSpriteStatus_t topStatus; uiSpriteStatus_t bottomStatus; if (disabled || delta == 0) { status = SPRITE_STATUS_DISABLED; topStatus = SPRITE_STATUS_DISABLED; bottomStatus = SPRITE_STATUS_DISABLED; } else { const float value = getValue(node); const float min = getMin(node); const float max = getMax(node); status = SPRITE_STATUS_NORMAL; bool increaseLocation = isPositionIncrease(node, mousePosX - pos[0], mousePosY - pos[1]); /* top button status */ if (value >= max) { topStatus = SPRITE_STATUS_DISABLED; } else if (node->state && increaseLocation) { topStatus = SPRITE_STATUS_HOVER; } else { topStatus = SPRITE_STATUS_NORMAL; } /* bottom button status */ if (value <= min) { bottomStatus = SPRITE_STATUS_DISABLED; } else if (node->state && !increaseLocation) { bottomStatus = SPRITE_STATUS_HOVER; } else { bottomStatus = SPRITE_STATUS_NORMAL; } } if (EXTRADATA(node).background) UI_DrawSpriteInBox(false, EXTRADATA(node).background, status, pos[0], pos[1], node->box.size[0], node->box.size[1]); if (EXTRADATA(node).topIcon) UI_DrawSpriteInBox(false, EXTRADATA(node).topIcon, topStatus, pos[0], pos[1], node->box.size[0], node->box.size[1]); if (EXTRADATA(node).bottomIcon) UI_DrawSpriteInBox(false, EXTRADATA(node).bottomIcon, bottomStatus, pos[0], pos[1], node->box.size[0], node->box.size[1]); }
/** * @brief Called when we press a key when the node got the focus * @return True, if we use the event */ bool uiTextEntryNode::onKeyPressed (uiNode_t* node, unsigned int key, unsigned short unicode) { switch (key) { /* remove the last char. */ case K_BACKSPACE: UI_TextEntryNodeEdit(node, K_BACKSPACE); return true; /* cancel the edition */ case K_ESCAPE: isAborted = true; UI_RemoveFocus(); return true; /* validate the edition */ case K_ENTER: case K_KP_ENTER: UI_TextEntryNodeValidateEdition(node); UI_RemoveFocus(); return true; case K_LEFTARROW: case K_KP_LEFTARROW: if (EXTRADATA(node).cursorPosition > 0) EXTRADATA(node).cursorPosition--; return true; case K_RIGHTARROW: case K_KP_RIGHTARROW: if (EXTRADATA(node).cursorPosition < UTF8_strlen(editedCvar->string)) EXTRADATA(node).cursorPosition++; return true; case K_HOME: case K_KP_HOME: EXTRADATA(node).cursorPosition = 0; return true; case K_END: case K_KP_END: EXTRADATA(node).cursorPosition = UTF8_strlen(editedCvar->string); return true; case K_DEL: case K_KP_DEL: UI_TextEntryNodeEdit(node, K_DEL); return true; } /* non printable */ if (unicode < 32 || (unicode >= 127 && unicode < 192)) return false; /* add a char. */ UI_TextEntryNodeEdit(node, unicode); return true; }
/** * @brief Try to autoplace an item at a position * when right-click was used in the inventory. * @param[in] node The context node * @param[in] mouseX X mouse coordinates. * @param[in] mouseY Y mouse coordinates. */ static void UI_ContainerNodeAutoPlace (uiNode_t* node, int mouseX, int mouseY) { if (!ui_inventory) return; /* don't allow this in tactical missions */ if (CL_BattlescapeRunning()) return; const int sel = cl_selected->integer; if (sel < 0) return; assert(EXTRADATA(node).container); invList_t *ic = UI_ContainerNodeGetItemAtPosition(node, mouseX, mouseY); if (!ic) return; UI_ContainerNodeAutoPlaceItem(node, ic); }
/** * @brief Handled after the end of the load of the node from the script (all data and/or child are set) */ void uiImageNode::onLoaded (uiNode_t* node) { /* update the size when its possible */ if (Vector2Empty(node->box.size)) { if (EXTRADATA(node).texl[0] != 0 || EXTRADATA(node).texh[0]) { node->box.size[0] = EXTRADATA(node).texh[0] - EXTRADATA(node).texl[0]; node->box.size[1] = EXTRADATA(node).texh[1] - EXTRADATA(node).texl[1]; } else if (EXTRADATA(node).source) { const image_t* image = UI_LoadImage(EXTRADATA(node).source); if (image) { node->box.size[0] = image->width; node->box.size[1] = image->height; } } } #ifdef DEBUG if (Vector2Empty(node->box.size)) { if (node->onClick || node->onRightClick || node->onMouseEnter || node->onMouseLeave || node->onWheelUp || node->onWheelDown || node->onWheel || node->onMiddleClick) { Com_DPrintf(DEBUG_CLIENT, "Node '%s' is an active image without size\n", UI_GetPath(node)); } } #endif }
static void UI_ModelNodeCapturedMouseMove (uiNode_t *node, int x, int y) { float *rotateAngles = EXTRADATA(node).angles; /* rotate a model */ rotateAngles[YAW] -= ROTATE_SPEED * (x - oldMousePosX); rotateAngles[ROLL] += ROTATE_SPEED * (y - oldMousePosY); /* clamp the angles */ while (rotateAngles[YAW] > 360.0) rotateAngles[YAW] -= 360.0; while (rotateAngles[YAW] < 0.0) rotateAngles[YAW] += 360.0; if (rotateAngles[ROLL] < 0.0) rotateAngles[ROLL] = 0.0; else if (rotateAngles[ROLL] > 180.0) rotateAngles[ROLL] = 180.0; oldMousePosX = x; oldMousePosY = y; }
/** * @brief Draws the free and usable inventory positions when dragging an item. * @note Only call this function in dragging mode */ static void UI_ContainerNodeDrawFreeSpace (uiNode_t *node, inventory_t *inv) { const objDef_t *od = UI_DNDGetItem()->item; /**< Get the 'type' of the dragged item. */ vec2_t nodepos; /* Draw only in dragging-mode and not for the equip-floor */ assert(UI_DNDIsDragging()); assert(inv); UI_GetNodeAbsPos(node, nodepos); /* if single container (hands, extension, headgear) */ if (EXTRADATA(node).container->single) { /* if container is free or the dragged-item is in it */ if (UI_DNDIsSourceNode(node) || INVSH_CheckToInventory(inv, od, EXTRADATA(node).container, 0, 0, dragInfoIC)) UI_DrawFree(EXTRADATA(node).container->id, node, nodepos[0], nodepos[1], node->box.size[0], node->box.size[1], true); } else { /* The shape of the free positions. */ uint32_t free[SHAPE_BIG_MAX_HEIGHT]; bool showTUs = true; int x, y; OBJZERO(free); for (y = 0; y < SHAPE_BIG_MAX_HEIGHT; y++) { for (x = 0; x < SHAPE_BIG_MAX_WIDTH; x++) { /* Check if the current position is usable (topleft of the item). */ /* Add '1's to each position the item is 'blocking'. */ const int checkedTo = INVSH_CheckToInventory(inv, od, EXTRADATA(node).container, x, y, dragInfoIC); if (checkedTo & INV_FITS) /* Item can be placed normally. */ INVSH_MergeShapes(free, (uint32_t)od->shape, x, y); if (checkedTo & INV_FITS_ONLY_ROTATED) /* Item can be placed rotated. */ INVSH_MergeShapes(free, INVSH_ShapeRotate((uint32_t)od->shape), x, y); /* Only draw on existing positions. */ if (INVSH_CheckShape(EXTRADATA(node).container->shape, x, y)) { if (INVSH_CheckShape(free, x, y)) { UI_DrawFree(EXTRADATA(node).container->id, node, nodepos[0] + x * C_UNIT, nodepos[1] + y * C_UNIT, C_UNIT, C_UNIT, showTUs); showTUs = false; } } } } } }
/** * @brief Calculates the size of a container node and links the container * into the node (uses the @c invDef_t shape bitmask to determine the size) * @param[in,out] node The node to get the size for */ void uiContainerNode::onLoaded (uiNode_t* const node) { const char *name; const invDef_t *container; /** @todo find a better way to add more equip node, without this hack */ name = node->name; if (Q_strstart(node->name, "equip_")) name = "equip"; container = INVSH_GetInventoryDefinitionByID(name); if (container == NULL) return; EXTRADATA(node).container = container; if (UI_IsScrollContainerNode(node)) { /* No need to compute the size, the script provide it */ } else { int i, j; /* Start on the last bit of the shape mask. */ for (i = SHAPE_BIG_MAX_WIDTH - 1; i >= 0; i--) { for (j = 0; j < SHAPE_BIG_MAX_HEIGHT; j++) if (container->shape[j] & (1 << i)) break; if (j < SHAPE_BIG_MAX_HEIGHT) break; } node->box.size[0] = C_UNIT * (i + 1) + 0.01; /* start on the lower row of the shape mask */ for (i = SHAPE_BIG_MAX_HEIGHT - 1; i >= 0; i--) if (container->shape[i] & ~0x0) break; node->box.size[1] = C_UNIT * (i + 1) + 0.01; } }
/** * @brief Update the scroll according to the number * of items and the size of the node */ static void UI_OptionListNodeUpdateScroll (uiNode_t* node) { int lineHeight; bool updated; int elements; lineHeight = EXTRADATA(node).lineHeight; if (lineHeight == 0) { const char* font = UI_GetFontFromNode(node); lineHeight = UI_FontGetHeight(font); } elements = (node->box.size[1] - node->padding - node->padding) / lineHeight; updated = EXTRADATA(node).scrollY.set(-1, elements, EXTRADATA(node).count); if (updated) { if (EXTRADATA(node).onViewChange) { UI_ExecuteEventActions(node, EXTRADATA(node).onViewChange); } else if (EXTRADATA(node).lua_onViewChange != LUA_NOREF) { UI_ExecuteLuaEventScript (node, EXTRADATA(node).lua_onViewChange); } } }
/** * @brief Return the first option of the node * @todo check versionId and update cached data, and fire events */ uiNode_t* UI_AbstractOptionGetFirstOption (uiNode_t * node) { if (node->firstChild && node->firstChild->behaviour == ui_optionBehaviour) { return node->firstChild; } else { const int v = UI_GetDataVersion(EXTRADATA(node).dataId); if (v != EXTRADATA(node).versionId) { int count = 0; uiNode_t *option = UI_GetOption(EXTRADATA(node).dataId); while (option) { if (!option->invis) count++; option = option->next; } EXTRADATA(node).count = count; EXTRADATA(node).versionId = v; } return UI_GetOption(EXTRADATA(node).dataId); } }
/** * @brief Scroll to the bottom * @param[in] nodePath absolute path */ void UI_TextScrollEnd (const char* nodePath) { uiNode_t* node = UI_GetNodeByPath(nodePath); if (!node) { Com_DPrintf(DEBUG_CLIENT, "UI_TextScrollEnd: Node '%s' could not be found\n", nodePath); return; } if (!UI_NodeInstanceOf(node, "text")) { Com_Printf("UI_TextScrollEnd: '%s' node is no instance of 'text'.\n", Cmd_Argv(1)); return; } uiTextNode* b = dynamic_cast<uiTextNode*>(node->behaviour->manager.get()); b->validateCache(node); if (EXTRADATA(node).super.scrollY.fullSize > EXTRADATA(node).super.scrollY.viewSize) { EXTRADATA(node).super.scrollY.viewPos = EXTRADATA(node).super.scrollY.fullSize - EXTRADATA(node).super.scrollY.viewSize; UI_ExecuteEventActions(node, EXTRADATA(node).super.onViewChange); } }
/** * @brief Set the position of the scrollbar to a value */ static void UI_VScrollbarNodeSet (uiNode_t* node, int value) { int pos = value; if (pos < 0) { pos = 0; } else if (pos > EXTRADATA(node).fullsize - EXTRADATA(node).viewsize) { pos = EXTRADATA(node).fullsize - EXTRADATA(node).viewsize; } if (pos < 0) pos = 0; /* nothing change */ if (EXTRADATA(node).pos == pos) return; /* update status */ EXTRADATA(node).pos = pos; /* fire change event */ if (node->onChange) { UI_ExecuteEventActions(node, node->onChange); } }
static void UI_PanelNodeDoLayout (uiNode_t *node) { if (!node->invalidated) return; switch (EXTRADATA(node).layout) { case LAYOUT_NONE: break; case LAYOUT_TOP_DOWN_FLOW: UI_TopDownFlowLayout(node, EXTRADATA(node).layoutMargin); break; case LAYOUT_LEFT_RIGHT_FLOW: UI_LeftRightFlowLayout(node, EXTRADATA(node).layoutMargin); break; case LAYOUT_BORDER: UI_BorderLayout(node, EXTRADATA(node).layoutMargin); break; case LAYOUT_PACK: UI_PackLayout(node, EXTRADATA(node).layoutMargin); break; case LAYOUT_STAR: UI_StarLayout(node); break; case LAYOUT_CLIENT: UI_ClientLayout(node); break; case LAYOUT_COLUMN: UI_ColumnLayout(node); break; default: Com_Printf("UI_PanelNodeDoLayout: layout '%d' unsupported.", EXTRADATA(node).layout); break; } localBehaviour->super->doLayout(node); }
void uiSequenceNode::onLeftClick (uiNode_t *node, int x, int y) { if (EXTRADATA(node).context != NULL) { SEQ_SendClickEvent(EXTRADATA(node).context); } }
void uiOptionListNode::draw (uiNode_t* node) { uiNode_t* option; const char* ref; const char* font; int lineHeight; vec2_t pos; int currentY; const float* textColor; int count = 0; ref = UI_AbstractOptionGetCurrentValue(node); if (ref == nullptr) return; UI_GetNodeAbsPos(node, pos); if (EXTRADATA(node).background) { UI_DrawSpriteInBox(false, EXTRADATA(node).background, SPRITE_STATUS_NORMAL, pos[0], pos[1], node->box.size[0], node->box.size[1]); } font = UI_GetFontFromNode(node); lineHeight = EXTRADATA(node).lineHeight; if (lineHeight == 0) lineHeight = UI_FontGetHeight(font); currentY = pos[1] + node->padding; /* skip option over current position */ option = UI_AbstractOptionGetFirstOption(node); while (option && count < EXTRADATA(node).scrollY.viewPos) { option = option->next; count++; } /* draw all available options for this selectbox */ for (; option; option = option->next) { int decX = pos[0] + node->padding; /* outside the node */ if (currentY + lineHeight > pos[1] + node->box.size[1] - node->padding) { count++; break; } /* draw the hover effect */ if (OPTIONEXTRADATA(option).hovered) UI_DrawFill(pos[0] + node->padding, currentY, node->box.size[0] - node->padding - node->padding, lineHeight, node->color); /* text color */ if (Q_streq(OPTIONEXTRADATA(option).value, ref)) { textColor = node->selectedColor; } else if (node->disabled || option->disabled) { textColor = node->disabledColor; } else if (option->color[3] == 0.0f) { textColor = node->color; } else { textColor = option->color; } if (OPTIONEXTRADATA(option).icon) { uiSpriteStatus_t iconStatus = SPRITE_STATUS_NORMAL; if (option->disabled) iconStatus = SPRITE_STATUS_DISABLED; R_Color(nullptr); UI_DrawSpriteInBox(OPTIONEXTRADATA(option).flipIcon, OPTIONEXTRADATA(option).icon, iconStatus, decX, currentY, OPTIONEXTRADATA(option).icon->size[0], lineHeight); decX += OPTIONEXTRADATA(option).icon->size[0] + lineHeight / 4; } /* print the option label */ const char* label = CL_Translate(OPTIONEXTRADATA(option).label); R_Color(textColor); UI_DrawString(font, ALIGN_UL, decX, currentY, pos[0], node->box.size[0] - node->padding - node->padding, 0, label, 0, 0, nullptr, false, LONGLINES_PRETTYCHOP); /* next entries' position */ currentY += lineHeight; count++; } R_Color(nullptr); /* count number of options (current architecture doesn't allow to know if the data change) */ for (; option; option = option->next) { count++; } if (EXTRADATA(node).count != count) { EXTRADATA(node).count = count; } UI_OptionListNodeUpdateScroll(node); }