/** ** Draw decoration (invis, for the unit.) ** ** @param unit Pointer to the unit. ** @param type Type of the unit. ** @param screenPos Screen position of the unit. */ static void DrawDecoration(const CUnit &unit, const CUnitType &type, const PixelPos &screenPos) { int x = screenPos.x; int y = screenPos.y; #ifdef DEBUG // Show the number of references. CLabel(GetGameFont()).DrawClip(x + 1, y + 1, unit.Refs); #endif UpdateUnitVariables(const_cast<CUnit &>(unit)); // Now show decoration for each variable. for (std::vector<CDecoVar *>::const_iterator i = UnitTypeVar.DecoVar.begin(); i < UnitTypeVar.DecoVar.end(); ++i) { const CDecoVar &var = *(*i); const int value = unit.Variable[var.Index].Value; const int max = unit.Variable[var.Index].Max; Assert(value <= max); if (!((value == 0 && !var.ShowWhenNull) || (value == max && !var.ShowWhenMax) || (var.HideHalf && value != 0 && value != max) || (!var.ShowIfNotEnable && !unit.Variable[var.Index].Enable) || (var.ShowOnlySelected && !unit.Selected) || (unit.Player->Type == PlayerNeutral && var.HideNeutral) || (ThisPlayer->IsEnemy(unit) && !var.ShowOpponent) || (ThisPlayer->IsAllied(unit) && (unit.Player != ThisPlayer) && var.HideAllied) || max == 0)) { var.Draw( x + var.OffsetX + var.OffsetXPercent * unit.Type->TileWidth * PixelTileSize.x / 100, y + var.OffsetY + var.OffsetYPercent * unit.Type->TileHeight * PixelTileSize.y / 100, type, unit.Variable[var.Index]); } } // Draw group number if (unit.Selected && unit.GroupId != 0 #ifndef DEBUG && unit.Player == ThisPlayer #endif ) { int groupId = 0; if (unit.Player->AiEnabled) { groupId = unit.GroupId - 1; } else { for (groupId = 0; !(unit.GroupId & (1 << groupId)); ++groupId) { } } const int width = GetGameFont().Width(groupId); x += (unit.Type->TileWidth * PixelTileSize.x + unit.Type->BoxWidth) / 2 - width; const int height = GetGameFont().Height(); y += (unit.Type->TileHeight * PixelTileSize.y + unit.Type->BoxHeight) / 2 - height; CLabel(GetGameFont()).DrawClip(x, y, groupId); } }
/** ** Draw the player resource in top line. ** ** @todo FIXME : make DrawResources more configurable (format, font). */ void DrawResources() { CLabel label(GetGameFont()); // Draw all icons of resource. for (int i = 0; i <= FreeWorkersCount; ++i) { if (UI.Resources[i].G) { UI.Resources[i].G->DrawFrameClip(UI.Resources[i].IconFrame, UI.Resources[i].IconX, UI.Resources[i].IconY); } } for (int i = 0; i < MaxCosts; ++i) { if (UI.Resources[i].TextX != -1) { const int resourceAmount = ThisPlayer->Resources[i]; if (ThisPlayer->MaxResources[i] != -1) { const int resAmount = ThisPlayer->StoredResources[i] + ThisPlayer->Resources[i]; char tmp[256]; snprintf(tmp, sizeof(tmp), "%d (%d)", resAmount, ThisPlayer->MaxResources[i] - ThisPlayer->StoredResources[i]); label.SetFont(GetSmallFont()); label.Draw(UI.Resources[i].TextX, UI.Resources[i].TextY + 3, tmp); } else { label.SetFont(resourceAmount > 99999 ? GetSmallFont() : GetGameFont()); label.Draw(UI.Resources[i].TextX, UI.Resources[i].TextY + (resourceAmount > 99999) * 3, resourceAmount); } } } if (UI.Resources[FoodCost].TextX != -1) { char tmp[256]; snprintf(tmp, sizeof(tmp), "%d/%d", ThisPlayer->Demand, ThisPlayer->Supply); label.SetFont(GetGameFont()); if (ThisPlayer->Supply < ThisPlayer->Demand) { label.DrawReverse(UI.Resources[FoodCost].TextX, UI.Resources[FoodCost].TextY, tmp); } else { label.Draw(UI.Resources[FoodCost].TextX, UI.Resources[FoodCost].TextY, tmp); } } if (UI.Resources[ScoreCost].TextX != -1) { const int score = ThisPlayer->Score; label.SetFont(score > 99999 ? GetSmallFont() : GetGameFont()); label.Draw(UI.Resources[ScoreCost].TextX, UI.Resources[ScoreCost].TextY + (score > 99999) * 3, score); } if (UI.Resources[FreeWorkersCount].TextX != -1) { const int workers = ThisPlayer->FreeWorkers.size(); label.SetFont(GetGameFont()); label.Draw(UI.Resources[FreeWorkersCount].TextX, UI.Resources[FreeWorkersCount].TextY, workers); } }
/** ** Show load progress. ** ** @param fmt printf format string. */ void ShowLoadProgress(const char *fmt, ...) { static unsigned int lastProgressUpdate = SDL_GetTicks(); if (SDL_GetTicks() < lastProgressUpdate + 16) { // Only show progress updates every c. 1/60th of a second, otherwise we're waiting for the screen too much return; } lastProgressUpdate = SDL_GetTicks(); UpdateLoadProgress(); va_list va; char temp[4096]; va_start(va, fmt); vsnprintf(temp, sizeof(temp) - 1, fmt, va); temp[sizeof(temp) - 1] = '\0'; va_end(va); if (Video.Depth && IsGameFontReady() && GetGameFont().IsLoaded()) { // Remove non printable chars for (unsigned char *s = (unsigned char *)temp; *s; ++s) { if (*s < 32) { *s = ' '; } } //Wyrmgus start // Video.FillRectangle(ColorBlack, 5, Video.Height - 18, Video.Width - 10, 18); if (loadingBackground == nullptr) { Video.FillRectangle(ColorBlack, 0, Video.Height - 18, Video.Width, 18); } //Wyrmgus end CLabel(GetGameFont()).DrawCentered(Video.Width / 2, Video.Height - 16, temp); //Wyrmgus start // InvalidateArea(5, Video.Height - 18, Video.Width - 10, 18); if (loadingBackground == nullptr) { InvalidateArea(0, Video.Height - 18, Video.Width, 18); } else { InvalidateArea(0, 0, Video.Width, Video.Height); } //Wyrmgus end RealizeVideoMemory(); } else { DebugPrint("!!!!%s\n" _C_ temp); } PollEvents(); }
/** ** Draw missile. */ void Missile::DrawMissile(const CViewport &vp) const { Assert(this->Type); CUnit *sunit = this->SourceUnit; // FIXME: I should copy SourcePlayer for second level missiles. if (sunit && sunit->Player) { #ifdef DYNAMIC_LOAD if (!this->Type->Sprite) { LoadMissileSprite(this->Type); } #endif } const PixelPos screenPixelPos = vp.MapToScreenPixelPos(this->position); switch (this->Type->Class) { case MissileClassHit: CLabel(GetGameFont()).DrawClip(screenPixelPos.x, screenPixelPos.y, this->Damage); break; default: if (Type->G) { this->Type->DrawMissileType(this->SpriteFrame, screenPixelPos); } break; } }
/** ** Draw costs in status line. ** ** @todo FIXME : make DrawCosts more configurable. ** @todo FIXME : 'time' resource should be shown too. ** ** @internal MaxCost == FoodCost. */ void CStatusLine::DrawCosts() { int x = UI.StatusLine.TextX + 268; CLabel label(GetGameFont()); if (this->Costs[ManaResCost]) { UI.Resources[ManaResCost].G->DrawFrameClip(UI.Resources[ManaResCost].IconFrame, x, UI.StatusLine.TextY); x += 20; x += label.Draw(x, UI.StatusLine.TextY, this->Costs[ManaResCost]); } for (unsigned int i = 1; i <= MaxCosts; ++i) { if (this->Costs[i]) { x += 5; if (UI.Resources[i].G) { UI.Resources[i].G->DrawFrameClip(UI.Resources[i].IconFrame, x, UI.StatusLine.TextY); x += 20; } x += label.Draw(x, UI.StatusLine.TextY, this->Costs[i]); if (x > Video.Width - 60) { break; } } } }
/** ** @brief Update load progress. */ void UpdateLoadProgress() { if (Video.Depth && IsGameFontReady() && GetGameFont().IsLoaded()) { UpdateLoadingBar(); } PollEvents(); }
static void InfoPanel_draw_no_selection() { DrawInfoPanelBackground(0); if (UnitUnderCursor && UnitUnderCursor->IsVisible(*ThisPlayer) && !UnitUnderCursor->Type->BoolFlag[ISNOTSELECTABLE_INDEX].value) { // FIXME: not correct for enemies units DrawUnitInfo(*UnitUnderCursor); } else { // FIXME: need some cool ideas for this. int x = UI.InfoPanel.X + 16; int y = UI.InfoPanel.Y + 8; CLabel label(GetGameFont()); label.Draw(x, y, "Stratagus"); y += 16; label.Draw(x, y, _("Cycle:")); label.Draw(x + 48, y, GameCycle); //Wyrmgus start // label.Draw(x + 110, y, CYCLES_PER_SECOND * VideoSyncSpeed / 100); label.Draw(x + 110, y, _("Speed:")); label.Draw(x + 110 + 53, y, CYCLES_PER_SECOND * VideoSyncSpeed / 100); //Wyrmgus end y += 20; std::string nc; std::string rc; GetDefaultTextColors(nc, rc); for (int i = 0; i < PlayerMax - 1; ++i) { if (Players[i].Type != PlayerNobody) { if (ThisPlayer->IsAllied(Players[i])) { label.SetNormalColor(FontGreen); } else if (ThisPlayer->IsEnemy(Players[i])) { label.SetNormalColor(FontRed); } else { label.SetNormalColor(nc); } label.Draw(x + 15, y, i); Video.DrawRectangleClip(ColorWhite, x, y, 12, 12); Video.FillRectangleClip(Players[i].Color, x + 1, y + 1, 10, 10); //Wyrmgus start // label.Draw(x + 27, y, Players[i].Name); label.Draw(x + 27, y, _(Players[i].Name.c_str())); //the score was appearing on top of the faction name // label.Draw(x + 117, y, Players[i].Score); //Wyrmgus end y += 14; } } } }
/** ** Display update. ** ** This functions updates everything on screen. The map, the gui, the ** cursors. */ void UpdateDisplay() { if (GameRunning || Editor.Running == EditorEditing) { // to prevent empty spaces in the UI #if defined(USE_OPENGL) || defined(USE_GLES) Video.FillRectangleClip(ColorBlack, 0, 0, Video.ViewportWidth, Video.ViewportHeight); #else Video.FillRectangleClip(ColorBlack, 0, 0, Video.Width, Video.Height); #endif DrawMapArea(); DrawMessages(); if (CursorState == CursorStateRectangle) { DrawCursor(); } //Wyrmgus start if (CursorBuilding && CursorOn == CursorOnMap) { DrawBuildingCursor(); } //Wyrmgus end if ((Preference.BigScreen && !BigMapMode) || (!Preference.BigScreen && BigMapMode)) { UiToggleBigMap(); } if (!BigMapMode) { for (size_t i = 0; i < UI.Fillers.size(); ++i) { UI.Fillers[i].G->DrawSubClip(0, 0, UI.Fillers[i].G->Width, UI.Fillers[i].G->Height, UI.Fillers[i].X, UI.Fillers[i].Y); } DrawMenuButtonArea(); DrawUserDefinedButtons(); UI.Minimap.Draw(); UI.Minimap.DrawViewportArea(*UI.SelectedViewport); UI.InfoPanel.Draw(); DrawResources(); UI.StatusLine.Draw(); UI.StatusLine.DrawCosts(); UI.ButtonPanel.Draw(); } DrawTimer(); //Wyrmgus start //draw worker icon if there are idle workers if (UI.IdleWorkerButton && !ThisPlayer->FreeWorkers.empty()) { int worker_unit_type_id = PlayerRaces.GetFactionClassUnitType(ThisPlayer->Race, ThisPlayer->Faction, GetUnitTypeClassIndexByName("worker")); if (worker_unit_type_id != -1) { const CUnitType &type = *UnitTypes[worker_unit_type_id]; const PixelPos pos(UI.IdleWorkerButton->X, UI.IdleWorkerButton->Y); const int flag = (ButtonAreaUnderCursor == ButtonAreaIdleWorker && ButtonUnderCursor == 0) ? (IconActive | (MouseButtons & LeftButton)) : 0; VariationInfo *varinfo = type.GetDefaultVariation(*ThisPlayer); if (varinfo && varinfo->Icon.Icon) { // check if the default variation is valid, and if it is, then make the button use the variation's icon varinfo->Icon.Icon->DrawUnitIcon(*UI.IdleWorkerButton->Style, flag, pos, ".", ThisPlayer->Index); } else { type.Icon.Icon->DrawUnitIcon(*UI.IdleWorkerButton->Style, flag, pos, ".", ThisPlayer->Index); } if (ButtonAreaUnderCursor == ButtonAreaIdleWorker && ButtonUnderCursor == 0) { //if the mouse is hovering over the idle worker button, draw a tooltip std::string idle_worker_tooltip = "Find Idle Worker (~!.)"; if (!Preference.NoStatusLineTooltips) { CLabel label(GetGameFont()); label.Draw(2 + 16, Video.Height + 2 - 16, idle_worker_tooltip); } DrawGenericPopup(idle_worker_tooltip, UI.IdleWorkerButton->X, UI.IdleWorkerButton->Y); } } } //draw icon if there are units with available level up upgrades if (UI.LevelUpUnitButton && !ThisPlayer->LevelUpUnits.empty()) { const PixelPos pos(UI.LevelUpUnitButton->X, UI.LevelUpUnitButton->Y); const int flag = (ButtonAreaUnderCursor == ButtonAreaLevelUpUnit && ButtonUnderCursor == 0) ? (IconActive | (MouseButtons & LeftButton)) : 0; ThisPlayer->LevelUpUnits[0]->GetIcon().Icon->DrawUnitIcon(*UI.LevelUpUnitButton->Style, flag, pos, "", ThisPlayer->Index); if (ButtonAreaUnderCursor == ButtonAreaLevelUpUnit && ButtonUnderCursor == 0) { //if the mouse is hovering over the level up unit button, draw a tooltip std::string level_up_unit_tooltip = "Find Unit with Available Level Up"; if (!Preference.NoStatusLineTooltips) { CLabel label(GetGameFont()); label.Draw(2 + 16, Video.Height + 2 - 16, level_up_unit_tooltip); } DrawGenericPopup(level_up_unit_tooltip, UI.LevelUpUnitButton->X, UI.LevelUpUnitButton->Y); } } //Wyrmgus end //Wyrmgus start } else if (GrandStrategy && !GameRunning && GameResult == GameNoResult) { //grand strategy mode if (!GrandStrategyGamePaused) { //scroll map if mouse is in the scroll area int scroll_up = 7; //the scroll area in the upper part of the screen is smaller to allow clicking on the menu buttons and etc. more comfortably int scroll_down = (Video.Height - 16); int scroll_left = 15; int scroll_right = (Video.Width - 16); bool scrolled = false; if (CursorScreenPos.y < scroll_up) { if (WorldMapOffsetY > 0) { if (GrandStrategyMapHeightIndent == 0) { WorldMapOffsetY = WorldMapOffsetY - 1; } GrandStrategyMapHeightIndent -= 32; } else if (WorldMapOffsetY == 0 && GrandStrategyMapHeightIndent == -32) { //this is to make the entire y 0 tiles be shown scrolling to the northmost part of the map GrandStrategyMapHeightIndent -= 32; } GameCursor = UI.ArrowN.Cursor; scrolled = true; } else if (CursorScreenPos.y > scroll_down) { if (WorldMapOffsetY < GetWorldMapHeight() - 1 - ((UI.MapArea.EndY - UI.MapArea.Y) / 64)) { if (GrandStrategyMapHeightIndent == -32) { WorldMapOffsetY = WorldMapOffsetY + 1; } GrandStrategyMapHeightIndent += 32; } else if (WorldMapOffsetY == GetWorldMapHeight() - 1 - ((UI.MapArea.EndY - UI.MapArea.Y) / 64) && GrandStrategyMapHeightIndent == 0) { GrandStrategyMapHeightIndent += 32; } GameCursor = UI.ArrowS.Cursor; scrolled = true; } if (CursorScreenPos.x < scroll_left) { if (WorldMapOffsetX > 0) { if (GrandStrategyMapWidthIndent == 0) { WorldMapOffsetX = WorldMapOffsetX - 1; } GrandStrategyMapWidthIndent -= 32; } else if (WorldMapOffsetX == 0 && GrandStrategyMapWidthIndent == -32) { //this is to make the entire x 0 tiles be shown scrolling to the westmost part of the map GrandStrategyMapWidthIndent -= 32; } if (GameCursor == UI.ArrowN.Cursor) { GameCursor = UI.ArrowNW.Cursor; } else if (GameCursor == UI.ArrowS.Cursor) { GameCursor = UI.ArrowSW.Cursor; } else { GameCursor = UI.ArrowW.Cursor; } scrolled = true; } else if (CursorScreenPos.x > scroll_right) { if (WorldMapOffsetX < GetWorldMapWidth() - 1 - ((UI.MapArea.EndX - UI.MapArea.X) / 64)) { if (GrandStrategyMapWidthIndent == -32) { WorldMapOffsetX = WorldMapOffsetX + 1; } GrandStrategyMapWidthIndent += 32; } else if (WorldMapOffsetX == GetWorldMapWidth() - 1 - ((UI.MapArea.EndX - UI.MapArea.X) / 64) && GrandStrategyMapWidthIndent == 0) { GrandStrategyMapWidthIndent += 32; } if (GameCursor == UI.ArrowN.Cursor) { GameCursor = UI.ArrowNE.Cursor; } else if (GameCursor == UI.ArrowS.Cursor) { GameCursor = UI.ArrowSE.Cursor; } else { GameCursor = UI.ArrowE.Cursor; } scrolled = true; } if (scrolled) { if (GrandStrategyMapWidthIndent <= -64) { GrandStrategyMapWidthIndent = 0; } if (GrandStrategyMapHeightIndent <= -64) { GrandStrategyMapHeightIndent = 0; } if (GrandStrategyMapWidthIndent > 0) { GrandStrategyMapWidthIndent *= -1; } if (GrandStrategyMapHeightIndent > 0) { GrandStrategyMapHeightIndent *= -1; } } else { GameCursor = UI.Point.Cursor; } } //draw map GrandStrategyGame.DrawMap(); // Fillers for (size_t i = 0; i != UI.Fillers.size(); ++i) { UI.Fillers[i].G->DrawClip(UI.Fillers[i].X, UI.Fillers[i].Y); } GrandStrategyGame.DrawMinimap(); GrandStrategyGame.DrawInterface(); if (UI.MapArea.Contains(CursorScreenPos) && GrandStrategyGame.WorldMapTiles[GrandStrategyGame.GetTileUnderCursor().x][GrandStrategyGame.GetTileUnderCursor().y] && !GrandStrategyGamePaused) { GrandStrategyGame.DrawTileTooltip(GrandStrategyGame.GetTileUnderCursor().x, GrandStrategyGame.GetTileUnderCursor().y); } //Wyrmgus end } DrawPieMenu(); // draw pie menu only if needed DrawGuichanWidgets(); if (CursorState != CursorStateRectangle) { DrawCursor(); } // // Update changes to display. // Invalidate(); }