void CIrrMeshWriter::writeMeshBuffer(const scene::IMeshBuffer* buffer)
{
	Writer->writeElement(L"buffer", false);
	Writer->writeLineBreak();

	// write bounding box

	writeBoundingBox(buffer->getBoundingBox());
	Writer->writeLineBreak();

	// write material

	writeMaterial(buffer->getMaterial());

	// write vertices

	const core::stringw vertexTypeStr = video::sBuiltInVertexTypeNames[buffer->getVertexType()];

	Writer->writeElement(L"vertices", false,
		L"type", vertexTypeStr.c_str(),
		L"vertexCount", core::stringw(buffer->getVertexCount()).c_str());

	Writer->writeLineBreak();

	u32 vertexCount = buffer->getVertexCount();

	switch(buffer->getVertexType())
	{
	case video::EVT_STANDARD:
		{
			video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices();
			for (u32 j=0; j<vertexCount; ++j)
			{
				core::stringw str = getVectorAsStringLine(vtx[j].Pos);
				str += L" ";
				str += getVectorAsStringLine(vtx[j].Normal);

				char tmp[12];
				sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue());
				str += tmp;

				str += getVectorAsStringLine(vtx[j].TCoords);

				Writer->writeText(str.c_str());
				Writer->writeLineBreak();
			}
		}
		break;
	case video::EVT_2TCOORDS:
		{
			video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices();
			for (u32 j=0; j<vertexCount; ++j)
			{
				core::stringw str = getVectorAsStringLine(vtx[j].Pos);
				str += L" ";
				str += getVectorAsStringLine(vtx[j].Normal);

				char tmp[12];
				sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue());
				str += tmp;

				str += getVectorAsStringLine(vtx[j].TCoords);
				str += L" ";
				str += getVectorAsStringLine(vtx[j].TCoords2);

				Writer->writeText(str.c_str());
				Writer->writeLineBreak();
			}
		}
		break;
	case video::EVT_TANGENTS:
		{
			video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices();
			for (u32 j=0; j<vertexCount; ++j)
			{
				core::stringw str = getVectorAsStringLine(vtx[j].Pos);
				str += L" ";
				str += getVectorAsStringLine(vtx[j].Normal);

				char tmp[12];
				sprintf(tmp, " %02x%02x%02x%02x ", vtx[j].Color.getAlpha(), vtx[j].Color.getRed(), vtx[j].Color.getGreen(), vtx[j].Color.getBlue());
				str += tmp;

				str += getVectorAsStringLine(vtx[j].TCoords);
				str += L" ";
				str += getVectorAsStringLine(vtx[j].Tangent);
				str += L" ";
				str += getVectorAsStringLine(vtx[j].Binormal);

				Writer->writeText(str.c_str());
				Writer->writeLineBreak();
			}
		}
		break;
	}

	Writer->writeClosingTag(L"vertices");
	Writer->writeLineBreak();

	// write indices

	Writer->writeElement(L"indices", false,
		L"indexCount", core::stringw(buffer->getIndexCount()).c_str());

	Writer->writeLineBreak();

	int indexCount = (int)buffer->getIndexCount();

	video::E_INDEX_TYPE iType = buffer->getIndexType();

	const u16* idx16 = buffer->getIndices();
	const u32* idx32 = (u32*) buffer->getIndices();
	const int maxIndicesPerLine = 25;

	for (int i=0; i<indexCount; ++i)
	{
		if(iType == video::EIT_16BIT)
		{
			core::stringw str((int)idx16[i]);
			Writer->writeText(str.c_str());
		}
		else
		{
			core::stringw str((int)idx32[i]);
			Writer->writeText(str.c_str());
		}

		if (i % maxIndicesPerLine != maxIndicesPerLine)
		{
			if (i % maxIndicesPerLine == maxIndicesPerLine-1)
				Writer->writeLineBreak();
			else
				Writer->writeText(L" ");
		}
	}

	if ((indexCount-1) % maxIndicesPerLine != maxIndicesPerLine-1)
		Writer->writeLineBreak();

	Writer->writeClosingTag(L"indices");
	Writer->writeLineBreak();

	// close buffer tag

	Writer->writeClosingTag(L"buffer");
}
            bloop(tree_list, i)
            {
                CTree* tree = (CTree*)b_get_mem_address(tree_list,i);
                if (tree->translation == vec3(0,0,0))
                {
                    continue;
                }
                for (s4 k = 0; k < tree->child_list.length;k++)
                { 
                    Component* cmpnt = (Component*)b_get_value(tree->child_list,k); 
                    cmpnt->node->setPosition(cmpnt->node->getPosition() + tree->translation.irr());
                    cmpnt->shadow->setPosition(cmpnt->node->getPosition() * vector3df(1,1,0) + vector3df(0,0,10));
                }
                tree->translation = vec3(0,0,0);
            }

            if (receiver->restart.state) { game_state = GAME_STATE_RESET; }
            if (receiver->QUIT) { game_state = GAME_STATE_QUIT; }
        }
        core::stringw str = L"Secret [";
        str += irrlicht->driver->getName();
        str += L"] FPS: ";
        str += (s32)irrlicht->driver->getFPS();

        irrlicht->device->setWindowCaption(str.c_str());
    } 

    irrlicht->device->getCursorControl()->setVisible(true);
}
int UnicodeEncoding::GetBytesCountW(const core::stringw& str)
{
	return str.length()*2;
}
int UnicodeEncoding::GetBytesW(const core::stringw& str,byte* buff,int maxLen)
{
	return GetBytesW(&str[0],str.length(),buff,maxLen);
}
void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, const int playerID)
{
    if (name == "options_choice")
    {
        std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER);

        Screen *screen = NULL;
        if (selection == "tab_audio")
            screen = OptionsScreenAudio::getInstance();
        else if (selection == "tab_video")
            screen = OptionsScreenVideo::getInstance();
        else if (selection == "tab_players")
            screen = TabbedUserScreen::getInstance();
        else if (selection == "tab_controls")
            screen = OptionsScreenInput::getInstance();
        //else if (selection == "tab_ui")
        //    screen = OptionsScreenUI::getInstance();
        if(screen)
            StateManager::get()->replaceTopMostScreen(screen);
    }
    else if(name == "back")
    {
        StateManager::get()->escapePressed();
    }
    else if (name == "skinchoice")
    {
        GUIEngine::SpinnerWidget* skinSelector = getWidget<GUIEngine::SpinnerWidget>("skinchoice");
        assert( skinSelector != NULL );

        const core::stringw selectedSkin = skinSelector->getStringValue();
        UserConfigParams::m_skin_file = core::stringc(selectedSkin.c_str()).c_str() + std::string(".stkskin");
        GUIEngine::reloadSkin();
    }
    else if (name == "showfps")
    {
        CheckBoxWidget* fps = getWidget<CheckBoxWidget>("showfps");
        assert( fps != NULL );
        UserConfigParams::m_display_fps = fps->getState();
    }
    else if (name=="enable-internet")
    {
        CheckBoxWidget* internet = getWidget<CheckBoxWidget>("enable-internet");
        assert( internet != NULL );
        UserConfigParams::m_internet_status =
            internet->getState() ? RequestManager::IPERM_ALLOWED
                                 : RequestManager::IPERM_NOT_ALLOWED;
        // If internet gets enabled, re-initialise the addon manager (which
        // happens in a separate thread) so that news.xml etc can be
        // downloaded if necessary.
        CheckBoxWidget *stats = getWidget<CheckBoxWidget>("enable-hw-report");
        LabelWidget *stats_label = getWidget<LabelWidget>("label-hw-report");
        if(internet->getState())
        {
            NewsManager::get()->init(false);
            stats->setVisible(true);
            stats_label->setVisible(true);
            stats->setState(UserConfigParams::m_hw_report_enable);
        }
        else
        {
            stats->setVisible(false);
            stats_label->setVisible(false);
        }

    }
    else if (name=="enable-hw-report")
    {
        CheckBoxWidget* stats = getWidget<CheckBoxWidget>("enable-hw-report");
        UserConfigParams::m_hw_report_enable = stats->getState();
        if(stats->getState())
            HardwareStats::reportHardwareStats();
    }
    else if (name=="show-login")
    {
        CheckBoxWidget* show_login = getWidget<CheckBoxWidget>("show-login");
        assert( show_login != NULL );
        UserConfigParams::m_always_show_login_screen = show_login->getState();
    }
    else if (name=="perPlayerDifficulty")
    {
        CheckBoxWidget* difficulty = getWidget<CheckBoxWidget>("perPlayerDifficulty");
        assert( difficulty != NULL );
        UserConfigParams::m_per_player_difficulty = difficulty->getState();
    }
    else if (name == "language")
    {
        ListWidget* list_widget = getWidget<ListWidget>("language");
        std::string selection = list_widget->getSelectionInternalName();

        delete translations;

        if (selection == "system")
        {
#ifdef WIN32
            _putenv("LANGUAGE=");
#else
            unsetenv("LANGUAGE");
#endif
        }
        else
        {
#ifdef WIN32
            std::string s=std::string("LANGUAGE=")+selection.c_str();
            _putenv(s.c_str());
#else
            setenv("LANGUAGE", selection.c_str(), 1);
#endif
        }

        translations = new Translations();

        //Reload fonts for new translation
        GUIEngine::cleanHollowCopyFont();
        GUIEngine::getTitleFont()->recreateFromLanguage();
        GUIEngine::getFont()->recreateFromLanguage();
        GUIEngine::reloadHollowCopyFont(GUIEngine::getFont());

        GUIEngine::getStateManager()->hardResetAndGoToScreen<MainMenuScreen>();

        GUIEngine::getFont()->updateRTL();
        GUIEngine::getTitleFont()->updateRTL();
        GUIEngine::getSmallFont()->updateRTL();

        UserConfigParams::m_language = selection.c_str();
        user_config->saveConfig();

        OptionsScreenUI::getInstance()->push();
    }

}   // eventCallback
void OptionsScreenUI::eventCallback(Widget* widget, const std::string& name, const int playerID)
{
    if (name == "options_choice")
    {
        std::string selection = ((RibbonWidget*)widget)->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str();

        if (selection == "tab_audio") StateManager::get()->replaceTopMostScreen(OptionsScreenAudio::getInstance());
        else if (selection == "tab_video") StateManager::get()->replaceTopMostScreen(OptionsScreenVideo::getInstance());
        else if (selection == "tab_players") StateManager::get()->replaceTopMostScreen(OptionsScreenPlayers::getInstance());
        else if (selection == "tab_controls") StateManager::get()->replaceTopMostScreen(OptionsScreenInput::getInstance());
    }
    else if(name == "back")
    {
        StateManager::get()->escapePressed();
    }
    else if (name == "skinchoice")
    {
        GUIEngine::SpinnerWidget* skinSelector = getWidget<GUIEngine::SpinnerWidget>("skinchoice");
        assert( skinSelector != NULL );

        const core::stringw selectedSkin = skinSelector->getStringValue();
        UserConfigParams::m_skin_file = core::stringc(selectedSkin.c_str()).c_str() + std::string(".stkskin");
        GUIEngine::reloadSkin();
    }
    else if (name == "showfps")
    {
        CheckBoxWidget* fps = getWidget<CheckBoxWidget>("showfps");
        assert( fps != NULL );
        UserConfigParams::m_display_fps = fps->getState();
    }
    else if (name=="enable-internet")
    {
        CheckBoxWidget* internet = getWidget<CheckBoxWidget>("enable-internet");
        assert( internet != NULL );
        UserConfigParams::m_internet_status =
            internet->getState() ? RequestManager::IPERM_ALLOWED
                                 : RequestManager::IPERM_NOT_ALLOWED;
        // If internet gets enabled, re-initialise the addon manager (which 
        // happens in a separate thread) so that news.xml etc can be
        // downloaded if necessary.
        if(internet->getState())
            NewsManager::get()->init(false);
    }
    else if (name == "language")
    {
        ListWidget* list_widget = getWidget<ListWidget>("language");
        std::string selection = list_widget->getSelectionInternalName();

        delete translations;

        if (selection == "system")
        {
#ifdef WIN32
            _putenv("LANGUAGE=");
#else
            unsetenv("LANGUAGE");
#endif
        }
        else
        {
#ifdef WIN32
            std::string s=std::string("LANGUAGE=")+selection.c_str();
            _putenv(s.c_str());
#else
            setenv("LANGUAGE", selection.c_str(), 1);
#endif
        }

        translations = new Translations();
        GUIEngine::getStateManager()->hardResetAndGoToScreen<MainMenuScreen>();

        GUIEngine::getFont()->updateRTL();
        GUIEngine::getTitleFont()->updateRTL();
        GUIEngine::getSmallFont()->updateRTL();

        UserConfigParams::m_language = selection.c_str();
        user_config->saveConfig();

        GUIEngine::getStateManager()->pushScreen(OptionsScreenUI::getInstance());
    }

}   // eventCallback
Exemple #7
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
        }
    }
}
void BrowserWindowImpl::ExecuteScript(const core::stringw& script)
{
	m_window->executeJavascript(Berkelium::WideString::point_to(script.c_str(),script.length()));
}
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 (!m_video_driver) return;

    GUIEngine::GlyphPageCreator* gp_creator = GUIEngine::getGlyphPageCreator();

    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);

    if (m_type == T_NORMAL || T_BOLD) //lazy load char, have to do this again
    {                                 //because some text isn't drawn with getDimension
        for (u32 i = 0; i < text_size; i++)
        {
            wchar_t c = text[i];
            if (c == L'\r' ||  c == L'\n' || c == L' ' || c < 32) continue;
            if (!GUIEngine::getFont()->hasThisChar(c))
                gp_creator->insertChar(c);

            if (charCollector != NULL && m_type == T_NORMAL && m_spritebank->getSprites()
                [GUIEngine::getFont()->getSpriteNoFromChar(&c)].Frames[0].textureNumber
                == m_spritebank->getTextureCount() - 1) //Prevent overwriting texture used by billboard text
            {
                 Log::debug("ScalableFont::doDraw",
                            "Character used by billboard text is in the last "
                            "glyph page of normal font. Create a new glyph "
                            "page for new characters inserted later to prevent "
                            "it from being removed.");
                 GUIEngine::getFont()->forceNewPage();
            }
        }

        if (gp_creator->getNewChar().size() > 0 && !m_is_hollow_copy && m_scale == 1)
        {
            Log::debug("ScalableFont::doDraw",
                       "New character(s) %s discoverd, perform lazy loading",
                       StringUtils::wideToUtf8(gp_creator->getNewChar()).c_str());

            if (!GUIEngine::getFont()->lazyLoadChar())
                Log::error("ScalableFont::lazyLoadChar",
                           "Can't insert new char into glyph pages.");
        }
    }

    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)(m_max_height*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;
        if (charCollector == NULL)
        {
            //Try to use ceil to make offset calculate correctly when m_scale is smaller than 1
            s32 glyph_offset_x = (s32)((float) area.bearingx*
                                 (fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
            s32 glyph_offset_y = (s32)ceil((float) area.offsety*
                                 (fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
            offset.X += glyph_offset_x;
            offset.Y += s32(glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0)); //Additional offset for digit text
            offsets.push_back(offset);
            offset.X -= glyph_offset_x;
            offset.Y -= s32(glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0));
        }
        else //Billboard text specific
        {
            s32 glyph_offset_x = (s32)ceil((float) area.bearingx*
                                 (fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
            s32 glyph_offset_y = (s32)ceil((float) area.offsety_bt*
                                 (fallback[i] ? m_scale*m_fallback_font_scale : m_scale));
            offset.X += glyph_offset_x;
            offset.Y += s32(glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0)); //Additional offset for digit text
            offsets.push_back(offset);
            offset.X -= glyph_offset_x;
            offset.Y -= s32(glyph_offset_y + floor(m_type == T_DIGIT ? 20*m_scale : 0));
        }
        // Invisible character. add something to the array anyway so that
        // indices from the various arrays remain in sync
        indices.push_back(m_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        = m_spritebank->getSprites();
    core::array< core::rect<s32> >& positions = m_spritebank->getPositions();
    core::array< 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 spriteAmount      = sprites.size();

    if (m_black_border && charCollector == 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 < indiceAmount; n++)
        {
            const int spriteID = indices[n];
            if (!fallback[n] && (spriteID < 0 || spriteID >= spriteAmount)) continue;
            if (indices[n] == -1) continue;

            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]);

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

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

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

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

            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);
                }
            }
        }
    }

    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]);

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

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

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

        video::ITexture* texture = (fallback[n] ?
                                    m_fallback_font->m_spritebank->getTexture(texID) :
                                    m_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);
        }
        */
#ifdef FONT_DEBUG
        GL32_draw2DRectangle(video::SColor(255, 255,0,0), dest,clip);
#endif

        if (fallback[n] || m_type == T_BOLD)
        {
            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 (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);
            }
        }
    }
}
Exemple #10
0
/** Render text and clip it to the specified rectangle if wanted, it will also
 *  do checking for missing characters in font and lazy load them.
 *  \param text The text to be rendering.
 *  \param position The position to be rendering.
 *  \param color The color used when rendering.
 *  \param hcenter If rendered horizontally center.
 *  \param vcenter If rendered vertically center.
 *  \param clip If clipping is needed.
 *  \param font_settings \ref FontSettings to use.
 *  \param char_collector \ref FontCharCollector to render billboard text.
 */
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)
{
#ifndef SERVER_ONLY
    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  = float(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
        {
            // 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 || isBold()) && 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] || isBold())
        {
            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);
            }
        }
    }
#endif
}   // render
Exemple #11
0
//! draws some text and clips it to the specified rectangle if wanted
void CGUIFont::draw(const core::stringw& text, const core::rect<s32>& position,
					video::SColor color,
					bool hcenter, bool vcenter, const core::rect<s32>* clip
				)
{
	if (!Driver || !SpriteBank)
		return;

	core::dimension2d<s32> textDimension;	// NOTE: don't make this u32 or the >> later on can fail when the dimension width is < position width
	core::position2d<s32> offset = position.UpperLeftCorner;

	if (hcenter || vcenter || clip)
		textDimension = getDimension(text.c_str());

	if (hcenter)
		offset.X += (position.getWidth() - textDimension.Width) >> 1;

	if (vcenter)
		offset.Y += (position.getHeight() - textDimension.Height) >> 1;

	if (clip)
	{
		core::rect<s32> clippedRect(offset, textDimension);
		clippedRect.clipAgainst(*clip);
		if (!clippedRect.isValid())
			return;
	}

	core::array<u32> indices(text.size());
	core::array<core::position2di> offsets(text.size());

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

		bool lineBreak=false;
		if ( c == L'\r') // Mac or Windows breaks
		{
			lineBreak = true;
			if ( text[i + 1] == L'\n') // Windows breaks
				c = text[++i];
		}
		else if ( c == L'\n') // Unix breaks
		{
			lineBreak = true;
		}

		if (lineBreak)
		{
			offset.Y += MaxHeight;
			offset.X = position.UpperLeftCorner.X;

			if ( hcenter )
			{
				offset.X += (position.getWidth() - textDimension.Width) >> 1;
			}
			continue;
		}

		SFontArea& area = Areas[getAreaFromCharacter(c)];

		offset.X += area.underhang;
		if ( Invisible.findFirst ( c ) < 0 )
		{
			indices.push_back(area.spriteno);
			offsets.push_back(offset);
		}

		offset.X += area.width + area.overhang + GlobalKerningWidth;
	}

	SpriteBank->draw2DSpriteBatch(indices, offsets, clip, color);
}