/*----------------------------------------------------------------------------- Name : primRoundRectOutline Description : Draw an outline 2d rounded rectangle. Inputs : rect - pointer to rectangle structure containing coordinates. thickness - thickness of the lines c - color to draw it in, xb - x offset, yb - y offset Outputs : .. Return : void ----------------------------------------------------------------------------*/ void primRoundRectOutline(rectangle *rect, sdword thickness, color c, uword xb, uword yb) { oval o; sdword segs = SEGS; glColor3ub(colRed(c), colGreen(c), colBlue(c)); glPushAttrib(GL_LINE_BIT); glLineWidth((GLfloat)thickness); glBegin(GL_LINES); glVertex2f(SX(X0+xb), SY(Y0)); glVertex2f(SX(X1-xb), SY(Y0)); glVertex2f(SX(X1), SY(Y0+yb)); glVertex2f(SX(X1), SY(Y1-yb)); glVertex2f(SX(X1-xb), SY(Y1)); glVertex2f(SX(X0+xb), SY(Y1)); glVertex2f(SX(X0), SY(Y1-yb)); glVertex2f(SX(X0), SY(Y0+yb)); glEnd(); glPopAttrib(); // if (xb > 4 || yb > 4) // segs *= 2; // upper left o.centreX = X0+xb; o.centreY = Y0+yb; o.radiusX = xb; o.radiusY = yb; primOvalArcOutline2(&o, 3*PI/2, TWOPI, 2, segs, c); // upper right o.centreX = X1-xb; primOvalArcOutline2(&o, (real32)0, PI/2, 2, segs, c); // lower right o.centreY = Y1-yb; primOvalArcOutline2(&o, PI/2, PI, 2, segs, c); // lower left o.centreX = X0+xb; primOvalArcOutline2(&o, PI, 3*PI/2, 2, segs, c); }
/*----------------------------------------------------------------------------- Name : pingListDraw Description : Draw all pings from farthest to nearest. Inputs : camera - the camera we're rendering from modelView, projection - current matrices viewPort - rectangle we're rending in, for the TO legend Outputs : Return : Note : The renderer should be in 2D mode at this point. ----------------------------------------------------------------------------*/ void pingListDraw(Camera *camera, hmatrix *modelView, hmatrix *projection, rectangle *viewPort) { real32 pingAge, pingCycle, pingMod, pingSize; real32 x, y, radius; Node *thisNode, *nextNode; ping *thisPing; vector distSquared; sdword nSegments, index, rowHeight, xScreen, yScreen; oval o; udword TOFlags = 0; fonthandle fhSave; toicon *icon; color col; real32 realMargin; ShipClass shipClass; static real32 lastProximityPing = REALlyBig; static real32 lastAnomolyPing = REALlyBig; static real32 lastBattlePing = REALlyBig; static real32 lastHyperspacePing = REALlyBig; static real32 lastNewshipPing = REALlyBig; bool pingset; //start by sorting the ping list from farthest to nearest thisNode = pingList.head; while (thisNode != NULL) { //scan all pings nextNode = thisNode->next; thisPing = listGetStructOfNode(thisNode); if (thisPing->owner != NULL) { thisPing->centre = thisPing->owner->posinfo.position; } vecSub(distSquared, camera->eyeposition, thisPing->centre); thisPing->cameraDistanceSquared = vecMagnitudeSquared(distSquared); TOFlags |= thisPing->TOMask; thisNode = nextNode; } listMergeSortGeneral(&pingList, pingListSortCallback); //now the list is sorted; proceed to draw all the pings thisNode = pingList.head; pingset = FALSE; while (thisNode != NULL) { //scan all pings nextNode = thisNode->next; thisPing = listGetStructOfNode(thisNode); pingCycle = thisPing->pingDuration + thisPing->interPingPause; pingAge = universe.totaltimeelapsed - thisPing->creationTime; pingMod = (real32)fmod((double)pingAge, (double)pingCycle); if (pingMod <= thisPing->pingDuration) { pingSize = (thisPing->size - thisPing->minSize) * pingMod / thisPing->pingDuration + thisPing->minSize; selCircleComputeGeneral(modelView, projection, &thisPing->centre, max(thisPing->size,thisPing->minSize), &x, &y, &radius); if (radius > 0.0f) { radius = max(radius, thisPing->minScreenSize); radius *= pingSize / max(thisPing->size,thisPing->minSize); o.centreX = primGLToScreenX(x); o.centreY = primGLToScreenY(y); o.radiusX = o.radiusY = primGLToScreenScaleX(radius); nSegments = pieCircleSegmentsCompute(radius); primOvalArcOutline2(&o, 0.0f, 2*PI, 1, nSegments, thisPing->c); /* starting to draw a new ping so play the sound */ if (!smZoomingIn && !smZoomingOut && !pingset) { switch (thisPing->TOMask) { case PTOM_Anomaly: if (pingSize <=lastAnomolyPing) { soundEvent(NULL, UI_SensorsPing); pingset = TRUE; lastAnomolyPing = pingSize; } break; case PTOM_Battle: if (pingSize <= lastBattlePing) { soundEvent(NULL, UI_PingBattle); pingset = TRUE; lastBattlePing = pingSize; } break; case PTOM_Hyperspace: if (pingSize <= lastHyperspacePing) { soundEvent(NULL, UI_PingHyperspace); pingset = TRUE; lastHyperspacePing = pingSize; } break; case PTOM_Proximity: if (pingSize <= lastProximityPing) { soundEvent(NULL, UI_PingProximity); pingset = TRUE; lastProximityPing = pingSize; } break; case PTOM_NewShips: if (pingSize <= lastNewshipPing) { soundEvent(NULL, UI_PingNewShips); pingset = TRUE; lastNewshipPing = pingSize; } break; default: break; } } } } thisNode = nextNode; } //draw the blip TO if (smTacticalOverlay) { realMargin = primScreenToGLScaleX(viewPort->x0); fhSave = fontCurrentGet(); //save the current font fontMakeCurrent(selGroupFont2); // use a common, fairly small font rowHeight = fontHeight("M"); // used to space the legend yScreen = viewPort->y0 + rowHeight; //leave some space at the top to start radius = primScreenToGLScaleX(rowHeight)/2; xScreen = viewPort->x0 + (sdword)(rowHeight * 2.5); for (index = 0; index < PTO_NumberTOs; index++) { if ((TOFlags & pingTOList[index].bitMask)) { // fontPrint(xScreen, yScreen, *pingTOList[index].c, "O"); pingTOList[index].lastTimeDrawn = universe.totaltimeelapsed; } if (universe.totaltimeelapsed - pingTOList[index].lastTimeDrawn <= pingTOLingerTime) { o.centreX = viewPort->x0 + rowHeight * 3 / 2; o.centreY = yScreen + rowHeight / 2; o.radiusX = o.radiusY = rowHeight / 2; primOvalArcOutline2(&o, 0.0f, TWOPI, 1, pingTONSegments, *pingTOList[index].c); fontPrint(xScreen, yScreen, TO_TextColor, strGetString(pingTOList[index].stringEnum)); yScreen += rowHeight + 1; } } for (shipClass = 0; shipClass < NUM_CLASSES; shipClass++) { if (!toClassUsed[shipClass][0]) { continue; } icon = toClassIcon[shipClass]; fontPrint(xScreen, yScreen + (rowHeight>>2), TO_TextColor, ShipClassToNiceStr(shipClass)); #if TO_STANDARD_COLORS col = teFriendlyColor; #else col = teColorSchemes[universe.curPlayerIndex].tacticalColor; #endif col = colRGB(colRed(col)/TO_IconColorFade, colGreen(col)/TO_IconColorFade, colBlue(col)/TO_IconColorFade); primLineLoopStart2(1, col); for (index = icon->nPoints - 1; index >= 0; index--) { primLineLoopPoint3F(realMargin + primScreenToGLX(rowHeight*1.5) + icon->loc[index].x * radius, primScreenToGLY(yScreen + rowHeight/2) + icon->loc[index].y * radius); } primLineLoopEnd2(); yScreen += rowHeight + 1; } fontMakeCurrent(fhSave); } }