void EC_OgreMovableTextOverlay::SetText(const std::string& text)
{
    if (!node_)
        return;

    text_ = text;
    boost::trim(text_);
    // Replace few common scandic letters with a and o.
    ReplaceCharInplace(text_, 'Ä', 'A');
    ReplaceCharInplace(text_, 'ä', 'a');
    ReplaceCharInplace(text_, 'Ö', 'O');
    ReplaceCharInplace(text_, 'ö', 'o');
    ReplaceCharInplace(text_, 'Å', 'A');
    ReplaceCharInplace(text_, 'å', 'a');

    try
    {
        text_element_->setCaption(text_);
    }
    catch(...)
    {
        text_ = "";
    }

    textDim_ = GetTextDimensions(text_);
    container_->setDimensions(textDim_.x, textDim_.y);
}
NS_IMETHODIMP
nsThebesRenderingContext::GetTextDimensions(const char*       aString,
                                            PRInt32           aLength,
                                            PRInt32           aAvailWidth,
                                            PRInt32*          aBreaks,
                                            PRInt32           aNumBreaks,
                                            nsTextDimensions& aDimensions,
                                            PRInt32&          aNumCharsFit,
                                            nsTextDimensions& aLastWordDimensions,
                                            PRInt32*          aFontID)
{
    PRUint32 maxChunkLength = GetMaxChunkLength(this);
    if (aLength <= PRInt32(maxChunkLength))
        return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks, aNumBreaks,
                                         aDimensions, aNumCharsFit, aLastWordDimensions, aFontID);

    if (aFontID) {
        *aFontID = 0;
    }

    // Do a naive implementation based on 3-arg GetTextDimensions
    PRInt32 x = 0;
    PRInt32 wordCount;
    for (wordCount = 0; wordCount < aNumBreaks; ++wordCount) {
        PRInt32 lastBreak = wordCount > 0 ? aBreaks[wordCount - 1] : 0;
        nsTextDimensions dimensions;

        NS_ASSERTION(aBreaks[wordCount] > lastBreak, "Breaks must be monotonically increasing");
        NS_ASSERTION(aBreaks[wordCount] <= aLength, "Breaks can't exceed string length");

         // Call safe method

        nsresult rv =
            GetTextDimensions(aString + lastBreak, aBreaks[wordCount] - lastBreak,
                            dimensions);
        if (NS_FAILED(rv))
            return rv;
        x += dimensions.width;
        // The first word always "fits"
        if (x > aAvailWidth && wordCount > 0)
            break;
        // aDimensions ascent/descent should exclude the last word (unless there
        // is only one word) so we let it run one word behind
        if (wordCount == 0) {
            aDimensions = dimensions;
        } else {
            aDimensions.Combine(aLastWordDimensions);
        }
        aNumCharsFit = aBreaks[wordCount];
        aLastWordDimensions = dimensions;
    }
    // aDimensions width should include all the text
    aDimensions.width = x;
    return NS_OK;
}
Exemplo n.º 3
0
DGLE_RESULT DGLE_API CBitmapFont::Draw3D(const char *pcTxt)
{
	size_t length = strlen(pcTxt);
	
	if (length == 0)
		return S_FALSE;

	DGLE_RESULT hr;

	uint strwidth, strheight;
	if (FAILED(hr = GetTextDimensions(pcTxt, strwidth, strheight)))
		return hr;

	_pTex->Bind();

	uint t_w, t_h;
	_pTex->GetDimensions(t_w, t_h);
	
	float x = -(float)strwidth * 0.5f, y = -(float)strheight * 0.5f;

	const uint floats_per_char = 12 /* vertices */ + 12 /* texture coords */,
		line_floats_cnt = length * floats_per_char;

	if (_uiBufferSize < line_floats_cnt)
	{
		_uiBufferSize = line_floats_cnt;
		delete[] _pBuffer;
		_pBuffer = new float[_uiBufferSize];
	}

	const uint tex_coords_offset = line_floats_cnt / 2;

	for (size_t i = 0; i < length; ++i)
	{
		const uchar ch = static_cast<const uchar>(pcTxt[i]) - 32;
		const int
			&curb_x = _astChars[ch].x,
			&curb_y = _astChars[ch].y,
			&curb_w = _astChars[ch].w,
			&curb_h = _astChars[ch].h;

		const uint char_step = i * (floats_per_char / 2);

		_pBuffer[char_step] = x + curb_w * _fScale; _pBuffer[char_step + 1] = y;
		_pBuffer[char_step + 2] = x + curb_w * _fScale; _pBuffer[char_step + 3] = y + curb_h * _fScale;
		_pBuffer[char_step + 4] = x; _pBuffer[char_step + 5] = y;
		
		_pBuffer[char_step + 6] = x; _pBuffer[char_step + 7] = y;
		_pBuffer[char_step + 8] = x + curb_w * _fScale; _pBuffer[char_step + 9] = _pBuffer[char_step + 3];
		_pBuffer[char_step + 10] = x; _pBuffer[char_step + 11] = _pBuffer[char_step + 3];

		_pBuffer[tex_coords_offset + char_step] = (curb_x + curb_w) / (float)t_w; _pBuffer[tex_coords_offset + char_step + 1] = (curb_y + curb_h) / (float)t_h;
		_pBuffer[tex_coords_offset + char_step + 2] = _pBuffer[tex_coords_offset + char_step]; _pBuffer[tex_coords_offset + char_step + 3] = curb_y / (float)t_h;
		_pBuffer[tex_coords_offset + char_step + 4] = curb_x / (float)t_w; _pBuffer[tex_coords_offset + char_step + 5] = _pBuffer[tex_coords_offset + char_step + 1];
		
		_pBuffer[tex_coords_offset + char_step + 6] = _pBuffer[tex_coords_offset + char_step + 4]; _pBuffer[tex_coords_offset + char_step + 7] = _pBuffer[tex_coords_offset + char_step + 1];
		_pBuffer[tex_coords_offset + char_step + 8] = _pBuffer[tex_coords_offset + char_step + 2]; _pBuffer[tex_coords_offset + char_step + 9] = _pBuffer[tex_coords_offset + char_step + 3];
		_pBuffer[tex_coords_offset + char_step + 10] = _pBuffer[tex_coords_offset + char_step + 4]; _pBuffer[tex_coords_offset + char_step + 11] = _pBuffer[tex_coords_offset + char_step + 3];

		x += curb_w * _fScale;
	}

	_pRender3D->Draw(TDrawDataDesc((uint8 *)_pBuffer, -1, tex_coords_offset * sizeof(float), true), CRDM_TRIANGLES, (uint)length * 6);

	return S_OK;
}
Exemplo n.º 4
0
DGLE_RESULT DGLE_API CBitmapFont::Draw2D(float fX, float fY, const char *pcTxt, const TColor4 &stColor, float fAngle, bool bVerticesColors)
{
	uint length = strlen(pcTxt);

	if (length == 0)
		return S_FALSE;

	bool b_need_update;

	_pRender2D->NeedToUpdateBatchData(b_need_update);

	if (!b_need_update)
	{
		_pRender2D->Draw(_pTex, TDrawDataDesc(), CRDM_TRIANGLES, length * 6, TRectF(), (E_EFFECT2D_FLAGS)(EF_BLEND | (bVerticesColors ? EF_DEFAULT : EF_COLOR_MIX)));
		return S_OK;
	}

	uint width, height;
	
	GetTextDimensions(pcTxt, width, height);
	
	float quad[] = {fX, fY, fX + (float)width, fY, fX + (float)width, fY + (float)height, fX, fY + (float)height};
	
	TMatrix4 transform;

	if (fAngle != 0.f)
	{
		TMatrix4 rot = MatrixIdentity();
		
		const float s = sinf(-fAngle * (float)M_PI/180.f), c = cosf(-fAngle * (float)M_PI/180.f);

		rot._2D[0][0] = c;
		rot._2D[0][1] = -s;
		rot._2D[1][0] = s;
		rot._2D[1][1] = c;

		transform = MatrixTranslate(TVector3(-(fX + width / 2.f), -(fY + height / 2.f), 0.f)) * rot * MatrixTranslate(TVector3(fX + width / 2.f, fY + height / 2.f, 0.f));

		float x = quad[0], y = quad[1];
		quad[0]	= transform._2D[0][0] * x + transform._2D[1][0] * y + transform._2D[3][0];
		quad[1]	= transform._2D[0][1] * x + transform._2D[1][1] * y + transform._2D[3][1];

		 x = quad[2]; y = quad[3];
		quad[2]	= transform._2D[0][0] * x + transform._2D[1][0] * y + transform._2D[3][0];
		quad[3]	= transform._2D[0][1] * x + transform._2D[1][1] * y + transform._2D[3][1];

		x = quad[4]; y = quad[5];
		quad[4]	= transform._2D[0][0] * x + transform._2D[1][0] * y + transform._2D[3][0];
		quad[5]	= transform._2D[0][1] * x + transform._2D[1][1] * y + transform._2D[3][1];

		x = quad[6]; y = quad[7];
		quad[6]	= transform._2D[0][0] * x + transform._2D[1][0] * y + transform._2D[3][0];
		quad[7]	= transform._2D[0][1] * x + transform._2D[1][1] * y + transform._2D[3][1];
	}

	if (!_pRender2D->BBoxInScreen(quad, fAngle != 0.f))
		return S_OK;

	float xoffset = 0.f;
	uint t_w, t_h;
	
	_pTex->GetDimensions(t_w, t_h);

	TColor4 prev_color, verts_colors[4];
	
	_pRender2D->GetColorMix(prev_color);
	_pRender2D->SetColorMix(stColor);

	if (bVerticesColors)
		_pRender2D->GetVerticesColors(verts_colors[0], verts_colors[1], verts_colors[2], verts_colors[3]);

	uint size = length * 12 * 2;

	if (bVerticesColors)
		size = length * 24 * 2;

	if (_uiBufferSize < size)
	{
		_uiBufferSize = size;
		delete[] _pBuffer;
		_pBuffer = new float[_uiBufferSize];
	}

	for (uint i = 0; i < length; ++i)
	{
		const uchar ch = static_cast<const uchar>(pcTxt[i]) - 32;
		
		const int
			&curb_x = _astChars[ch].x,
			&curb_y = _astChars[ch].y,
			&curb_w = _astChars[ch].w,
			&curb_h = _astChars[ch].h;
		
		const uint idx = i * 24;

		_pBuffer[idx] = fX + xoffset; _pBuffer[idx + 1] = fY; _pBuffer[idx + 2] = (float)curb_x / (float)t_w; _pBuffer[idx + 3] = (float)curb_y / (float)t_h;
		_pBuffer[idx + 4] = fX + xoffset + (float)curb_w * _fScale; _pBuffer[idx + 5] = fY; _pBuffer[idx + 6] = (float)(curb_x + curb_w) / (float)t_w; _pBuffer[idx + 7] = (float)curb_y / (float)t_h;
		_pBuffer[idx + 8] = fX + xoffset + (float)curb_w * _fScale; _pBuffer[idx + 9] = fY + (float)curb_h * _fScale; _pBuffer[idx + 10] = (float)(curb_x + curb_w) / (float)t_w; _pBuffer[idx + 11] = (float)(curb_y + curb_h) / (float)t_h;
		_pBuffer[idx + 12] = _pBuffer[idx]; _pBuffer[idx + 13] = _pBuffer[idx + 1]; _pBuffer[idx + 14] = _pBuffer[idx + 2]; _pBuffer[idx + 15] = _pBuffer[idx + 3];
		_pBuffer[idx + 16] = _pBuffer[idx + 8]; _pBuffer[idx + 17] = _pBuffer[idx + 9]; _pBuffer[idx + 18] = _pBuffer[idx + 10]; _pBuffer[idx + 19] = _pBuffer[idx + 11];
		_pBuffer[idx + 20] = fX + xoffset; _pBuffer[idx + 21] = fY + (float)curb_h * _fScale; _pBuffer[idx + 22] = (float)curb_x / (float)t_w; _pBuffer[idx + 23] = (float)(curb_y + curb_h) / (float)t_h;

		if (fAngle != 0.f)
		{
			float x = _pBuffer[idx], y = _pBuffer[idx + 1];
			_pBuffer[idx]		= transform._2D[0][0] * x + transform._2D[1][0] * y + transform._2D[3][0];
			_pBuffer[idx + 1]	= transform._2D[0][1] * x + transform._2D[1][1] * y + transform._2D[3][1];

			 x = _pBuffer[idx + 4]; y = _pBuffer[idx + 5];
			_pBuffer[idx + 4]	= transform._2D[0][0] * x + transform._2D[1][0] * y + transform._2D[3][0];
			_pBuffer[idx + 5]	= transform._2D[0][1] * x + transform._2D[1][1] * y + transform._2D[3][1];

			x = _pBuffer[idx + 8]; y = _pBuffer[idx + 9];
			_pBuffer[idx + 8]	= transform._2D[0][0] * x + transform._2D[1][0] * y + transform._2D[3][0];
			_pBuffer[idx + 9]	= transform._2D[0][1] * x + transform._2D[1][1] * y + transform._2D[3][1];

			x = _pBuffer[idx + 20]; y = _pBuffer[idx + 21];
			_pBuffer[idx + 20] = transform._2D[0][0] * x + transform._2D[1][0] * y + transform._2D[3][0];
			_pBuffer[idx + 21] = transform._2D[0][1] * x + transform._2D[1][1] * y + transform._2D[3][1];

			_pBuffer[idx + 12] = _pBuffer[idx]; _pBuffer[idx + 13] = _pBuffer[idx + 1];
			_pBuffer[idx + 16] = _pBuffer[idx + 8]; _pBuffer[idx + 17] = _pBuffer[idx + 9];
		}

		if (bVerticesColors)
		{
			const uint idx = length * 24 + i * 24;
			memcpy(&_pBuffer[idx], verts_colors[0], 12 * sizeof(float));
			memcpy(&_pBuffer[idx + 12], verts_colors[0], 4 * sizeof(float));
			memcpy(&_pBuffer[idx + 16], verts_colors[2], 8 * sizeof(float));
		}

		xoffset += (float)curb_w * _fScale;
	}

	TDrawDataDesc desc;

	desc.pData = (uint8 *)_pBuffer;
	desc.uiVertexStride = 4 * sizeof(float);
	desc.bVertices2D = true;
	desc.uiTextureVertexOffset = 2 * sizeof(float);
	desc.uiTextureVertexStride = desc.uiVertexStride;

	if (bVerticesColors)
		desc.uiColorOffset = length * 24 * sizeof(float);

	_pRender2D->Draw(_pTex, desc, CRDM_TRIANGLES, length*6, TRectF(), (E_EFFECT2D_FLAGS)(EF_BLEND | (bVerticesColors ? EF_DEFAULT : EF_COLOR_MIX)));

	_pRender2D->SetColorMix(prev_color);

	return S_OK;
}
void EC_OgreMovableTextOverlay::Update()
{
    if (!node_ || !visible_ || !placeable_ || renderer_.expired())
        return;

    if(!node_->isInSceneGraph())
    {
        overlay_->hide();
        return;
    }

    Ogre::Camera* camera = renderer_.lock()->GetCurrentCamera();
    if (!camera)
        return;

    Ogre::Viewport* viewport = camera->getViewport();
    Ogre::Vector3 point = node_->_getDerivedPosition();

    // Is the camera facing that point? If not, hide the overlay and return.
    Ogre::Plane cameraPlane = Ogre::Plane(Ogre::Vector3(camera->getDerivedOrientation().zAxis()), camera->getDerivedPosition());
    if(cameraPlane.getSide(point) != Ogre::Plane::NEGATIVE_SIDE)
    {
        overlay_->hide();
        return;
    }

    // Hide the overlay if it's too far.
    Ogre::Vector3 res = camera->getDerivedPosition() - point;
    float distance = sqrt(res.x * res.x + res.y * res.y + res.z * res.z);

    if (distance > MAX_VISIBILITY_DISTANCE)
    {
        overlay_->hide();
        return;
    }

    // Set the alpha channel for the overlay.
    if (materialHasAlpha_)
        SetAlphaChannelIntensity(distance);

    // Derive the 2D screen-space coordinates for node point.
    point = camera->getProjectionMatrix() * (camera->getViewMatrix() * point);

    // Transform from coordinate space [-1, 1] to [0, 1]
    float x = (point.x / 2) + 0.5f;
    float y = 1 - ((point.y / 2) + 0.5f);

    // Update the position (centering the text)
    container_->setPosition(x - (textDim_.x / 2), y);

    // Update the dimensions also if the window is resized.
    if (windowWidth_ != viewport->getActualWidth() ||
        windowHeight_ != viewport->getActualHeight())
    {
        windowWidth_ = viewport->getActualWidth();
        windowHeight_ = viewport->getActualHeight();
        
        textDim_ = GetTextDimensions(text_);
        container_->setDimensions(textDim_.x, textDim_.y);
    }

    ///\todo Scale the text and width and height of the container?
//        text_element_->setMetricsMode(Ogre::GMM_RELATIVE);
//        text_element_->setPosition(textDim_.x, textDim_.y);
//        text_element_->setPosition(textDim_.x / 10, 0.01);
//        text_element_->setCharHeight(max_x - min_x/*2*0.0175f*///);

    overlay_->show();
}
void EC_OgreMovableTextOverlay::CreateOverlay(const Vector3df& offset)
{
    if (renderer_.expired())
        return;

    // Return if already created
    if (node_)
        return;

    // Create SceneNode
    Ogre::SceneManager *scene_mgr = renderer_.lock()->GetSceneManager();
    node_ = scene_mgr->createSceneNode();

    // Set the node position to an user-specified offset
    node_->setPosition(ToOgreVector3(offset));

    // Overlay
    overlayName_ = renderer_.lock()->GetUniqueObjectName();
    overlay_ = Ogre::OverlayManager::getSingleton().create(overlayName_);

    // Container
    containerName_ = renderer_.lock()->GetUniqueObjectName();
    container_ = static_cast<Ogre::OverlayContainer*>
        (Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", containerName_));
    overlay_->add2D(container_);

    // Font
    ///\todo user-defined font
    std::string fontName = "Console";
    Ogre::FontManager::getSingleton().load(fontName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
    font_ = (Ogre::Font*)Ogre::FontManager::getSingleton().getByName(fontName).getPointer();
    font_->setParameter("size", "16");

    // Overlay text
    text_element_ = checked_static_cast<Ogre::TextAreaOverlayElement*>
        (Ogre::OverlayManager::getSingleton().createOverlayElement("TextArea", overlayName_));
//        text_element_ = Ogre::OverlayManager::getSingleton().createOverlayElement("TextArea", "shapeNameText");
    text_element_->setDimensions(0.8, 0.8);
    text_element_->setMetricsMode(Ogre::GMM_PIXELS);
    text_element_->setPosition(1, 2);
    text_element_->setParameter("font_name", fontName);
    text_element_->setParameter("char_height", font_->getParameter("size"));
//        text_element_->setCharHeight(0.035f);
    text_element_->setParameter("horz_align", "left");
    fontColor_ = Color(0, 0, 0, 1);
    text_element_->setColour(Ogre::ColourValue::Black);
    container_->addChild(text_element_);

    if(text_ != "")
    {
        textDim_ = GetTextDimensions(text_);
        container_->setDimensions(textDim_.x, textDim_.y);
    }

    SetMaterial("BlueTransparent"/*baseMaterialName_*/);

    if (visible_)
        overlay_->show();
    else
        overlay_->hide();

    overlay_->setZOrder(100);
}