コード例 #1
0
ファイル: scenpick.c プロジェクト: Almamu/homeworld
/*-----------------------------------------------------------------------------
    Name        : spScenarioBitmap
    Description :
    Inputs      :
    Outputs     :
    Return      :
----------------------------------------------------------------------------*/
void spScenarioBitmap(featom *atom, regionhandle region)
{
    rectangle textureRect;
    sdword index, y;
    fonthandle oldFont;

    textureRect.x0 = region->rect.x0 + SCP_TEXTURE_INSET;
    textureRect.y0 = region->rect.y0 + SCP_TEXTURE_INSET;
    textureRect.x1 = region->rect.x1 - SCP_TEXTURE_INSET;
    textureRect.y1 = region->rect.y1 - SCP_TEXTURE_INSET;

    //draw the bitmap...
    if (scenarioTexture != TR_InvalidInternalHandle)
    {
        if (glcActive())
        {
            glcRectSolidTexturedScaled2(&textureRect,
                                        spTextureWidth, spTextureHeight,
                                        spTextureData, NULL, TRUE);
        }
        else
        {
            trRGBTextureMakeCurrent(scenarioTexture);
            rndPerspectiveCorrection(FALSE);
            primRectSolidTextured2(&textureRect);               //draw the bitmap
        }
        feStaticRectangleDraw(region);                      //draw a border
    }
    //draw the description text...
    if (spDescription != NULL)
    {                                                       //if there is description text
        dbgAssert(spDescriptionFont != FONT_InvalidFontHandle);
        oldFont = fontMakeCurrent(spDescriptionFont);       //set the font
        if (spDescriptionShadow)
        {                                                   //optionally enable dropshadow
            fontShadowSet(FS_SE, colBlack);
        }
        for (index = 0, y = textureRect.y0; index < spNDescriptionLines; index++)
        {                                                   //draw each line
            dbgAssert(spDescriptionLines[index] != NULL);
            if (y + fontHeight(" ") >= textureRect.y1)
            {                                               //if this line will extend off bottom of region
                break;
            }
            fontPrint(textureRect.x0, y, spDescriptionColor, spDescriptionLines[index]);
            y += fontHeight(" ") + 1;
        }
        fontShadowSet(FS_NONE, colBlack);
        fontMakeCurrent(oldFont);
    }
}
コード例 #2
0
/*-----------------------------------------------------------------------------
    Name        : svShipViewRender
    Description : Callback which draws the main ship view.
    Inputs      : standard FE callback
    Outputs     : ..
    Return      : void
----------------------------------------------------------------------------*/
void svShipViewRender(featom* atom, regionhandle region)
{
    rectangle drawRect;
    rectangle* rect;
    rectangle viewRect;
    fonthandle currentFont;
    GLint viewPort[4];
    GLint box[4];
    ShipStaticInfo* info;
    real32 scale;
    sdword width, height;
    sdword x, y;
    keyindex key;
    char* keystring;
    bool resetRender = FALSE;
    char    temp[100];

    // facilitates smooth transition between auto/manual rotation of ship
    static real32 angle_user_rotated_to       = 0.0f;
    static real32 declination_user_rotated_to = 0.0f;
    static real32 time_user_rotated_view      = 0.0f;
           real32 real_time_angle             = 0.0f;
    static real32 user_real_angle_offset      = 0.0f;
    
    rect = &region->rect;
    viewRect.x0 = 0;
    viewRect.y0 = 0;
    viewRect.x1 = MAIN_WindowWidth  - 1;
    viewRect.y1 = MAIN_WindowHeight - 1;
    info = NULL;

    if (svShipType != DefaultShip)
    {
        if (universe.curPlayerPtr)
        {
            info = GetShipStaticInfoSafe(svShipType, universe.curPlayerPtr->race);
        }
        if (info == NULL)
        {
            info = GetShipStaticInfoSafe(svShipType, GetValidRaceForShipType(svShipType));
        }
        if (info == NULL)
        {
            return;
        }
    }

    svShipViewRegion = region;

    if (!resetRender)
    {
        if (svMouseInside)
        {
            ferDrawFocusWindow(region, lw_focus);
        }
        else
        {
            ferDrawFocusWindow(region, lw_normal);
        }
    }

    soundEventUpdate();

    currentFont = fontMakeCurrent(svShipViewFont);

    if (region->flags == 0 || region->flags == RPE_DrawFunctionAdded)
    {                                         //if region not processed yet
        region->flags =
            RPE_Enter | RPE_Exit |
            RPE_WheelDown | RPE_WheelUp |
            RPE_PressLeft | RPE_ReleaseLeft |
            RPE_PressRight | RPE_ReleaseRight;

        regFunctionSet(region, (regionfunction) svReadMouseEvent);               //set new region handler function
    }

    //scale = *svScale[svShipType];
        //svCamera.closestZoom  = *svMinZoom[svShipType];
    //svCamera.farthestZoom = *svMaxZoom[svShipType];

    scale = 1.0f; //*svScale[svShipType];

    if(svShipType != DefaultShip)
    {
        svCamera.closestZoom = info->minimumZoomDistance*svZoomInScalar;
        svCamera.farthestZoom = (svCamera.closestZoom+info->staticheader.staticCollInfo.approxcollspheresize)*svZoomOutScalar;
        if(ReZoom)
        {
            ReZoom=FALSE;
            cameraZoom(&svCamera,1.0f,FALSE);
        }

        if (svMouseInside && (wheel_down || wheel_up))
        {
            cameraControl(&svCamera, FALSE);
        }
        else if (svMouseInside && svMousePressRight)
        {
            camMouseX = (svMouseCentreX - mouseCursorX()) * 4;      //was 2
            camMouseY = (svMouseCentreY - mouseCursorY()) * 4;
            savecamMouseX = savecamMouseX * SPIN_FEEDBACK +
                (real32)camMouseX * (1.0f - SPIN_FEEDBACK);
            cameraControl(&svCamera, FALSE);                         //update the camera

            mouseCursorHide();
            mousePositionSet(svMouseCentreX, svMouseCentreY); // Reset position so it doesn't walk off region

            // keep track of where the user left the camera so we can sync auto-rotation with it
            angle_user_rotated_to       = svCamera.angle;
            declination_user_rotated_to = svCamera.declination;
            time_user_rotated_view      = universe.totaltimeelapsed;
        }
        else // auto rotate ship model
        {
            // continual 360 degree yaw rotation
            real_time_angle = DEG_TO_RAD(remainder(universe.totaltimeelapsed, SV_360_ROTATION_SECS) / SV_360_ROTATION_SECS * 360);

            if (angle_user_rotated_to >= 0.0) {
                user_real_angle_offset = angle_user_rotated_to - real_time_angle;
                angle_user_rotated_to = -1.0;
            }

            svCamera.angle = real_time_angle + user_real_angle_offset;
            
            // collapse pitch to default declination
            if (time_user_rotated_view > 0.0) {
                if (universe.totaltimeelapsed > time_user_rotated_view + SV_PITCH_FLATTEN_SECS) {
                    svCamera.declination = DEG_TO_RAD(svDeclination);
                    time_user_rotated_view = 0.0;
                }
                else {
                    svCamera.declination = declination_user_rotated_to + (DEG_TO_RAD(svDeclination) - declination_user_rotated_to) * ((universe.totaltimeelapsed - time_user_rotated_view) / SV_PITCH_FLATTEN_SECS);
                }
            }
            
            if (svMouseInside) mouseCursorShow();
        }
    }
    //rotation

    drawRect.x0 = rect->x0 + SV_ViewMargin;
    drawRect.y0 = rect->y0 + SV_ViewMargin;
    drawRect.x1 = rect->x1 - SV_ViewMargin;
    drawRect.y1 = rect->y1 - SV_ViewMargin;

    width  = drawRect.x1 - drawRect.x0;
    height = drawRect.y1 - drawRect.y0;

    glGetIntegerv(GL_VIEWPORT, viewPort);
    glViewport(drawRect.x0, MAIN_WindowHeight - drawRect.y1, width, height);

    primModeSet2();
    if (!resetRender)
    {
        primRectSolid2(&viewRect, FEC_Background);
    }
    primModeClear2();

    glEnable(GL_SCISSOR_TEST);
    glGetIntegerv(GL_SCISSOR_BOX, box);
    glScissor(drawRect.x0, MAIN_WindowHeight - drawRect.y1, width, height);
    glClear(GL_DEPTH_BUFFER_BIT);
    glDisable(GL_SCISSOR_TEST);

    rndPerspectiveCorrection(TRUE);

    //svCamera.lookatpoint.x = -info->staticheader.staticCollInfo.collsphereoffset.z * scale;
    //svCamera.lookatpoint.y = -info->staticheader.staticCollInfo.collsphereoffset.x * scale;
    //svCamera.lookatpoint.z = -info->staticheader.staticCollInfo.collsphereoffset.y * scale;
    if (svShipType == DefaultShip)
    {
        svCamera.lookatpoint.x=0.0f;
        svCamera.lookatpoint.y=0.0f;
        svCamera.lookatpoint.z=0.0f;
    }
    else
    {
        svCamera.lookatpoint.x = -info->staticheader.staticCollInfo.collsphereoffset.z;
        svCamera.lookatpoint.y = -info->staticheader.staticCollInfo.collsphereoffset.x;
        svCamera.lookatpoint.z = -info->staticheader.staticCollInfo.collsphereoffset.y;
    }

    cameraSetEyePosition(&svCamera);

    rndLightingEnable(TRUE);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    rgluPerspective(
        svCamera.fieldofview,
        (float)(width) / (float)(height) /*rndAspectRatio*/,    //set projection matrix
        svCamera.clipPlaneNear,
        svCamera.clipPlaneFar);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

    rgluLookAt(
        svCamera.eyeposition.x,
        svCamera.eyeposition.y,
        svCamera.eyeposition.z,
        svCamera.lookatpoint.x,
        svCamera.lookatpoint.y,
        svCamera.lookatpoint.z,
        svCamera.upvector.x,
        svCamera.upvector.y,
        svCamera.upvector.z);

    glPushMatrix();

    glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);

    glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)(&rndCameraMatrix));
    glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)(&rndProjectionMatrix));

    glEnable(GL_NORMALIZE);

    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition0);      //position light(s) within world

    glScalef(scale, scale, scale);

    if (svShipType != DefaultShip)
    {
        sdword index;
        //try player index colours first
        index = universe.curPlayerIndex;
        if (info->teamColor[index] == 0)
        {
            //colour scheme doesn't exist, search for something valid
            for (index = 0; index < MAX_MULTIPLAYER_PLAYERS; index++)
            {
                if (info->teamColor[index] != 0)
                {
                    break;
                }
            }
            if (index == MAX_MULTIPLAYER_PLAYERS)
            {
                //this ship doesn't have any colour info,
                //at least avoid a GPF
                index = universe.curPlayerIndex;
            }
        }
        meshRender((meshdata *)info->staticheader.LOD->level[0].pData, index);
    }

    glDisable(GL_NORMALIZE);

    glPopMatrix();

    primModeSet2();

    glScissor(box[0], box[1], box[2], box[3]);
    glViewport(viewPort[0], viewPort[1], viewPort[2], viewPort[3]);

    rndLightingEnable(FALSE);
    rndPerspectiveCorrection(FALSE);

    x = rect->x0 + 2 + SV_ViewMargin;
    y = rect->y0 + 2 + SV_ViewMargin;

    if (svShipType != DefaultShip && !resetRender)
    {
        fontPrintf(
            x,
            y,
            FEC_ListItemStandard,
            "%s",
            ShipTypeToNiceStr(svShipType));

        y += fontHeight(" ");

        sprintf(temp, "%s %d %s",strGetString(strSVCost),info->buildCost, strGetString(strSVRUs));

        fontPrintf(
            x,
            y,
            FEC_ListItemStandard,
            temp);

        if (cmPrintHotKey)
        {
            x = rect->x1 - 2 - SV_ViewMargin;
            y = rect->y0 + 2 + SV_ViewMargin;

            key = cmShipTypeToKey(svShipType);
            keystring = opKeyToNiceString((keyindex)(key & 0x00ff));

            if (key & CM_SHIFT)
            {
                width = fontWidthf("[SHIFT-%s]",keystring);
                fontPrintf(
                    x-width,
                    y,
                    FEC_ListItemStandard,
                    "[SHIFT-%s]",
                    keystring);
            }
            else if (key)
            {
                width = fontWidthf("[%s]",keystring);
                fontPrintf(
                    x-width,
                    y,
                    FEC_ListItemStandard,
                    "[%s]",
                    keystring);
            }
        }
    }
    fontMakeCurrent(currentFont);

    svDirtyShipView();
}
コード例 #3
0
ファイル: TradeMgr.c プロジェクト: rcarmo/homeworld
/*-----------------------------------------------------------------------------
    Name        : tmTechImageDraw
    Description : Loads in, decompresses and draws the tech picture.
    Inputs      : none
    Outputs     : loads in tmTechImage and creates tmTechTexture
    Return      : void
----------------------------------------------------------------------------*/
void tmTechImageDraw(featom *atom, regionhandle region)
{
    char      filename[128];
    sdword    index, lru = 0;
    real32    time=(real32)1.0e22;
    rectangle textureRect;

    tmTechImageRegion = region;

    feStaticRectangleDraw(region); //draw standard rectangle

    if (tmtechinfo != -1)
    {
        if (tmtechinfo != tmCurTechTexture)
        {
            for (index=0;index<TM_TOTALPICS;index++) // RM_TOTALPICS is the size of the cache
            {
                // Find least recently used texture
                if (pictures[index].timestamp < time)
                {
                    time = pictures[index].timestamp;
                    lru  = index;
                }
                // If already cached, use it and exit this routine
                if ( (pictures[index].tech==tmtechinfo) &&
                     (pictures[index].race==universe.curPlayerPtr->race) )
                {
                    tmTechTexturePrepare(index);
                    tmCurTechTexture = tmtechinfo;
                    tmCurTechImage = pictures[lru].techImage;
                    tmCurIndex = index;
                    pictures[index].timestamp = universe.totaltimeelapsed;

                    textureRect.x0=region->rect.x0+TM_TEXTURE_INSET;
                    textureRect.y0=region->rect.y0+TM_TEXTURE_INSET;
                    textureRect.x1=region->rect.x1-TM_TEXTURE_INSET;
                    textureRect.y1=region->rect.y1-TM_TEXTURE_INSET;

                    rndPerspectiveCorrection(FALSE);
                    primRectSolidTextured2(&textureRect);

                    //if(tmExtendedInfoActive)
                    //{
                    //    primRectTranslucent2(&textureRect, colRGBA(0, 0, 0, 128));
                    //    tmTechInfoDraw(region);
                    //}
                    return;
                }
            }

            // Build filename for loading texture from file
            strcpy(filename, TechImagePaths[universe.curPlayerPtr->race]);
            strcat(filename, TechTypeToString(tmtechinfo));
            strcat(filename,".lif");

            // Remove oldest (least recently used) texture from memory
            if (pictures[lru].techImage != NULL)
            {
                memFree(pictures[lru].techImage);
                pictures[lru].techImage = NULL;
            }
            if (pictures[lru].techTexture != TR_InvalidInternalHandle)
            {
                trRGBTextureDelete(pictures[lru].techTexture);
                pictures[lru].techTexture = TR_InvalidInternalHandle;
            }

            // Load the image into LRU cache
            pictures[lru].techImage = trLIFFileLoad(filename, NonVolatile);
            dbgAssertOrIgnore(pictures[lru].techImage->flags & TRF_Paletted);

            tmTechTexturePrepare(lru);
            tmCurTechTexture = tmtechinfo;
            tmCurTechImage = pictures[lru].techImage;
            pictures[lru].tech = tmtechinfo;
            pictures[lru].race = universe.curPlayerPtr->race;
            pictures[lru].timestamp = universe.totaltimeelapsed;
        }
        else
        {
            trPalettedTextureMakeCurrent(pictures[tmCurIndex].techTexture,
                                         pictures[tmCurIndex].techImage->palette);
        }

        textureRect.x0=region->rect.x0+TM_TEXTURE_INSET;
        textureRect.y0=region->rect.y0+TM_TEXTURE_INSET;
        textureRect.x1=region->rect.x1-TM_TEXTURE_INSET;
        textureRect.y1=region->rect.y1-TM_TEXTURE_INSET;

        rndPerspectiveCorrection(FALSE);
        primRectSolidTextured2(&textureRect);
    }
}
コード例 #4
0
ファイル: BTG.c プロジェクト: australopitheque/HomeworldSDL
/*-----------------------------------------------------------------------------
    Name        : btgRender
    Description : renders the background.  assumes modelview already set
    Inputs      :
    Outputs     :
    Return      :
----------------------------------------------------------------------------*/
void btgRender()
{
    udword nStar;
    sdword lightOn, index;
    GLboolean texOn, blendOn, depthOn;
    udword* dlast;
    udword* dnext;
    static sdword lastFade = 255;

#if MR_KEYBOARD_CHEATS
    extern bool gMosaic;
#endif

    if (btgHead == NULL)
    {
#ifdef _WIN32
        btgLoad("BTG\\default.btg");
#else
        btgLoad("BTG/default.btg");
#endif
    }

#if MR_KEYBOARD_CHEATS
    glShadeModel(gMosaic ? GL_FLAT : GL_SMOOTH);
#else
    glShadeModel(GL_SMOOTH);
#endif
    glGetFloatv(GL_COLOR_CLEAR_VALUE, _bgColor);
    for (index = 0; index < 4; index++)
    {
        _bgByte[index] = (GLubyte)(_bgColor[index] * 255.0f);
    }

    dnext = (udword*)_bgByte;
    dlast = (udword*)lastbg;

    depthOn = glIsEnabled(GL_DEPTH_TEST);
    lightOn = rndLightingEnable(FALSE);
    texOn = glIsEnabled(GL_TEXTURE_2D);
    blendOn = glIsEnabled(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    rndAdditiveBlends(FALSE);

    if (useVBO) glBindBuffer(GL_ARRAY_BUFFER, vboTransVerts);

    //polys
    if (btgFade != lastFade || *dnext != *dlast)
    {
        if (btgFade < 0)
        {
            btgFade = 255;
        }
#ifndef _WIN32_FIXME
        btgColorVertices();
#endif
        if (useVBO) glBufferData(GL_ARRAY_BUFFER, btgHead->numVerts * sizeof(btgTransVertex), btgTransVerts, GL_STATIC_DRAW);
        *dlast = *dnext;
        lastFade = btgFade;
    }

    //use DrawElements to render the bg polys
    glEnableClientState(GL_COLOR_ARRAY);
    glEnableClientState(GL_VERTEX_ARRAY);
    if (useVBO) {
        glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(btgTransVertex), 0);
        glVertexPointer(3, GL_FLOAT, sizeof(btgTransVertex), (GLvoid*)4);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndices);
        glDrawElements(GL_TRIANGLES, 3 * btgHead->numPolys, GL_UNSIGNED_SHORT, 0);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    } else {
        glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(btgTransVertex), (GLubyte*)btgTransVerts);
        glVertexPointer(3, GL_FLOAT, sizeof(btgTransVertex), ((GLubyte*)btgTransVerts) + 4);
        glDrawElements(GL_TRIANGLES, 3 * btgHead->numPolys, GL_UNSIGNED_SHORT, btgIndices);
    }
    glDisableClientState(GL_COLOR_ARRAY);

    //stars
    rndPerspectiveCorrection(FALSE);
    rndAdditiveBlends(TRUE);

    trClearCurrent();
    glEnable(GL_TEXTURE_2D);
    rndTextureEnvironment(RTE_Modulate);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    if (useVBO) {
        glBindBuffer(GL_ARRAY_BUFFER, vboTransStars);
        glVertexPointer(3, GL_FLOAT, sizeof(GLfloat) * 5, 0);
        glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 5, (GLubyte*)sizeof(vector));
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    } else {
        glVertexPointer(3, GL_FLOAT, sizeof(GLfloat) * 5, (GLubyte*)btgTransStars);
        glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 5, ((GLubyte*)btgTransStars) + sizeof(vector));
    }

    for (nStar = 0; nStar < btgHead->numStars; nStar++) {
        if (btgStars[nStar].glhandle) {
            glColor4ub((GLubyte)btgStars[nStar].red, (GLubyte)btgStars[nStar].green, (GLubyte)btgStars[nStar].blue, (GLubyte)btgStars[nStar].alpha);
            glBindTexture(GL_TEXTURE_2D, btgStars[nStar].glhandle);
            glDrawArrays(GL_TRIANGLE_STRIP, nStar * 4, 4);
         }
    }

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);

    glDisable(GL_BLEND);

    rndAdditiveBlends(FALSE);

    rndLightingEnable(lightOn);
    if (texOn) glEnable(GL_TEXTURE_2D);
    if (blendOn)
    {
        glEnable(GL_BLEND);
    }
    else
    {
        glDisable(GL_BLEND);
    }
    glEnable(GL_CULL_FACE);
    if (depthOn)
    {
        glEnable(GL_DEPTH_TEST);
    }
    else
    {
        glDisable(GL_DEPTH_TEST);
    }
}
コード例 #5
0
ファイル: tutorial.c プロジェクト: spippolatore/homeworld-1
void tutExecute(regionhandle reg)
{
    fonthandle currentfont;
    sdword texty, bitmap;

    rectangle rect;                         // used for translucent boxes behind text
    rectangle *buttonrect = &reg->rect;     // used for "next" button
    bool modeset = FALSE;
    sdword bitmap_x, bitmap_vel;

	if(tutorial == 3)
		return;

    if(tutRegion->previous)
        regSiblingMoveToFront(tutRegion);

    if(tutTransition == 0 && tutLesson != TUT_LESSON_ENTER_BUILD_MANAGER && tutLesson != TUT_LESSON_BUILD_SHIP) // don't draw button on build manager lessons
    {
        if(mouseInRect(buttonrect))
        {
            if(mouseLeftButton())
            {
                tutSkip = TRUE;
                trRGBTextureMakeCurrent(tutButtonTexture[NEXT_ON]);
            }
            else
                trRGBTextureMakeCurrent(tutButtonTexture[NEXT_MOUSE]);
        }
        else
            trRGBTextureMakeCurrent(tutButtonTexture[NEXT_OFF]);
        rndPerspectiveCorrection(FALSE);
//      glEnable(GL_BLEND);         // needs to be enabled once Keith fixes alpha blending intel compiler optimization bug
        primRectSolidTextured2(buttonrect);
//      glDisable(GL_BLEND);        // needs to be enabled once Keith fixes alpha blending intel compiler optimization bug
    }

    if(tutTransition == 0)
    {
        switch(PassedTutorial(tutLesson))
        {
        case 0:     // Didn't pass
            break;

        case 1:     // Perform transition
            tutTransition = 1;
            break;

        case -1:    // No Transition
            tutLesson++;
            InitTutorial(tutLesson);
            break;
        }
    }
    else if(tutTransition == 1)
    {
        tutTransitionCount++;
        if(tutTransitionCount == TUT_TransitionFramesOut)
        {
            tutTransition = 2;
            tutTransitionCount = TUT_TransitionFramesIn;
            tutLesson++;
            InitTutorial(tutLesson);
            if((tutLesson >= TUT_ADVANCED_INTRO && tutorial == 1) || (tutLesson >= TUT_TOTAL_LESSONS && tutorial == 2))
            {
                tutorialdone = TRUE;
                return;
            }
        }
    }
    else if(tutTransition == 2)
    {
        tutTransitionCount--;
        if(tutTransitionCount == 0)
            tutTransition = 0;
    }

    if(tutBitmapList[tutLesson][2] != -1)
    {
        bitmap_x = TUT_BITMAP_X;
        bitmap_vel = 210;
    }
    else if(tutBitmapList[tutLesson][1] != -1)
    {
        bitmap_x = TUT_BITMAP_X + (TUT_BITMAP_WIDTH + 8);
        bitmap_vel = 150;
    }
    else
    {
        bitmap_x = TUT_BITMAP_X + ((2 * TUT_BITMAP_WIDTH) + 8);
        bitmap_vel = 90;
    }

    if(tutTransition == 0)
        bitmap_vel = 0;
    else if(tutTransition == 1)
        bitmap_vel = (long) (((float)bitmap_vel/(float)TUT_TransitionFramesOut) * (float)tutTransitionCount);
    else if(tutTransition == 2)
        bitmap_vel = (long) (((float)bitmap_vel/(float)TUT_TransitionFramesIn) * (float)tutTransitionCount);

//  glEnable(GL_BLEND);
    for(bitmap = 0; bitmap < 3; bitmap++)
    {
        if(tutBitmapList[tutLesson][bitmap] != -1)
        {
            trRGBTextureMakeCurrent(tutButtonTexture[tutBitmapList[tutLesson][bitmap]]);
            rndPerspectiveCorrection(FALSE);
            rect.x0 = bitmap_x + ((TUT_BITMAP_WIDTH + 8) * bitmap) + bitmap_vel;
            rect.y0 = TUT_BITMAP_Y;
            rect.x1 = bitmap_x + ((TUT_BITMAP_WIDTH + 8) * bitmap) + TUT_BITMAP_WIDTH + bitmap_vel;
            rect.y1 = TUT_BITMAP_Y + TUT_BITMAP_HEIGHT;
            primRectSolidTextured2(&rect);
        }
    }
//  glDisable(GL_BLEND);

    if (!primModeEnabled)   // draw translucent polys before text
    {
        primModeSet2();
        modeset = TRUE;
    }

    if(tutLesson != TUT_LESSON_BUILD_SHIP)      // default behaviour for lessons
    {
    long    TitlePos = (long)(TUT_TitleTransMult[tutTransition] * (float)tutTransitionCount);
    long    TextPos = (long)(TUT_TextTransMult[tutTransition] * (float)tutTransitionCount);

        rect.x0 = 0;
        rect.y0 = TUT_Title_Y - TitlePos - 7;
        rect.x1 = 640;
        rect.y1 = TUT_Title_Y - TitlePos + 22;
        primRectTranslucent2(&rect, colRGBA(0, 0, 0, 128));

        rect.x0 = TUT_Main_X - TextPos - 12;
        rect.y0 = TUT_Main_Y - 6;
        rect.x1 = TUT_Main_X - TextPos + TUT_MainTextWidth + 4;
        rect.y1 = tutLastMainY;
        primRectTranslucent2(&rect, colRGBA(0, 0, 0, 128));

        currentfont = fontMakeCurrent(tutTitleFont);    // draw text
        fontPrintf(TUT_Title_X, TUT_Title_Y - TitlePos, TUT_TitleColor, "%s", strGetString(strTutorial00Title + (tutLesson * 7)));
        currentfont = fontMakeCurrent(tutMainFont);
        texty = DrawTextBlock(strGetString(strTutorial00Line01 + (tutLesson * 7)), TUT_Main_X - TextPos, TUT_Main_Y, TUT_MainTextWidth, TUT_MainTextHeight, TUT_MainColor);
        texty = DrawTextBlock(strGetString(strTutorial00Line02 + (tutLesson * 7)), TUT_Main_X - TextPos, texty, TUT_MainTextWidth, TUT_MainTextHeight, TUT_MainColor);
        texty = DrawTextBlock(strGetString(strTutorial00Line03 + (tutLesson * 7)), TUT_Main_X - TextPos, texty, TUT_MainTextWidth, TUT_MainTextHeight, TUT_MainColor);
        texty = DrawTextBlock(strGetString(strTutorial00Line04 + (tutLesson * 7)), TUT_Main_X - TextPos, texty, TUT_MainTextWidth, TUT_MainTextHeight, TUT_MainColor);
        tutLastMainY = DrawTextBlock(strGetString(strTutorial00Line05 + (tutLesson * 7)), TUT_Main_X - TextPos, texty, TUT_MainTextWidth, TUT_MainTextHeight, TUT_MainColor);
        fontMakeCurrent(currentfont);
    }
    else                                    // special case for build ship lesson
    {
        currentfont = fontMakeCurrent(tutMainFont);
        texty = DrawTextBlock(strGetString(strTutorial17Line01 + tutVar.count), TUT_Build_X, TUT_Build_Y, TUT_BuildTextWidth, TUT_BuildTextHeight, TUT_BuildColor);
        fontMakeCurrent(currentfont);

        rect.x0 = TUT_Build_X - 8;          // draw outline box around text
        rect.y0 = TUT_Build_Y - 6;
        rect.x1 = TUT_Build_X + TUT_BuildTextWidth + 8;
        rect.y1 = texty;
        primRectOutline2(&rect, 2, colRGB(tutPulseValue, tutPulseValue, tutPulseValue));

        if(tutVar.count == 0)               // point to appropriate place on screen
            tutDrawLinePulse(TUT_Build_X - 8, texty, 160, 100, tutPulseValue, 8);
        else if(tutVar.count == 1)
            tutDrawLinePulse(TUT_Build_X - 8, texty, 180, 410, tutPulseValue, 8);
        else if(tutVar.count == 2)
            tutDrawLinePulse(TUT_Build_X - 8, texty, 550, 410, tutPulseValue, 8);

        tutPulseValue -= 8;
    }

    if(!FirstWordNULL(strGetString(strTutorial00Tip + (tutLesson * 7))))
    {
    long    TipPos = (long)(TUT_TipTransMult[tutTransition] * (float)tutTransitionCount);
    long    TextPos = (long)(TUT_TextTransMult[tutTransition] * (float)tutTransitionCount);

        if (!primModeEnabled)   // draw translucent polys before tip text
        {
            primModeSet2();
            modeset = TRUE;
        }

        rect.x0 = TUT_TipTitle_X - 8;
        rect.y0 = TUT_TipTitle_Y - TipPos - 6;
        rect.x1 = TUT_Tip_X - 8;
        rect.y1 = TUT_TipTitle_Y - TipPos + 18;
        primRectTranslucent2(&rect, colRGBA(0, 0, 0, 128));

        rect.x0 = TUT_Tip_X + TextPos - 8;
        rect.y0 = TUT_Tip_Y - 6;
        rect.x1 = TUT_Tip_X + TextPos + TUT_TipTextWidth + 8;
        rect.y1 = tutLastTipY;
        primRectTranslucent2(&rect, colRGBA(0, 0, 0, 128));

        if(modeset)
            primModeClear2();

        currentfont = fontMakeCurrent(tutTipTitleFont);
        fontPrintf(TUT_TipTitle_X, TUT_TipTitle_Y - TipPos, TUT_TipTitleColor, "%s", strGetString(strTutorialTip));
        currentfont = fontMakeCurrent(tutTipFont);
        tutLastTipY = DrawTextBlock(strGetString(strTutorial00Tip + (tutLesson * 7)), TUT_Tip_X + TextPos, TUT_Tip_Y, TUT_TipTextWidth, TUT_TipTextHeight, TUT_TipColor);
    }

    fontMakeCurrent(currentfont);
}