/* ================ SCR_DrawPic Coordinates are 640*480 virtual values ================= */ void SCR_DrawPic(float x, float y, float width, float height, qhandle_t hShader) { SCR_AdjustFrom640(&x, &y, &width, &height); re.DrawStretchPic(x, y, width, height, 0, 0, 1, 1, hShader); }
/* ========================== Menu_Draw ========================== */ void Menu_Draw (menuframework_s *menu) { int i; menucommon_s *item; // // draw contents // for (i = 0; i < menu->nitems; i++) { // skip hidden items if ( ((menucommon_s *)menu->items[i])->flags & QMF_HIDDEN ) continue; switch ( ((menucommon_s *)menu->items[i])->type ) { case MTYPE_FIELD: Field_Draw( ( menufield_s * )menu->items[i] ); break; case MTYPE_SLIDER: Slider_Draw( (menuslider_s *)menu->items[i] ); break; case MTYPE_LIST: MenuList_Draw( (menulist_s *)menu->items[i] ); break; case MTYPE_SPINCONTROL: SpinControl_Draw( (menulist_s *)menu->items[i] ); break; case MTYPE_ACTION: Action_Draw( (menuaction_s *)menu->items[i] ); break; case MTYPE_SEPARATOR: Separator_Draw( (menuseparator_s *)menu->items[i] ); break; } } // added Psychspaz's mouse support // // now check mouseovers - psychospaz // cursor.menu = menu; if (cursor.mouseaction) { menucommon_s *lastitem = cursor.menuitem; UI_RefreshCursorLink(); for (i = menu->nitems; i >= 0 ; i--) { int type, len; int min[2], max[2]; float x1, y1, w1, h1; item = ((menucommon_s * )menu->items[i]); if (!item || item->type == MTYPE_SEPARATOR) continue; x1 = menu->x + item->x + RCOLUMN_OFFSET; // + 2 chars for space + cursor y1 = menu->y + item->y; w1 = 0; h1 = MENU_FONT_SIZE; SCR_AdjustFrom640 (&x1, &y1, &w1, &h1, ALIGN_CENTER); min[0] = x1; max[0] = x1+w1; min[1] = y1; max[1] = y1+h1; // max[0] = min[0] = SCR_ScaledVideo(menu->x + item->x + RCOLUMN_OFFSET); //+ 2 chars for space + cursor // max[1] = min[1] = SCR_ScaledVideo(menu->y + item->y); // max[1] += SCR_ScaledVideo(MENU_FONT_SIZE); switch (item->type) { case MTYPE_ACTION: { len = strlen(item->name); if (item->flags & QMF_LEFT_JUSTIFY) { min[0] += SCR_ScaledVideo(LCOLUMN_OFFSET*2); max[0] = min[0] + SCR_ScaledVideo(len*MENU_FONT_SIZE); } else min[0] -= SCR_ScaledVideo(len*MENU_FONT_SIZE + MENU_FONT_SIZE*3); type = MENUITEM_ACTION; } break; case MTYPE_SLIDER: { if (item->name) { len = strlen(item->name); min[0] -= SCR_ScaledVideo(len*MENU_FONT_SIZE - LCOLUMN_OFFSET*2); } else min[0] -= SCR_ScaledVideo(16); max[0] += SCR_ScaledVideo((SLIDER_RANGE + 4)*MENU_FONT_SIZE); type = MENUITEM_SLIDER; } break; case MTYPE_LIST: case MTYPE_SPINCONTROL: { int len; menulist_s *spin = menu->items[i]; if (item->name) { len = strlen(item->name); min[0] -= SCR_ScaledVideo(len*MENU_FONT_SIZE - LCOLUMN_OFFSET*2); } len = strlen(spin->itemnames[spin->curvalue]); max[0] += SCR_ScaledVideo(len*MENU_FONT_SIZE); type = MENUITEM_ROTATE; } break; case MTYPE_FIELD: { menufield_s *text = menu->items[i]; len = text->visible_length + 2; max[0] += SCR_ScaledVideo(len*MENU_FONT_SIZE); type = MENUITEM_TEXT; } break; default: continue; } if (cursor.x>=min[0] && cursor.x<=max[0] && cursor.y>=min[1] && cursor.y<=max[1]) { // new item if (lastitem!=item) { int j; for (j=0; j<MENU_CURSOR_BUTTON_MAX; j++) { cursor.buttonclicks[j] = 0; cursor.buttontime[j] = 0; } } cursor.menuitem = item; cursor.menuitemtype = type; menu->cursor = i; break; } } } cursor.mouseaction = false; // end mouseover code item = Menu_ItemAtCursor(menu); if (item && item->cursordraw) { item->cursordraw(item); } else if (menu->cursordraw) { menu->cursordraw(menu); } else if (item && item->type != MTYPE_FIELD) { if (item->flags & QMF_LEFT_JUSTIFY) { SCR_DrawChar (menu->x+item->x+item->cursor_offset-24, menu->y+item->y, ALIGN_CENTER, 12+((int)(Sys_Milliseconds()/250)&1), 255,255,255,255, false, true); } else { SCR_DrawChar (menu->x+item->cursor_offset, menu->y+item->y, ALIGN_CENTER, 12+((int)(Sys_Milliseconds()/250)&1), 255,255,255,255, false, true); } } if (item) { if (item->statusbarfunc) item->statusbarfunc ( (void *)item ); else if (item->statusbar) Menu_DrawStatusBar (item->statusbar); else Menu_DrawStatusBar (menu->statusbar); } else Menu_DrawStatusBar( menu->statusbar ); }
/* ================== Con_UpdateConsoleState updates the consoleState ================== */ void Con_UpdateConsoleState( void ) { float horizontalMargin, verticalMargin; int totalVerticalPadding; const int charHeight = SCR_ConsoleFontCharHeight(); const int charPadding = SCR_ConsoleFontCharVPadding(); /* * calculate margin and border * we will treat the border in pixel (as opposed to margins and paddings) * to allow for nice looking 1px borders, as well as to prevent * different widths for horizontal and vertical borders due to different resolution-ratios * since that isn't as nice looking as with areas */ consoleState.border.bottom = std::max( 0, con_borderWidth->integer ); if(con_margin->value > 0) { horizontalMargin = con_margin->value; verticalMargin = con_margin->value; consoleState.border.sides = consoleState.border.bottom; consoleState.border.top = consoleState.border.bottom; } else { horizontalMargin = - con_margin->value; verticalMargin = 0; consoleState.border.sides = 0; consoleState.border.top = 0; } SCR_AdjustFrom640( &horizontalMargin, &verticalMargin, NULL, NULL ); consoleState.margin.top = verticalMargin; consoleState.margin.bottom = verticalMargin; consoleState.margin.sides = horizontalMargin; /* * calculate padding */ consoleState.padding.top = floor( verticalMargin * 0.3f ); consoleState.padding.bottom = std::max( 3, consoleState.padding.top ); // on wide screens, this will lead to somewhat of a centering of the text if(con_horizontalPadding->integer) { float horizontalVidPadding = con_horizontalPadding->value; SCR_AdjustFrom640( &horizontalVidPadding, NULL, NULL, NULL ); consoleState.padding.sides = horizontalVidPadding; } else { consoleState.padding.sides = floor( horizontalMargin * 0.3f ); } /* * calculate global alpha factor * apply the fade animation if the type is set, otherwise remain completly visible */ consoleState.currentAlphaFactor = ( con_animationType->integer & ANIMATION_TYPE_FADE ) ? consoleState.currentAnimationFraction : 1.0f; /* * calculate current console height */ consoleState.height = con_height->integer * 0.01 * (cls.glconfig.vidHeight - consoleState.margin.top - consoleState.margin.bottom - consoleState.border.top - consoleState.border.bottom ); totalVerticalPadding = consoleState.padding.top + consoleState.padding.bottom; // clip to a multiple of the character height, plus padding consoleState.height -= ( consoleState.height - totalVerticalPadding - charPadding ) % charHeight; // ... and ensure that at least three lines are visible consoleState.height = std::max( 3 * charHeight + totalVerticalPadding, consoleState.height ); //animate via scroll animation if the type is set if ( con_animationType->integer & ANIMATION_TYPE_SCROLL_DOWN) { consoleState.height *= consoleState.currentAnimationFraction; } if ( consoleState.height > cls.glconfig.vidHeight ) { consoleState.height = cls.glconfig.vidHeight; } /* * calculate current amount of visible lines after we learned about the current height */ consoleState.visibleAmountOfLines = ( consoleState.height - consoleState.padding.top - consoleState.padding.bottom ) / charHeight //rowheight in pixel -> amount of rows - 2 ; // dont count the input and the scrollbackindicator }
/* ================ Con_DrawSolidConsole Draws the console with the solid background ================ */ void Con_DrawSolidConsole( float frac ) { int i, x, y; int rows; int row; int lines; // qhandle_t conShader; int currentColor; vec4_t color; float yVer; float totalwidth; float currentWidthLocation = 0; const int charHeight = SCR_ConsoleFontCharHeight(); if ( scr_conUseOld->integer ) { lines = cls.glconfig.vidHeight * frac; if ( lines <= 0 ) { return; } if ( lines > cls.glconfig.vidHeight ) { lines = cls.glconfig.vidHeight; } } else { lines = cls.glconfig.vidHeight * frac; } lines += charHeight / ( CONSOLE_FONT_VPADDING + 1 ); // on wide screens, we will center the text if (!scr_conUseOld->integer) { con.xadjust = 15; } SCR_AdjustFrom640 (&con.xadjust, NULL, NULL, NULL); // draw the background if ( scr_conUseOld->integer ) { yVer = 5 + charHeight; y = frac * SCREEN_HEIGHT; if ( y < 1 ) { y = 0; } else { if ( scr_conUseShader->integer ) { SCR_DrawPic( 0, 0, SCREEN_WIDTH, y, cls.consoleShader ); } else { // This will be overwritten, so i'll just abuse it here, no need to define another array color[ 0 ] = scr_conColorRed->value; color[ 1 ] = scr_conColorGreen->value; color[ 2 ] = scr_conColorBlue->value; color[ 3 ] = scr_conColorAlpha->value; SCR_FillRect( 0, 0, SCREEN_WIDTH, y, color ); } } color[ 0 ] = scr_conBarColorRed->value; color[ 1 ] = scr_conBarColorGreen->value; color[ 2 ] = scr_conBarColorBlue->value; color[ 3 ] = scr_conBarColorAlpha->value; SCR_FillRect( 0, y, SCREEN_WIDTH, scr_conBarSize->value, color ); } else { yVer = 10; SCR_AdjustFrom640( NULL, &yVer, NULL, NULL ); yVer = floor( yVer + 5 + charHeight ); color[ 0 ] = scr_conColorRed->value; color[ 1 ] = scr_conColorGreen->value; color[ 2 ] = scr_conColorBlue->value; color[ 3 ] = frac * 2 * scr_conColorAlpha->value; SCR_FillRect( 10, 10, 620, 460 * scr_conHeight->integer * 0.01, color ); color[ 0 ] = scr_conBarColorRed->value; color[ 1 ] = scr_conBarColorGreen->value; color[ 2 ] = scr_conBarColorBlue->value; color[ 3 ] = frac * 2 * scr_conBarColorAlpha->value; SCR_FillRect( 10, 10, 620, 1, color ); //top SCR_FillRect( 10, 460 * scr_conHeight->integer * 0.01 + 10, 621, 1, color ); //bottom SCR_FillRect( 10, 10, 1, 460 * scr_conHeight->integer * 0.01, color ); //left SCR_FillRect( 630, 10, 1, 460 * scr_conHeight->integer * 0.01, color ); //right } // draw the version number color[ 0 ] = 1.0f; color[ 1 ] = 1.0f; color[ 2 ] = 1.0f; color[ 3 ] = ( scr_conUseOld->integer ? 0.75f : frac * 0.75f ); re.SetColor( color ); i = strlen( Q3_VERSION ); totalwidth = SCR_ConsoleFontStringWidth( Q3_VERSION, i ) + cl_conXOffset->integer; if ( !scr_conUseOld->integer ) { totalwidth += 30; } currentWidthLocation = cls.glconfig.vidWidth - totalwidth; for ( x = 0; x < i; x++ ) { int ch = Q_UTF8CodePoint( &Q3_VERSION[ x ] ); SCR_DrawConsoleFontUnichar( currentWidthLocation, yVer, ch ); currentWidthLocation += SCR_ConsoleFontUnicharWidth( ch ); } // engine string i = strlen( Q3_ENGINE ); totalwidth = SCR_ConsoleFontStringWidth( Q3_ENGINE, i ) + cl_conXOffset->integer; if ( !scr_conUseOld->integer ) { totalwidth += 30; } currentWidthLocation = cls.glconfig.vidWidth - totalwidth; for ( x = 0; x < i; x++ ) { int ch = Q_UTF8CodePoint( &Q3_ENGINE[ x ] ); SCR_DrawConsoleFontUnichar( currentWidthLocation, yVer + charHeight, ch ); currentWidthLocation += SCR_ConsoleFontUnicharWidth( ch ); } // draw the input prompt, user text, and cursor if desired // moved back here (have observed render issues to do with time taken) Con_DrawInput(); // draw the text con.vislines = lines; rows = ( lines ) / SCR_ConsoleFontCharHeight() - 3; // rows of text to draw if ( scr_conUseOld->integer ) { rows++; } y = lines - ( SCR_ConsoleFontCharHeight() * 3 ) + 10; // draw from the bottom up if ( con.display != con.current ) { // draw arrows to show the buffer is backscrolled const int hatWidth = SCR_ConsoleFontUnicharWidth( '^' ); color[ 0 ] = 1.0f; color[ 1 ] = 0.0f; color[ 2 ] = 0.0f; color[ 3 ] = ( scr_conUseOld->integer ? 1.0f : frac * 2.0f ); re.SetColor( color ); for ( x = 0; x < con.linewidth - ( scr_conUseOld->integer ? 0 : 4 ); x += 4 ) { SCR_DrawConsoleFontUnichar( con.xadjust + ( x + 1 ) * hatWidth, y, '^' ); } y -= charHeight; rows--; } row = con.display; if ( con.x == 0 ) { row--; } currentColor = 7; color[ 0 ] = g_color_table[ currentColor ][ 0 ]; color[ 1 ] = g_color_table[ currentColor ][ 1 ]; color[ 2 ] = g_color_table[ currentColor ][ 2 ]; color[ 3 ] = ( scr_conUseOld->integer ? 1.0f : frac * 2.0f ); re.SetColor( color ); for ( i = 0; i < rows; i++, y -= charHeight, row-- ) { conChar_t *text; if ( row < 0 ) { break; } if ( con.current - row >= con.totallines ) { // past scrollback wrap point continue; } text = con.text + CON_LINE( row ); currentWidthLocation = cl_conXOffset->integer; for ( x = 0; x < con.linewidth && text[x].ch; ++x ) { if ( text[ x ].ink != currentColor ) { currentColor = text[ x ].ink; color[ 0 ] = g_color_table[ currentColor ][ 0 ]; color[ 1 ] = g_color_table[ currentColor ][ 1 ]; color[ 2 ] = g_color_table[ currentColor ][ 2 ]; color[ 3 ] = ( scr_conUseOld->integer ? 1.0f : frac * 2.0f ); re.SetColor( color ); } SCR_DrawConsoleFontUnichar( con.xadjust + currentWidthLocation, y, text[ x ].ch ); currentWidthLocation += SCR_ConsoleFontUnicharWidth( text[ x ].ch ); } } re.SetColor( NULL ); }
/* ================ Con_CheckResize If the line width has changed, reformat the buffer. ================ */ void Con_CheckResize( void ) { int i, width, oldwidth, oldtotallines, numlines, numchars; conChar_t buf[ CON_TEXTSIZE ]; if ( cls.glconfig.vidWidth ) { if ( scr_conUseOld->integer ) { width = cls.glconfig.vidWidth / SCR_ConsoleFontUnicharWidth( 'W' ); } else { float adjust = 30; SCR_AdjustFrom640( &adjust, NULL, NULL, NULL ); width = ( cls.glconfig.vidWidth - adjust ) / SCR_ConsoleFontUnicharWidth( 'W' ); } g_consoleField.widthInChars = width - Q_PrintStrlen( cl_consolePrompt->string ) - 1; } else { width = 0; } if ( width == con.linewidth ) { // nothing } else if ( width < 1 ) // video hasn't been initialized yet { width = DEFAULT_CONSOLE_WIDTH; con.linewidth = width; con.totallines = CON_TEXTSIZE / con.linewidth; Con_Clear(); con.current = con.totallines - 1; con.display = con.current; } else { SCR_AdjustFrom640( &con.xadjust, NULL, NULL, NULL ); oldwidth = con.linewidth; con.linewidth = width; oldtotallines = con.totallines; con.totallines = CON_TEXTSIZE / con.linewidth; numlines = oldtotallines; if ( con.totallines < numlines ) { numlines = con.totallines; } numchars = oldwidth; if ( con.linewidth < numchars ) { numchars = con.linewidth; } Com_Memcpy( buf, con.text, sizeof( con.text ) ); Con_Clear(); for ( i = 0; i < numlines; i++ ) { memcpy( con.text + ( con.totallines - 1 - i ) * con.linewidth, buf + ( ( con.current - i + oldtotallines ) % oldtotallines ) * oldwidth, numchars * sizeof( conChar_t ) ); } con.current = con.totallines - 1; con.display = con.current; } g_console_field_width = g_consoleField.widthInChars = con.linewidth - 7 - ( cl_consolePrompt ? Q_UTF8Strlen( cl_consolePrompt->string ) : 0 ); }
/* ================ SCR_FillRect Coordinates are 640*480 virtual values ================= */ void SCR_FillAdjustedRect( float x, float y, float width, float height, const float *color ) { SCR_AdjustFrom640( &x, &y, &width, &height ); SCR_FillRect( x, y, width, height, color ); }
void PlayerConfig_MenuDraw (void) { refdef_t refdef; float rx, ry, rw, rh; Menu_DrawBanner ("m_banner_plauer_setup"); // typo for image name is id's fault memset(&refdef, 0, sizeof(refdef)); rx = 0; ry = 0; rw = SCREEN_WIDTH; rh = SCREEN_HEIGHT; SCR_AdjustFrom640 (&rx, &ry, &rw, &rh, ALIGN_CENTER); refdef.x = rx; refdef.y = ry; refdef.width = rw; refdef.height = rh; refdef.fov_x = 50; refdef.fov_y = CalcFov (refdef.fov_x, refdef.width, refdef.height); refdef.time = cls.realtime*0.001; if ( s_pmi[s_player_model_box.curvalue].skindisplaynames ) { int yaw; int maxframe = 29; vec3_t modelOrg; // Psychopspaz's support for showing weapon model entity_t entity[2], *ent; refdef.num_entities = 0; refdef.entities = entity; yaw = anglemod(cl.time/10); VectorSet (modelOrg, 150, (hand->value==1)?25:-25, 0); // was 80, 0, 0 // Setup player model ent = &entity[0]; memset (&entity[0], 0, sizeof(entity[0])); // moved registration code to init and change only ent->model = playermodel; ent->skin = playerskin; ent->flags = RF_FULLBRIGHT|RF_NOSHADOW|RF_DEPTHHACK; if (hand->value == 1) ent->flags |= RF_MIRRORMODEL; ent->origin[0] = modelOrg[0]; ent->origin[1] = modelOrg[1]; ent->origin[2] = modelOrg[2]; VectorCopy( ent->origin, ent->oldorigin ); ent->frame = 0; ent->oldframe = 0; ent->backlerp = 0.0; ent->angles[1] = yaw; //if ( ++yaw > 360 ) // yaw -= 360; if (hand->value == 1) ent->angles[1] = 360 - ent->angles[1]; refdef.num_entities++; // Setup weapon model ent = &entity[1]; memset (&entity[1], 0, sizeof(entity[1])); // moved registration code to init and change only ent->model = weaponmodel; if (ent->model) { ent->skinnum = 0; ent->flags = RF_FULLBRIGHT|RF_NOSHADOW|RF_DEPTHHACK; if (hand->value == 1) ent->flags |= RF_MIRRORMODEL; ent->origin[0] = modelOrg[0]; ent->origin[1] = modelOrg[1]; ent->origin[2] = modelOrg[2]; VectorCopy( ent->origin, ent->oldorigin ); ent->frame = 0; ent->oldframe = 0; ent->backlerp = 0.0; ent->angles[1] = yaw; if (hand->value == 1) ent->angles[1] = 360 - ent->angles[1]; refdef.num_entities++; } refdef.areabits = 0; refdef.lightstyles = 0; refdef.rdflags = RDF_NOWORLDMODEL; Menu_Draw( &s_player_config_menu ); // skin selection preview PlayerConfig_DrawSkinSelection (); R_RenderFrame( &refdef ); } }