예제 #1
0
/** Draws the powerup icons on the screen (called once for each player).
 *  \param kart The kart for which to draw the powerup icons.
 *  \param viewport The viewport into which to draw the icons.
 *  \param scaling The scaling to use when draing the icons.
 */
void RaceGUIBase::drawPowerupIcons(const AbstractKart* kart,
                                   const core::recti &viewport,
                                   const core::vector2df &scaling)
{
    // If player doesn't have any powerups or has completed race, do nothing.
    const Powerup* powerup = kart->getPowerup();
    if (powerup->getType() == PowerupManager::POWERUP_NOTHING
        || kart->hasFinishedRace()) return;

    int n = kart->getPowerup()->getNum() ;
    if (n<1) return;    // shouldn't happen, but just in case
    if (n>5) n=5;       // Display at most 5 items

    int nSize = (int)(64.0f*std::min(scaling.X, scaling.Y));

    int itemSpacing = (int)(std::min(scaling.X, scaling.Y)*30);

    int x1 = viewport.UpperLeftCorner.X  + viewport.getWidth()/2
           - (n * itemSpacing)/2;
    int y1 = viewport.UpperLeftCorner.Y  + (int)(20 * scaling.Y);

    assert(powerup != NULL);
    assert(powerup->getIcon() != NULL);
    video::ITexture *t=powerup->getIcon()->getTexture();
    assert(t != NULL);
    core::rect<s32> rect(core::position2di(0, 0), t->getOriginalSize());

    for ( int i = 0 ; i < n ; i++ )
    {
        int x2 = (int)(x1+i*itemSpacing);
        core::rect<s32> pos(x2, y1, x2+nSize, y1+nSize);
        draw2DImage(t, pos, rect, NULL,
                                                  NULL, true);
    }   // for i
}   // drawPowerupIcons
예제 #2
0
//! draws an 2d image
void CNullDriver::draw2DImage(const ITexture* texture, const position2d<s32>& destPos)
{
	if (!texture)
		return;

	draw2DImage(texture,destPos, rectangle<s32>(position2d<s32>(0,0),
												dimension2di(texture->getOriginalSize())));
}
예제 #3
0
파일: 2dutils.cpp 프로젝트: shiv05/stk-code
void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
    const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
    const video::SColor &colors, bool useAlphaChannelOfTexture)
{
    if (!irr_driver->isGLSL()) {
        video::SColor duplicatedArray[4] = {
            colors, colors, colors, colors
        };
        draw2DImage(texture, destRect, sourceRect, clipRect, duplicatedArray, useAlphaChannelOfTexture);
        return;
    }

    float width, height,
        center_pos_x, center_pos_y,
        tex_width, tex_height,
        tex_center_pos_x, tex_center_pos_y;

    getSize(texture->getOriginalSize().Width, texture->getOriginalSize().Height, texture->isRenderTarget(),
        destRect, sourceRect, width, height, center_pos_x, center_pos_y,
        tex_width, tex_height, tex_center_pos_x, tex_center_pos_y);

    if (useAlphaChannelOfTexture)
    {
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }
    else
    {
        glDisable(GL_BLEND);
    }
    if (clipRect)
    {
        if (!clipRect->isValid())
            return;

        glEnable(GL_SCISSOR_TEST);
        const core::dimension2d<u32>& renderTargetSize = irr_driver->getVideoDriver()->getCurrentRenderTargetSize();
        glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,
            clipRect->getWidth(), clipRect->getHeight());
    }

    glUseProgram(UIShader::UniformColoredTextureRectShader::getInstance()->Program);
    glBindVertexArray(SharedObject::UIVAO);

    UIShader::UniformColoredTextureRectShader::getInstance()->SetTextureUnits(createVector<GLuint>(static_cast<const irr::video::COpenGLTexture*>(texture)->getOpenGLTextureName()));
    UIShader::UniformColoredTextureRectShader::getInstance()->setUniforms(
        core::vector2df(center_pos_x, center_pos_y), core::vector2df(width, height), core::vector2df(tex_center_pos_x, tex_center_pos_y), core::vector2df(tex_width, tex_height), colors);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    if (clipRect)
        glDisable(GL_SCISSOR_TEST);
    glUseProgram(0);

    glGetError();
}
예제 #4
0
//! Draws a part of the texture into the rectangle.
void CNullDriver::draw2DImage(const ITexture* texture, const rectangle<s32>& destRect,
	const rectangle<s32>& sourceRect, const rectangle<s32>* clipRect,
	const SColor* const colors, bool useAlphaChannelOfTexture)
{
	if (destRect.isValid())
		draw2DImage(texture, position2d<s32>(destRect.UpperLeftCorner),
				sourceRect, clipRect, colors?colors[0]:SColor(0xffffffff),
				useAlphaChannelOfTexture);
}
예제 #5
0
// ----------------------------------------------------------------------------
//! draws a sprite in 2d with scale and color
void STKModifiedSpriteBank::draw2DSprite(u32 index,
        const core::position2di& pos,
        const core::rect<s32>* clip, const video::SColor& color,
        u32 starttime, u32 currenttime, bool loop, bool center)
{
    assert( m_magic_number == 0xCAFEC001 );
    if (index >= Sprites.size() || Sprites[index].Frames.empty() )
        return;

    // work out frame number
    u32 frame = 0;
    if (Sprites[index].frameTime)
    {
        u32 f = ((currenttime - starttime) / Sprites[index].frameTime);
        if (loop)
            frame = f % Sprites[index].Frames.size();
        else
            frame = (f >= Sprites[index].Frames.size())
                  ? Sprites[index].Frames.size()-1 : f;
    }

    const video::ITexture* tex =
        Textures[Sprites[index].Frames[frame].textureNumber];
    if (!tex)
        return;

    const u32 rn = Sprites[index].Frames[frame].rectNumber;
    if (rn >= Rectangles.size())
        return;

    const core::rect<s32>& r = Rectangles[rn];

    const core::dimension2d<s32>& dim = r.getSize();

    core::rect<s32> dest( pos,
                          core::dimension2d<s32>((int)(dim.Width*m_scale),
                                                 (int)(dim.Height*m_scale)) );
    if (center)
    {
        dest -= dest.getSize() / 2;
    }

    /*
        draw2DImage  (const video::ITexture  *texture,
                      const core::rect<  s32  > &destRect,
                      const core::rect<  s32  > &sourceRect,
                      const core::rect<  s32  > *clipRect=0,
                      const video::SColor  *const colors=0,
                      bool useAlphaChannelOfTexture=false)=0
     */
    draw2DImage(tex, dest, r /* source rect */, clip,
                        NULL /* colors */, true);

}   // draw2DSprite
예제 #6
0
//! draws a set of 2d images, using a color and the alpha channel of the
//! texture if desired.
void CNullDriver::draw2DImageBatch(const ITexture* texture,
				const array<position2d<s32> >& positions,
				const array<rectangle<s32> >& sourceRects,
				const rectangle<s32>* clipRect,
				SColor color,
				bool useAlphaChannelOfTexture)
{
	const u32 drawCount = min_<u32>(positions.size(), sourceRects.size());

	for (u32 i=0; i<drawCount; ++i)
	{
		draw2DImage(texture, positions[i], sourceRects[i],
				clipRect, color, useAlphaChannelOfTexture);
	}
}
예제 #7
0
//! draws a set of 2d images, using a color and the alpha channel of the
//! texture if desired. The images are drawn beginning at pos and concatenated
//! in one line. All drawings are clipped against clipRect (if != 0).
//! The subtextures are defined by the array of sourceRects and are chosen
//! by the indices given.
void CNullDriver::draw2DImageBatch(const ITexture* texture,
				const position2d<s32>& pos,
				const array<rectangle<s32> >& sourceRects,
				const array<s32>& indices,
				s32 kerningWidth,
				const rectangle<s32>* clipRect, SColor color,
				bool useAlphaChannelOfTexture)
{
	position2d<s32> target(pos);

	for (u32 i=0; i<indices.size(); ++i)
	{
		draw2DImage(texture, target, sourceRects[indices[i]],
				clipRect, color, useAlphaChannelOfTexture);
		target.X += sourceRects[indices[i]].getWidth();
		target.X += kerningWidth;
	}
}
예제 #8
0
// ----------------------------------------------------------------------------
void draw2DImage(const video::ITexture* texture,
                 const core::rect<float>& destRect,
                 const core::rect<s32>& sourceRect,
                 const core::rect<s32>* clip_rect,
                 const video::SColor &colors,
                 bool use_alpha_channel_of_texture)
{
    if (!CVS->isGLSL())
    {
        core::rect<irr::s32> dest_rect
            (irr::s32(destRect.UpperLeftCorner.X),
            irr::s32(destRect.UpperLeftCorner.Y),
            irr::s32(destRect.LowerRightCorner.X),
            irr::s32(destRect.LowerRightCorner.Y));

        video::SColor duplicatedArray[4] = { colors, colors, colors, colors };
        draw2DImage(texture, dest_rect, sourceRect, clip_rect, duplicatedArray,
                    use_alpha_channel_of_texture);
        return;
    }

    float width, height, center_pos_x, center_pos_y;
    float tex_width, tex_height, tex_center_pos_x, tex_center_pos_y;

    getSize(texture->getSize().Width, texture->getSize().Height,
            texture->isRenderTarget(), destRect, sourceRect, width, height,
            center_pos_x, center_pos_y, tex_width, tex_height,
            tex_center_pos_x, tex_center_pos_y);

    if (use_alpha_channel_of_texture)
    {
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }
    else
    {
        glDisable(GL_BLEND);
    }

    if (clip_rect)
    {
        if (!clip_rect->isValid())
            return;

        glEnable(GL_SCISSOR_TEST);
        const core::dimension2d<u32>& render_target_size = 
                           irr_driver->getActualScreenSize();
        glScissor(clip_rect->UpperLeftCorner.X,
                  render_target_size.Height - clip_rect->LowerRightCorner.Y,
                  clip_rect->getWidth(), clip_rect->getHeight());
    }

    UniformColoredTextureRectShader::getInstance()->use();
    glBindVertexArray(SharedGPUObjects::getUI_VAO());
    UniformColoredTextureRectShader::getInstance()
        ->setTextureUnits(texture->getOpenGLTextureName());

    UniformColoredTextureRectShader::getInstance()
        ->setUniforms(core::vector2df(center_pos_x, center_pos_y),
                      core::vector2df(width, height),
                      core::vector2df(tex_center_pos_x, tex_center_pos_y),
                      core::vector2df(tex_width, tex_height),
                      colors);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    if (clip_rect)
        glDisable(GL_SCISSOR_TEST);
    glUseProgram(0);

    glGetError();
}   // draw2DImage
예제 #9
0
// ----------------------------------------------------------------------------
void FontWithFace::render(const core::stringw& text,
                          const core::rect<s32>& position,
                          const video::SColor& color, bool hcenter,
                          bool vcenter, const core::rect<s32>* clip,
                          FontSettings* font_settings,
                          FontCharCollector* char_collector)
{
    const bool is_bold_face = dynamic_cast<BoldFace*>(this);
    const bool black_border = font_settings ?
        font_settings->useBlackBorder() : false;
    const bool rtl = font_settings ? font_settings->isRTL() : false;
    const float scale = font_settings ? font_settings->getScale() : 1.0f;
    const float shadow = font_settings ? font_settings->useShadow() : false;

    if (shadow)
    {
        assert(font_settings);
        // Avoid infinite recursion
        font_settings->setShadow(false);

        core::rect<s32> shadowpos = position;
        shadowpos.LowerRightCorner.X += 2;
        shadowpos.LowerRightCorner.Y += 2;
        render(text, shadowpos, font_settings->getShadowColor(), hcenter,
            vcenter, clip, font_settings);

        // Set back
        font_settings->setShadow(true);
    }

    core::position2d<float> offset(float(position.UpperLeftCorner.X),
        float(position.UpperLeftCorner.Y));
    core::dimension2d<s32> text_dimension;

    if (rtl || hcenter || vcenter || clip)
    {
        text_dimension = getDimension(text.c_str(), font_settings);

        if (hcenter)
            offset.X += (position.getWidth() - text_dimension.Width) / 2;
        else if (rtl)
            offset.X += (position.getWidth() - text_dimension.Width);

        if (vcenter)
            offset.Y += (position.getHeight() - text_dimension.Height) / 2;
        if (clip)
        {
            core::rect<s32> clippedRect(core::position2d<s32>
                (s32(offset.X), s32(offset.Y)), text_dimension);
            clippedRect.clipAgainst(*clip);
            if (!clippedRect.isValid()) return;
        }
    }

    // Collect character locations
    const unsigned int text_size = text.size();
    core::array<s32> indices(text_size);
    core::array<core::position2d<float>> offsets(text_size);
    std::vector<bool> fallback(text_size);

    // Test again if lazy load char is needed,
    // as some text isn't drawn with getDimension
    insertCharacters(text.c_str());
    updateCharactersList();

    for (u32 i = 0; i < text_size; i++)
    {
        wchar_t c = text[i];

        if (c == L'\r' ||          // Windows breaks
            c == L'\n'    )        // Unix breaks
        {
            if (c==L'\r' && text[i+1]==L'\n')
                c = text[++i];
            offset.Y += m_font_max_height * scale;
            offset.X  = position.UpperLeftCorner.X;
            if (hcenter)
                offset.X += (position.getWidth() - text_dimension.Width) >> 1;
            continue;
        }   // if lineBreak

        bool use_fallback_font = false;
        const FontArea &area   = getAreaFromCharacter(c, &use_fallback_font);
        fallback[i]            = use_fallback_font;
        if (char_collector == NULL)
        {
            float glyph_offset_x = area.bearing_x *
                (fallback[i] ? m_fallback_font_scale : scale);
            float glyph_offset_y = area.offset_y *
                (fallback[i] ? m_fallback_font_scale : scale);
            offset.X += glyph_offset_x;
            offset.Y += glyph_offset_y;
            offsets.push_back(offset);
            offset.X -= glyph_offset_x;
            offset.Y -= glyph_offset_y;
        }
        else
        {
            // Prevent overwriting texture used by billboard text when
            // using lazy loading characters
            if (supportLazyLoadChar() && fallback[i])
            {
                const int cur_texno = m_fallback_font->getSpriteBank()
                    ->getSprites()[area.spriteno].Frames[0].textureNumber;
                if (cur_texno == int(m_fallback_font->getSpriteBank()
                    ->getTextureCount() - 1))
                {
                    m_fallback_font->createNewGlyphPage();
                }
            }
            else if (supportLazyLoadChar())
            {
                const int cur_texno = m_spritebank
                    ->getSprites()[area.spriteno].Frames[0].textureNumber;
                if (cur_texno == int(m_spritebank->getTextureCount() - 1))
                {
                    createNewGlyphPage();
                }
            }

            // Billboard text specific, use offset_y_bt instead
            float glyph_offset_x = area.bearing_x *
                (fallback[i] ? m_fallback_font_scale : scale);
            float glyph_offset_y = area.offset_y_bt *
                (fallback[i] ? m_fallback_font_scale : scale);
            offset.X += glyph_offset_x;
            offset.Y += glyph_offset_y;
            offsets.push_back(offset);
            offset.X -= glyph_offset_x;
            offset.Y -= glyph_offset_y;
        }

        indices.push_back(area.spriteno);
        offset.X += getCharWidth(area, fallback[i], scale);
    }   // for i < text_size

    // Do the actual rendering
    const int indice_amount                 = indices.size();
    core::array<gui::SGUISprite>& sprites   = m_spritebank->getSprites();
    core::array<core::rect<s32>>& positions = m_spritebank->getPositions();
    core::array<gui::SGUISprite>* fallback_sprites;
    core::array<core::rect<s32>>* fallback_positions;
    if (m_fallback_font != NULL)
    {
        fallback_sprites   = &m_fallback_font->m_spritebank->getSprites();
        fallback_positions = &m_fallback_font->m_spritebank->getPositions();
    }
    else
    {
        fallback_sprites   = NULL;
        fallback_positions = NULL;
    }

    const int sprite_amount = sprites.size();

    if ((black_border || is_bold_face) && char_collector == NULL)
    {
        // Draw black border first, to make it behind the real character
        // which make script language display better
        video::SColor black(color.getAlpha(),0,0,0);
        for (int n = 0; n < indice_amount; n++)
        {
            const int sprite_id = indices[n];
            if (!fallback[n] && (sprite_id < 0 || sprite_id >= sprite_amount))
                continue;
            if (indices[n] == -1) continue;

            const int tex_id = (fallback[n] ?
                (*fallback_sprites)[sprite_id].Frames[0].textureNumber :
                sprites[sprite_id].Frames[0].textureNumber);

            core::rect<s32> source = (fallback[n] ? (*fallback_positions)
                [(*fallback_sprites)[sprite_id].Frames[0].rectNumber] :
                positions[sprites[sprite_id].Frames[0].rectNumber]);

            core::dimension2d<float> size(0.0f, 0.0f);

            float cur_scale = (fallback[n] ? m_fallback_font_scale : scale);
            size.Width  = source.getSize().Width  * cur_scale;
            size.Height = source.getSize().Height * cur_scale;

            core::rect<float> dest(offsets[n], size);

            video::ITexture* texture = (fallback[n] ?
                m_fallback_font->m_spritebank->getTexture(tex_id) :
                m_spritebank->getTexture(tex_id));

            for (int x_delta = -2; x_delta <= 2; x_delta++)
            {
                for (int y_delta = -2; y_delta <= 2; y_delta++)
                {
                    if (x_delta == 0 || y_delta == 0) continue;
                    draw2DImage(texture, dest + core::position2d<float>
                        (float(x_delta), float(y_delta)), source, clip,
                        black, true);
                }
            }
        }
    }

    for (int n = 0; n < indice_amount; n++)
    {
        const int sprite_id = indices[n];
        if (!fallback[n] && (sprite_id < 0 || sprite_id >= sprite_amount))
            continue;
        if (indices[n] == -1) continue;

        const int tex_id = (fallback[n] ?
            (*fallback_sprites)[sprite_id].Frames[0].textureNumber :
            sprites[sprite_id].Frames[0].textureNumber);

        core::rect<s32> source = (fallback[n] ?
            (*fallback_positions)[(*fallback_sprites)[sprite_id].Frames[0]
            .rectNumber] : positions[sprites[sprite_id].Frames[0].rectNumber]);

        core::dimension2d<float> size(0.0f, 0.0f);

        float cur_scale = (fallback[n] ? m_fallback_font_scale : scale);
        size.Width  = source.getSize().Width  * cur_scale;
        size.Height = source.getSize().Height * cur_scale;

        core::rect<float> dest(offsets[n], size);

        video::ITexture* texture = (fallback[n] ?
            m_fallback_font->m_spritebank->getTexture(tex_id) :
            m_spritebank->getTexture(tex_id));

        if (fallback[n] || is_bold_face)
        {
            video::SColor top = GUIEngine::getSkin()->getColor("font::top");
            video::SColor bottom = GUIEngine::getSkin()
                ->getColor("font::bottom");
            top.setAlpha(color.getAlpha());
            bottom.setAlpha(color.getAlpha());

            video::SColor title_colors[] = {top, bottom, top, bottom};
            if (char_collector != NULL)
            {
                char_collector->collectChar(texture, dest, source,
                    title_colors);
            }
            else
            {
                draw2DImage(texture, dest, source, clip, title_colors, true);
            }
        }
        else
        {
            if (char_collector != NULL)
            {
                video::SColor colors[] = {color, color, color, color};
                char_collector->collectChar(texture, dest, source, colors);
            }
            else
            {
                draw2DImage(texture, dest, source, clip, color, true);
            }
        }
    }
}   // render
예제 #10
0
/** Draws the plunger-in-face if necessary. Does nothing if there is no
 *  plunger in face atm.
 */
void RaceGUIBase::drawPlungerInFace(const Camera *camera, float dt)
{
    const AbstractKart *kart = camera->getKart();
    if (kart->getBlockedByPlungerTime()<=0)
    {
        m_plunger_state = PLUNGER_STATE_INIT;
        return;
    }

    const core::recti &viewport = camera->getViewport();

    const int screen_width = viewport.LowerRightCorner.X
                           - viewport.UpperLeftCorner.X;

    if(m_plunger_state == PLUNGER_STATE_INIT)
    {
        m_plunger_move_time = 0.0f;
        m_plunger_offset    = core::vector2di(0,0);
        m_plunger_state     = PLUNGER_STATE_SLOW_2;
        m_plunger_speed     = core::vector2df(0, 0);
    }

    if(World::getWorld()->getPhase()!=World::IN_GAME_MENU_PHASE)
    {
        m_plunger_move_time -= dt;
        if(m_plunger_move_time < dt && m_plunger_state!=PLUNGER_STATE_FAST)
        {
            const float fast_time = 0.3f;
            if(kart->getBlockedByPlungerTime()<fast_time)
            {
                // First time we reach faste state: select random target point
                // at top of screen and set speed accordingly
                RandomGenerator random;
                float movement_fraction = 0.3f;
                int plunger_x_target  = screen_width/2
                    + random.get((int)(screen_width*movement_fraction))
                    - (int)(screen_width*movement_fraction*0.5f);
                m_plunger_state = PLUNGER_STATE_FAST;
                m_plunger_speed =
                    core::vector2df((plunger_x_target-screen_width/2)/fast_time,
                    viewport.getHeight()*0.5f/fast_time);
                m_plunger_move_time = fast_time;
            }
            else
            {
                RandomGenerator random;
                m_plunger_move_time = 0.1f+random.get(50)/200.0f;
                // Plunger is either moving or not moving
                if(m_plunger_state==PLUNGER_STATE_SLOW_1)
                {
                    m_plunger_state = PLUNGER_STATE_SLOW_2;
                    m_plunger_speed =
                        core::vector2df(0, 0.05f*viewport.getHeight()
                        /m_plunger_move_time      );
                }
                else
                {
                    m_plunger_state = PLUNGER_STATE_SLOW_1;
                    m_plunger_speed =
                        core::vector2df(0, 0.02f*viewport.getHeight()
                        /m_plunger_move_time      );
                }
            }   // has not reach fast moving state
        }

        m_plunger_offset.X += (int)(m_plunger_speed.X * dt);
        m_plunger_offset.Y += (int)(m_plunger_speed.Y * dt);
    }

    const int plunger_size = (int)(0.6f * screen_width);
    int offset_y = viewport.UpperLeftCorner.Y + viewport.getHeight()/2
                 - plunger_size/2 - m_plunger_offset.Y;

    int plunger_x = viewport.UpperLeftCorner.X + screen_width/2
                  - plunger_size/2;

    video::ITexture *t=m_plunger_face->getTexture();
    plunger_x += (int)m_plunger_offset.X;
    core::rect<s32> dest(plunger_x,              offset_y,
                         plunger_x+plunger_size, offset_y+plunger_size);

    const core::rect<s32> source(core::position2d<s32>(0,0),
                                 t->getOriginalSize());

    draw2DImage(t, dest, source,
                                              &viewport /* clip */,
                                              NULL /* color */,
                                              true /* alpha */     );
}   // drawPlungerInFace
예제 #11
0
/** Draw players icons and their times (if defined in the current mode).
 *  Also takes care of icon looking different due to plumber, squashing, ...
 */
void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin)
{
    // For now, don't draw player icons when in soccer mode
    const RaceManager::MinorRaceModeType  minor_mode = race_manager->getMinorMode();
    if(minor_mode == RaceManager::MINOR_MODE_SOCCER)
        return;

    int x_base = 10;
    int y_base = 20;
    unsigned int y_space = UserConfigParams::m_height - bottom_margin - y_base;
    // Special case : when 3 players play, use 4th window to display such stuff
    if (race_manager->getNumLocalPlayers() == 3)
    {
        x_base = UserConfigParams::m_width/2 + x_base;
        y_base = UserConfigParams::m_height/2 + y_base;
        y_space = UserConfigParams::m_height - y_base;
    }

    // -2 because that's the spacing further on
    int ICON_PLAYER_WIDTH = y_space / race_manager->getNumberOfKarts() - 2;

    int icon_width_max = (int)(50*(UserConfigParams::m_width/800.0f));
    int icon_width_min = (int)(35*(UserConfigParams::m_height/600.0f));
    if (icon_width_min > icon_width_max)
    {
        int icon_width_tmp = icon_width_max;
        icon_width_max = icon_width_min;
        icon_width_min = icon_width_tmp;
    }

    // Make sure it fits within our boundaries
    if (ICON_PLAYER_WIDTH > icon_width_max) ICON_PLAYER_WIDTH = icon_width_max;
    if (ICON_PLAYER_WIDTH < icon_width_min) ICON_PLAYER_WIDTH = icon_width_min;

    // TODO: Is this absolute treshold necessary?
    if(UserConfigParams::m_height<600)
    {
        ICON_PLAYER_WIDTH = 35;
    }

    // Icon width for the AI karts
    int ICON_WIDTH = ICON_PLAYER_WIDTH * 4 / 5;

    WorldWithRank *world    = (WorldWithRank*)(World::getWorld());
    //initialize m_previous_icons_position
    if(m_previous_icons_position.size()==0)
    {
        for(unsigned int i=0; i<race_manager->getNumberOfKarts(); i++)
        {
            const AbstractKart *kart = world->getKart(i);
            int position = kart->getPosition();
            core::vector2d<s32> pos(x_base,y_base+(position-1)*(ICON_PLAYER_WIDTH+2));
            m_previous_icons_position.push_back(pos);
        }
    }

    int x;
    int y;
    float previous_distance=0.0;//no need to be far ahead, first kart won't try to overlap



    int previous_x=x_base;
    int previous_y=y_base-ICON_PLAYER_WIDTH-2;

    gui::ScalableFont* font = GUIEngine::getFont();
    const unsigned int kart_amount = world->getNumKarts();

    //where is the limit to hide last icons
    int y_icons_limit=UserConfigParams::m_height-bottom_margin-ICON_PLAYER_WIDTH;
    if (race_manager->getNumLocalPlayers() == 3)
        y_icons_limit=UserConfigParams::m_height-ICON_WIDTH;

    world->getKartsDisplayInfo(&m_kart_display_infos);

    for(int position = 1; position <= (int)kart_amount ; position++)
    {
        AbstractKart *kart = world->getKartAtPosition(position);

        if (kart->getPosition() == -1)//if position is not set
        {
            //we use karts ordered by id only
            //(needed for beginning of MINOR_MODE_3_STRIKES)
            kart= world->getKart(position-1);
        }

        if(kart->isEliminated()) continue;
        unsigned int kart_id = kart->getWorldKartId();

        KartIconDisplayInfo &info = m_kart_display_infos[kart_id];
        //x,y is the target position
        int lap = info.lap;

        // In battle mode mode there is no distance along track etc.
        if( minor_mode==RaceManager::MINOR_MODE_3_STRIKES ||
            minor_mode==RaceManager::MINOR_MODE_EASTER_EGG)
        {
            x = x_base;
            y = previous_y+ICON_PLAYER_WIDTH+2;
        }
        else
        {
            LinearWorld *linear_world = (LinearWorld*)(World::getWorld());

            float distance = linear_world->getDistanceDownTrackForKart(kart_id)
                           + linear_world->getTrack()->getTrackLength()*lap;
            if ((position>1) &&
                (previous_distance-distance<m_dist_show_overlap) &&
                (!kart->hasFinishedRace())                          )
            {
                //linear translation : form (0,ICON_PLAYER_WIDTH+2) to
                // (previous_x-x_base+(ICON_PLAYER_WIDTH+2)/2,0)
                x=(int)(x_base+(1-(previous_distance-distance)
                                /m_dist_show_overlap)
                        *(previous_x-x_base+(ICON_PLAYER_WIDTH+2)/2));
                y=(int)(previous_y+(previous_distance-distance)
                        /m_dist_show_overlap*(ICON_PLAYER_WIDTH+2));
            }
            else
            {
                x=x_base;
                y=previous_y+ICON_PLAYER_WIDTH+2;
            }
            previous_distance=distance;
        }   // not three-strike-battle


        previous_x=x;//save coord of the previous kart in list
        previous_y=y;

        //soft movement using previous position:
        x=(int)((x+m_previous_icons_position[kart_id].X*m_icons_inertia)
                /(m_icons_inertia+1));
        y=(int)((y+m_previous_icons_position[kart_id].Y*m_icons_inertia)
                /(m_icons_inertia+1));

        //save position for next time
        m_previous_icons_position[kart_id].X=x;
        m_previous_icons_position[kart_id].Y=y;

        if (y>y_icons_limit)
        {
            //there are too many icons, write "Top 9", to express that
            //there is not everybody shown
            core::recti pos_top;
            pos_top.UpperLeftCorner.Y  = y_base-22;
            pos_top.UpperLeftCorner.X  = x_base;

            static video::SColor color = video::SColor(255, 255, 255, 255);
            pos_top.LowerRightCorner   = pos_top.UpperLeftCorner;

            font->draw(StringUtils::insertValues( m_string_top, position-1 ), pos_top, color);

            break;
        }

        if (m_kart_display_infos[kart_id].m_text.size() > 0)
        {
            core::rect<s32> pos(x+ICON_PLAYER_WIDTH, y+5,
                                x+ICON_PLAYER_WIDTH, y+5);
            core::stringw s=info.m_text.c_str();

            font->draw(s.c_str(), pos, info.m_color, false, false, NULL,
                       true /* ignore RTL */);
        }

        if (info.special_title.size() > 0)
        {
            core::rect<s32> pos(x+ICON_PLAYER_WIDTH, y+5,
                                x+ICON_PLAYER_WIDTH, y+5);
            core::stringw s(info.special_title.c_str());
            font->draw(s.c_str(), pos, info.m_color, false, false, NULL,
                       true /* ignore RTL */);
        }

        // draw icon
        video::ITexture *icon =
        kart->getKartProperties()->getIconMaterial()->getTexture();
        int w =
        kart->getController()->isPlayerController() ? ICON_PLAYER_WIDTH
        : ICON_WIDTH;
        const core::rect<s32> pos(x, y, x+w, y+w);

        //to bring to light the player's icon: add a background
        if (kart->getController()->isPlayerController())
        {
            video::SColor colors[4];
            for (unsigned int i=0;i<4;i++)
            {
                colors[i]=kart->getKartProperties()->getColor();
                colors[i].setAlpha(
                                   100+(int)(100*cos(M_PI/2*i+World::getWorld()->getTime()*2)));
            }
            const core::rect<s32> rect(core::position2d<s32>(0,0),
                                       m_icons_frame->getTexture()->getOriginalSize());
            draw2DImage(
                                                      m_icons_frame->getTexture(), pos, rect,NULL, colors, true);
        }

        // Fixes crash bug, why are certain icons not showing up?
        if (icon  && !kart->getKartAnimation() && !kart->isSquashed())
        {
            const core::rect<s32> rect(core::position2d<s32>(0,0),
                                       icon->getOriginalSize());
            draw2DImage(icon, pos, rect,
                                                      NULL, NULL, true);
        }

        //draw status info - icon fade out in case of rescue/explode

        if (icon  && dynamic_cast<RescueAnimation*>(kart->getKartAnimation()))
        {
            //icon fades to the left
            float t = kart->getKartAnimation()->getAnimationTimer();
            float t_anim=100*sin(0.5f*M_PI*t);
            const core::rect<s32> rect1(core::position2d<s32>(0,0),
                                        icon->getOriginalSize());
            const core::rect<s32> pos1((int)(x-t_anim), y,
                                       (int)(x+w-t_anim), y+w);
            draw2DImage(icon, pos1, rect1,
                                                      NULL, NULL, true);
        }

        if (icon  && !kart->getKartAnimation() && kart->isSquashed() )
        {
            //syncs icon squash with kart squash
            const core::rect<s32> destRect(core::position2d<s32>(x,y+w/4),
                                           core::position2d<s32>(x+w,y+w*3/4));
            const core::rect<s32> sourceRect(core::position2d<s32>(0,0),
                                             icon->getOriginalSize());
            draw2DImage(icon, destRect,
                                                      sourceRect, NULL, NULL,
                                                      true);
        }

        if (icon  &&
            dynamic_cast<ExplosionAnimation*>(kart->getKartAnimation()) )
        {
            //exploses into 4 parts
            float t = kart->getKartAnimation()->getAnimationTimer();
            float t_anim=50.0f*sin(0.5f*M_PI*t);
            u16 icon_size_x=icon->getOriginalSize().Width;
            u16 icon_size_y=icon->getOriginalSize().Height;

            const core::rect<s32> rect1(0, 0, icon_size_x/2,icon_size_y/2);
            const core::rect<s32> pos1((int)(x-t_anim), (int)(y-t_anim),
                                       (int)(x+w/2-t_anim),
                                       (int)(y+w/2-t_anim));
            draw2DImage(icon, pos1, rect1,
                                                      NULL, NULL, true);

            const core::rect<s32> rect2(icon_size_x/2,0,
                                        icon_size_x,icon_size_y/2);
            const core::rect<s32> pos2((int)(x+w/2+t_anim),
                                       (int)(y-t_anim),
                                       (int)(x+w+t_anim),
                                       (int)(y+w/2-t_anim));
            draw2DImage(icon, pos2, rect2,
                                                      NULL, NULL, true);

            const core::rect<s32> rect3(0, icon_size_y/2, icon_size_x/2,icon_size_y);
            const core::rect<s32> pos3((int)(x-t_anim), (int)(y+w/2+t_anim),
                                       (int)(x+w/2-t_anim), (int)(y+w+t_anim));
            draw2DImage(icon, pos3, rect3, NULL, NULL, true);

            const core::rect<s32> rect4(icon_size_x/2,icon_size_y/2,icon_size_x,icon_size_y);
            const core::rect<s32> pos4((int)(x+w/2+t_anim), (int)(y+w/2+t_anim),
                                       (int)(x+w+t_anim), (int)(y+w+t_anim));
            draw2DImage(icon, pos4, rect4, NULL, NULL, true);
        }

        //Plunger
        if (kart->getBlockedByPlungerTime()>0)
        {
            video::ITexture *icon_plunger =
            powerup_manager->getIcon(PowerupManager::POWERUP_PLUNGER)->getTexture();
            if (icon_plunger != NULL)
            {
                const core::rect<s32> rect(core::position2d<s32>(0,0),
                                           icon_plunger->getOriginalSize());
                const core::rect<s32> pos1(x+10, y-10, x+w+10, y+w-10);
                draw2DImage(icon_plunger, pos1,
                                                          rect, NULL, NULL,
                                                          true);
            }
        }
        //attachment
        if (kart->getAttachment()->getType() != Attachment::ATTACH_NOTHING)
        {
            video::ITexture *icon_attachment =
            attachment_manager->getIcon(kart->getAttachment()->getType())
            ->getTexture();
            if (icon_attachment != NULL)
            {
                const core::rect<s32> rect(core::position2d<s32>(0,0),
                                           icon_attachment->getOriginalSize());
                const core::rect<s32> pos1(x-20, y-10, x+w-20, y+w-10);
                draw2DImage(icon_attachment,
                                                          pos1, rect, NULL,
                                                          NULL, true);
            }
        }

    } //next position
}   // drawGlobalPlayerIcons
예제 #12
0
/** Displays the description given for the music currently being played.
 *  This is usually the title and composer.
 */
void RaceGUIBase::drawGlobalMusicDescription()
{
     // show no music description when it's off
    if (!UserConfigParams::m_music) return;

    gui::IGUIFont*       font = GUIEngine::getFont();

    float race_time = World::getWorld()->getTime();
    // In follow the leader the clock counts backwards, so convert the
    // countdown time to time since start:
    if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER)
        race_time = ((FollowTheLeaderRace*)World::getWorld())->getClockStartTime()
                  - race_time;
    // ---- Manage pulsing effect
    // 3.0 is the duration of ready/set (TODO: don't hardcode)
    float timeProgression = (float)(race_time) /
                            (float)(stk_config->m_music_credit_time - 2.0f);

    const int x_pulse = (int)(sin(race_time*9.0f)*10.0f);
    const int y_pulse = (int)(cos(race_time*9.0f)*10.0f);

    float resize = 1.0f;
    if (timeProgression < 0.1)
    {
        resize = timeProgression/0.1f;
    }
    else if (timeProgression > 0.9)
    {
        resize = 1.0f - (timeProgression - 0.9f)/0.1f;
    }

    const float resize3 = resize*resize*resize;

    // Get song name, and calculate its size, allowing us to position stuff
    const MusicInformation* mi = music_manager->getCurrentMusic();
    if (!mi) return;

    core::stringw thetext = core::stringw(L"\"") + mi->getTitle() + L"\"";

    core::dimension2d< u32 > textSize = font->getDimension(thetext.c_str());
    int textWidth = textSize.Width;

    int textWidth2 = 0;
    core::stringw thetext_composer;
    if (mi->getComposer()!="")
    {
        // I18N: string used to show the author of the music. (e.g. "Sunny Song" by "John Doe")
        thetext_composer = _("by");
        thetext_composer += " ";
        thetext_composer += mi->getComposer().c_str();
        textWidth2 = font->getDimension(thetext_composer.c_str()).Width;
    }
    const int max_text_size = (int)(UserConfigParams::m_width*2.0f/3.0f);
    if (textWidth  > max_text_size) textWidth  = max_text_size;
    if (textWidth2 > max_text_size) textWidth2 = max_text_size;

    const int ICON_SIZE = 64;
    const int y         = UserConfigParams::m_height - 80;
    // the 20 is an arbitrary space left between the note icon and the text
    const int noteX     = (UserConfigParams::m_width / 2)
                        - std::max(textWidth, textWidth2)/2 - ICON_SIZE/2 - 20;
    const int noteY     = y;
    // the 20 is an arbitrary space left between the note icon and the text
    const int textXFrom = (UserConfigParams::m_width / 2)
                        - std::max(textWidth, textWidth2)/2 + 20;
    const int textXTo   = (UserConfigParams::m_width / 2)
                        + std::max(textWidth, textWidth2)/2 + 20;

    // ---- Draw "by" text
    const int text_y = (int)(UserConfigParams::m_height - 80*(resize3)
                     + 40*(1-resize));

    static const video::SColor white = video::SColor(255, 255, 255, 255);
    if(mi->getComposer()!="")
    {
        core::rect<s32> pos_by(textXFrom, text_y+40,
                               textXTo,   text_y+40);
        font->draw(thetext_composer, pos_by, white,
                   true, true);
    }

    // ---- Draw "song name" text
    core::rect<s32> pos(textXFrom, text_y,
                        textXTo,   text_y);

    font->draw(thetext.c_str(), pos, white, true /* hcenter */,
               true /* vcenter */);

    // Draw music icon
    int iconSizeX = (int)(ICON_SIZE*resize + x_pulse*resize*resize);
    int iconSizeY = (int)(ICON_SIZE*resize + y_pulse*resize*resize);

    video::ITexture *t = m_music_icon->getTexture();
    core::rect<s32> dest(noteX-iconSizeX/2+20,
                         noteY-iconSizeY/2+ICON_SIZE/2,
                         noteX+iconSizeX/2+20,
                         noteY+iconSizeY/2+ICON_SIZE/2);
    const core::rect<s32> source(core::position2d<s32>(0,0),
                                 t->getOriginalSize());

    draw2DImage(t, dest, source,
                                              NULL, NULL, true);
}   // drawGlobalMusicDescription
예제 #13
0
//! draws some text and clips it to the specified rectangle if wanted
void ScalableFont::doDraw(const core::stringw& text,
                          const core::rect<s32>& position, video::SColor color,
                          bool hcenter, bool vcenter,
                          const core::rect<s32>* clip,
                          FontCharCollector* charCollector)
{
    if (!Driver) return;

    if (m_shadow)
    {
        m_shadow = false; // avoid infinite recursion

        core::rect<s32> shadowpos = position;
        shadowpos.LowerRightCorner.X += 2;
        shadowpos.LowerRightCorner.Y += 2;

        draw(text, shadowpos, m_shadow_color, hcenter, vcenter, clip);

        m_shadow = true; // set back
    }

    core::position2d<s32> offset = position.UpperLeftCorner;
    core::dimension2d<s32> text_dimension;

    if (m_rtl || hcenter || vcenter || clip)
    {
        text_dimension = getDimension(text.c_str());

        if (hcenter)    offset.X += (position.getWidth() - text_dimension.Width) / 2;
        else if (m_rtl) offset.X += (position.getWidth() - text_dimension.Width);

        if (vcenter)    offset.Y += (position.getHeight() - text_dimension.Height) / 2;
        if (clip)
        {
            core::rect<s32> clippedRect(offset, text_dimension);
            clippedRect.clipAgainst(*clip);
            if (!clippedRect.isValid()) return;
        }
    }

    // ---- collect character locations
    const unsigned int text_size = text.size();
    core::array<s32>               indices(text_size);
    core::array<core::position2di> offsets(text_size);
    std::vector<bool>              fallback(text_size);

    for (u32 i = 0; i<text_size; i++)
    {
        wchar_t c = text[i];

        if (c == L'\r' ||          // Windows breaks
            c == L'\n'    )        // Unix breaks
        {
            if(c==L'\r' && text[i+1]==L'\n') c = text[++i];
            offset.Y += (int)(MaxHeight*m_scale);
            offset.X  = position.UpperLeftCorner.X;
            if (hcenter)
                offset.X += (position.getWidth() - text_dimension.Width) >> 1;
            continue;
        }   // if lineBreak

        bool use_fallback_font = false;
        const SFontArea &area  = getAreaFromCharacter(c, &use_fallback_font);
        fallback[i]            = use_fallback_font;
        offset.X              += area.underhang;
        offsets.push_back(offset);
        // Invisible character. add something to the array anyway so that
        // indices from the various arrays remain in sync
        indices.push_back( Invisible.findFirst(c) < 0  ? area.spriteno
                                                       : -1            );
        offset.X += getCharWidth(area, fallback[i]);
    }   // for i<text_size

    // ---- do the actual rendering
    const int indiceAmount                    = indices.size();
    core::array< SGUISprite >& sprites        = SpriteBank->getSprites();
    core::array< core::rect<s32> >& positions = SpriteBank->getPositions();
    core::array< SGUISprite >* fallback_sprites;
    core::array< core::rect<s32> >* fallback_positions;
    if(m_fallback_font!=NULL)
    {
        fallback_sprites   = &m_fallback_font->SpriteBank->getSprites();
        fallback_positions = &m_fallback_font->SpriteBank->getPositions();
    }
    else
    {
        fallback_sprites   = NULL;
        fallback_positions = NULL;
    }

    const int spriteAmount      = sprites.size();
    for (int n=0; n<indiceAmount; n++)
    {
        const int spriteID = indices[n];
        if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue;
        if (indices[n] == -1) continue;

        //assert(sprites[spriteID].Frames.size() > 0);

        const int texID = (fallback[n] ?
                           (*fallback_sprites)[spriteID].Frames[0].textureNumber :
                           sprites[spriteID].Frames[0].textureNumber);

        core::rect<s32> source = (fallback[n] ?
                                  (*fallback_positions)[(*fallback_sprites)[spriteID].Frames[0].rectNumber] :
                                  positions[sprites[spriteID].Frames[0].rectNumber]);

        const TextureInfo& info = (fallback[n] ?
                                   (*(m_fallback_font->m_texture_files.find(texID))).second :
                                   (*(m_texture_files.find(texID))).second
                                   );
        float char_scale = info.m_scale;

        core::dimension2d<s32> size = source.getSize();

        float scale = (fallback[n] ? m_scale*m_fallback_font_scale : m_scale);
        size.Width  = (int)(size.Width  * scale * char_scale);
        size.Height = (int)(size.Height * scale * char_scale);

        // align vertically if character is smaller
        int y_shift = (size.Height < MaxHeight*m_scale ? (int)((MaxHeight*m_scale - size.Height)/2.0f) : 0);

        core::rect<s32> dest(offsets[n] + core::position2di(0, y_shift), size);

        video::ITexture* texture = (fallback[n] ?
                                    m_fallback_font->SpriteBank->getTexture(texID) :
                                    SpriteBank->getTexture(texID) );

        /*
        if (fallback[n])
        {
            Log::info("ScalableFont", "Using fallback font %s; source area is %d, %d; size %d, %d; dest = %d, %d",
                core::stringc(texture->getName()).c_str(), source.UpperLeftCorner.X, source.UpperLeftCorner.Y,
                source.getWidth(), source.getHeight(), offsets[n].X, offsets[n].Y);
        }
        */

        if (texture == NULL)
        {
            // perform lazy loading

            if (fallback[n])
            {
                m_fallback_font->lazyLoadTexture(texID);
                texture = m_fallback_font->SpriteBank->getTexture(texID);
            }
            else
            {
                lazyLoadTexture(texID);
                texture = SpriteBank->getTexture(texID);
            }

            if (texture == NULL)
            {
                Log::warn("ScalableFont", "Character not found in current font");
                continue; // no such character
            }
        }

        if (m_black_border && charCollector == NULL)
        {
            // draw black border
            video::SColor black(color.getAlpha(),0,0,0);

            for (int x_delta=-2; x_delta<=2; x_delta++)
            {
                for (int y_delta=-2; y_delta<=2; y_delta++)
                {
                    if (x_delta == 0 || y_delta == 0) continue;
                    draw2DImage(texture,
                                dest + core::position2d<s32>(x_delta, y_delta),
                                source,
                                clip,
                                black, true);
                }
            }
        }

        if (fallback[n])
        {
            // TODO: don't hardcode colors?
            video::SColor orange(color.getAlpha(), 255, 100, 0);
            video::SColor yellow(color.getAlpha(), 255, 220, 15);
            video::SColor title_colors[] = {orange, yellow, orange, yellow};

            if (charCollector != NULL)
            {
                charCollector->collectChar(texture,
                    dest,
                    source,
                    title_colors);
            }
            else
            {
                draw2DImage(texture,
                    dest,
                    source,
                    clip,
                    title_colors, true);
            }
        }
        else
        {
            if (charCollector != NULL)
            {
                video::SColor colors[] = { color, color, color, color };
                charCollector->collectChar(texture,
                    dest,
                    source,
                    colors);
            }
            else
            {
                draw2DImage(texture,
                    dest,
                    source,
                    clip,
                    color, true);
            }
#ifdef FONT_DEBUG
            video::IVideoDriver* driver = GUIEngine::getDriver();
            driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X,  dest.UpperLeftCorner.Y),
                               core::position2d<s32>(dest.UpperLeftCorner.X,  dest.LowerRightCorner.Y),
                               video::SColor(255, 255,0,0));
            driver->draw2DLine(core::position2d<s32>(dest.LowerRightCorner.X, dest.LowerRightCorner.Y),
                               core::position2d<s32>(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y),
                               video::SColor(255, 255,0,0));
            driver->draw2DLine(core::position2d<s32>(dest.LowerRightCorner.X, dest.LowerRightCorner.Y),
                               core::position2d<s32>(dest.UpperLeftCorner.X,  dest.LowerRightCorner.Y),
                               video::SColor(255, 255,0,0));
            driver->draw2DLine(core::position2d<s32>(dest.UpperLeftCorner.X,  dest.UpperLeftCorner.Y),
                               core::position2d<s32>(dest.LowerRightCorner.X, dest.UpperLeftCorner.Y),
                               video::SColor(255, 255,0,0));
#endif
        }
    }
}
예제 #14
0
//-----------------------------------------------------------------------------
void RaceResultGUI::displaySoccerResults()
{

    //Draw win text
    core::stringw resultText;
    static video::SColor color = video::SColor(255, 255, 255, 255);
    gui::IGUIFont* font = GUIEngine::getTitleFont();
    int currX = UserConfigParams::m_width/2;
    RowInfo *ri = &(m_all_row_infos[0]);
    int currY = (int)ri->m_y_pos; 
    SoccerWorld* soccerWorld = (SoccerWorld*)World::getWorld();
    int teamScore[2] = {soccerWorld->getScore(0), soccerWorld->getScore(1)};
    
    GUIEngine::Widget *table_area = getWidget("result-table");
    int height = table_area->m_h + table_area->m_y;

    if(teamScore[0] > teamScore[1])
    {
        resultText = _("Red Team Wins");
    }
    else if(teamScore[1] > teamScore[0])
    {
        resultText = _("Blue Team Wins");
    }
    else
    {
        //Cannot really happen now. Only in time limited matches.
        resultText = _("It's a draw");
    }
    core::rect<s32> pos(currX, currY, currX, currY);
    font->draw(resultText.c_str(), pos, color, true, true);
    
    core::dimension2du rect = m_font->getDimension(resultText.c_str());

    //Draw team scores:
    currY += rect.Height;
    currX /= 2;
    irr::video::ITexture* redTeamIcon = irr_driver->getTexture(FileManager::GUI,
                                                              "soccer_ball_red.png");
    irr::video::ITexture* blueTeamIcon = irr_driver->getTexture(FileManager::GUI,
                                                               "soccer_ball_blue.png");

    core::recti sourceRect(core::vector2di(0,0), redTeamIcon->getSize());
    core::recti destRect(currX, currY, currX+redTeamIcon->getSize().Width/2,
        currY+redTeamIcon->getSize().Height/2);
    draw2DImage(redTeamIcon, destRect,sourceRect,
        NULL,NULL, true);
    currX += UserConfigParams::m_width/2 - redTeamIcon->getSize().Width/2;
    destRect = core::recti(currX, currY, currX+redTeamIcon->getSize().Width/2,
        currY+redTeamIcon->getSize().Height/2);
    draw2DImage(blueTeamIcon,destRect,sourceRect,
        NULL, NULL, true);
    
    resultText = StringUtils::toWString(teamScore[1]);
    rect = m_font->getDimension(resultText.c_str());
    currX += redTeamIcon->getSize().Width/4;
    currY += redTeamIcon->getSize().Height/2 + rect.Height/4;
    pos = core::rect<s32>(currX, currY, currX, currY);
    color = video::SColor(255,255,255,255);
    font->draw(resultText.c_str(), pos, color, true, false);

    currX -= UserConfigParams::m_width/2 - redTeamIcon->getSize().Width/2;
    resultText = StringUtils::toWString(teamScore[0]);
    pos = core::rect<s32>(currX,currY,currX,currY);
    font->draw(resultText.c_str(), pos, color, true, false);
    
    int centerX = UserConfigParams::m_width/2;
    pos = core::rect<s32>(centerX, currY, centerX, currY);
    font->draw("-", pos, color, true, false);

    //Draw goal scorers:
    //The red scorers:
    currY += rect.Height/2 + rect.Height/4;
    font = GUIEngine::getSmallFont();
    std::vector<int> scorers = soccerWorld->getScorers(0);
    std::vector<float> scoreTimes = soccerWorld->getScoreTimes(0);
    irr::video::ITexture* scorerIcon;

    int prevY = currY;
    for(unsigned int i=0; i<scorers.size(); i++)
    {
        resultText = soccerWorld->getKart(scorers.at(i))->
            getKartProperties()->getName();
        resultText.append(" ");
        resultText.append(StringUtils::timeToString(scoreTimes.at(i)).c_str());
        rect = m_font->getDimension(resultText.c_str());

        if(height-prevY < ((short)scorers.size()+1)*(short)rect.Height)
            currY += (height-prevY)/((short)scorers.size()+1);
        else
            currY += rect.Height;

        if(currY > height) break;

        pos = core::rect<s32>(currX,currY,currX,currY);
        font->draw(resultText,pos, color, true, false);
        scorerIcon = soccerWorld->getKart(scorers.at(i))
                                ->getKartProperties()->getIconMaterial()->getTexture();
        sourceRect = core::recti(core::vector2di(0,0), scorerIcon->getSize());
        irr::u32 offsetX = GUIEngine::getFont()->getDimension(resultText.c_str()).Width/2;
        destRect = core::recti(currX-offsetX-30, currY, currX-offsetX, currY+ 30);
        draw2DImage(scorerIcon, destRect, sourceRect,
            NULL, NULL, true);
    }

    //The blue scorers:
    currY = prevY;
    currX += UserConfigParams::m_width/2 - redTeamIcon->getSize().Width/2;
    scorers = soccerWorld->getScorers(1);
    scoreTimes = soccerWorld->getScoreTimes(1);
    for(unsigned int i=0; i<scorers.size(); i++)
    {
        resultText = soccerWorld->getKart(scorers.at(i))->
            getKartProperties()->getName();
        resultText.append(" ");
        resultText.append(StringUtils::timeToString(scoreTimes.at(i)).c_str());
        rect = m_font->getDimension(resultText.c_str());
        
        if(height-prevY < ((short)scorers.size()+1)*(short)rect.Height)
            currY += (height-prevY)/((short)scorers.size()+1);
        else
            currY += rect.Height;

        if(currY > height) break;

        pos = core::rect<s32>(currX,currY,currX,currY);
        font->draw(resultText,pos, color, true, false);
        scorerIcon = soccerWorld->getKart(scorers.at(i))->
                     getKartProperties()->getIconMaterial()->getTexture();
        sourceRect = core::recti(core::vector2di(0,0), scorerIcon->getSize());
        irr::u32 offsetX = GUIEngine::getFont()->getDimension(resultText.c_str()).Width/2;

        destRect = core::recti(currX-offsetX-30, currY, currX-offsetX, currY+ 30);
        draw2DImage(scorerIcon, destRect, sourceRect,
            NULL, NULL, true);
    }
}
예제 #15
0
/** Displays the race results for a single kart.
 *  \param n Index of the kart to be displayed.
 *  \param display_points True if GP points should be displayed, too
 */
void RaceResultGUI::displayOneEntry(unsigned int x, unsigned int y,
                                    unsigned int n, bool display_points)
{
    RowInfo *ri = &(m_all_row_infos[n]);
    video::SColor color = ri->m_is_player_kart
                        ? video::SColor(255,255,0,  0  )
                        : video::SColor(255,255,255,255);

    unsigned int current_x = x;

    // First draw the icon
    // -------------------
    if(ri->m_kart_icon)
    {
        core::recti source_rect(core::vector2di(0,0),
                                ri->m_kart_icon->getSize());
        core::recti dest_rect(current_x, y,
                                current_x+m_width_icon, y+m_width_icon);
        draw2DImage(ri->m_kart_icon, dest_rect,
                                                    source_rect, NULL, NULL,
                                                    true);
    }
    
    current_x += m_width_icon + m_width_column_space;

    // Draw the name
    // -------------

    core::recti pos_name(current_x, y,
                            UserConfigParams::m_width, y+m_distance_between_rows);
    m_font->draw(ri->m_kart_name, pos_name, color, false, false, NULL,
                    true /* ignoreRTL */);
    current_x += m_width_kart_name + m_width_column_space;

   
    // Draw the time except in FTL mode
    // --------------------------------
    if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_FOLLOW_LEADER)
    {
        core::recti dest_rect = core::recti(current_x, y, current_x+100, y+10);
        m_font->draw(ri->m_finish_time_string, dest_rect, color, false, false,
                     NULL, true /* ignoreRTL */);
        current_x += m_width_finish_time + m_width_column_space;
    }

    // Only display points in GP mode and when the GP results are displayed.
    // =====================================================================
    if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX &&
        m_animation_state != RR_RACE_RESULT)
    {
        // Draw the new points
        // -------------------
        if(ri->m_new_points > 0)
        {
            core::recti dest_rect = core::recti(current_x,     y,
                                                current_x+100, y+10);
            core::stringw point_string = core::stringw("+")
                                       + core::stringw((int)ri->m_new_points);
            // With mono-space digits space has the same width as each digit,
            // so we can simply fill up the string with spaces to get the
            // right aligned.
            while(point_string.size()<3)
                point_string = core::stringw(" ")+point_string;
            m_font->draw(point_string, dest_rect, color, false, false, NULL,
                         true /* ignoreRTL */);
        }
        current_x += m_width_new_points + m_width_column_space;

        // Draw the old_points plus increase value
        // ---------------------------------------
        core::recti dest_rect = core::recti(current_x, y, current_x+100, y+10);
        core::stringw point_inc_string =
            core::stringw((int)(ri->m_current_displayed_points));
        while(point_inc_string.size()<3)
            point_inc_string = core::stringw(" ")+point_inc_string;
        m_font->draw(point_inc_string, dest_rect, color, false, false, NULL,
                     true /* ignoreRTL */);
    }
}   // displayOneEntry
예제 #16
0
// ----------------------------------------------------------------------------
void RaceResultGUI::displayHighScores()
{
    // This happens in demo world
    if(!World::getWorld())
        return;

    Highscores* scores = World::getWorld()->getHighscores();
    // In some case for exemple FTL they will be no highscores
    if (scores != NULL)
    {
        video::SColor white_color = video::SColor(255,255,255,255);

        int x = (int)(UserConfigParams::m_width*0.55f);
        int y = m_top;

        // First draw title
        GUIEngine::getFont()->draw(_("Highscores"),
              core::recti(x, y, 0, 0),
              white_color,
              false, false, NULL, true /* ignoreRTL */);

        std::string kart_name;
        irr::core::stringw player_name;

        // prevent excessive long name
        unsigned int max_characters = 15;
        float time;
        for (int i = 0; i < scores->getNumberEntries(); i++)
        {
            scores->getEntry(i,kart_name,player_name, &time);
            if (player_name.size() > max_characters)
            {
                int begin = (int(m_timer/0.4f)) % ( player_name.size() - max_characters );
                player_name = player_name.subString(begin,max_characters,false);
            }

            video::SColor text_color = white_color;
            if (m_highscore_rank-1 == i)
            {
                text_color = video::SColor(255,255,0,  0  );
            }

            int current_x = x;
            int current_y = y+(i+1)*50;

            const KartProperties* prop = kart_properties_manager->getKart(kart_name);
            if (prop != NULL)
            {
                const std::string &icon_path = prop->getAbsoluteIconFile();
                video::ITexture* kart_icon_texture = irr_driver->getTexture( icon_path );

                if (kart_icon_texture != NULL)
                {
                    core::recti source_rect(core::vector2di(0,0),
                        kart_icon_texture->getSize());

                    core::recti dest_rect(current_x, current_y,
                        current_x+m_width_icon, current_y+m_width_icon);

                    draw2DImage(
                        kart_icon_texture, dest_rect,
                        source_rect, NULL, NULL,
                        true);

                    current_x += m_width_icon + m_width_column_space;
                }
            }

            // draw the player name
            GUIEngine::getSmallFont()->draw(player_name.c_str(),
                core::recti(current_x, current_y, current_x+150, current_y+10),
                text_color,
                false, false, NULL, true /* ignoreRTL */);

            current_x += 180;

            // Finally draw the time
            std::string time_string = StringUtils::timeToString(time);
            GUIEngine::getSmallFont()->draw(time_string.c_str(),
                core::recti(current_x, current_y, current_x+100, current_y+10),
                text_color,
                false, false, NULL, true /* ignoreRTL */);
        }
    }
}