Example #1
0
// ***************************************************************************
void	CPatchUVLocator::build(const CPatch *patchCenter, sint edgeCenter, CPatch::CBindInfo	&bindInfo)
{
	nlassert(bindInfo.Zone);
	// copy basic. NB: NPatchs==0 means patchCenter is binded on a 1/X patch.
	_CenterPatch= const_cast<CPatch*>(patchCenter);
	_CenterPatchEdge= edgeCenter;
	_NPatchs= bindInfo.NPatchs;


	// set it to true. false-d if one of the neighbor patch does not have same number of tile.
	_SameEdgeOrder= true;


	// For all patchs binded to me.
	for(sint i=0; i<_NPatchs; i++)
	{
		// The edge of the neihbor on which we are binded.
		sint	edgeNeighbor= bindInfo.Edge[i];
		CPatch	*paNeighbor= bindInfo.Next[i];
		_NeighborPatch[i]= paNeighbor;


		// Find uvI, uvJ, uvP such that:
		// uvOut= uvIn.x * uvI + uvIn.y * uvJ + uvP.
		CVector2f		&uvI= _NeighborBasis[i].UvI;
		CVector2f		&uvJ= _NeighborBasis[i].UvJ;
		CVector2f		&uvP= _NeighborBasis[i].UvP;


		// Find the basis MeToNeighbor.
		//=============================
		sint	rotation= (edgeCenter - edgeNeighbor + 4) & 3;
		// Find scale to apply.
		float	scX, scY;
		// If our neighbor edge is a vertical edge
		if( (edgeNeighbor&1)==0 )
		{
			scX= 1;

			// Manage difference of Order at the edge.
			scY= (float)paNeighbor->getOrderForEdge(edgeNeighbor) / (float)patchCenter->getOrderForEdge(edgeCenter);
			// Manage bind on the edge.
			// If patchCenter is binded on a bigger
			if(bindInfo.MultipleBindNum!=0)
				scY/= bindInfo.MultipleBindNum;
			if(_NPatchs>1)
				scY*= _NPatchs;
			// same TileOrder on the edge??
			if(scY!=1)
				_SameEdgeOrder= false;
		}
		else
		{
			scY= 1;

			// Manage difference of Order at the edge.
			scX= (float)paNeighbor->getOrderForEdge(edgeNeighbor) / (float)patchCenter->getOrderForEdge(edgeCenter);
			// Manage bind on the edge.
			// If patchCenter is binded on a bigger
			if(bindInfo.MultipleBindNum!=0)
				scX/= bindInfo.MultipleBindNum;
			if(_NPatchs>1)
				scX*= _NPatchs;
			// same TileOrder on the edge??
			if(scX!=1)
				_SameEdgeOrder= false;
		}
		// Find rotation to apply.
		switch(rotation)
		{
		case 0: uvI.set(-scX, 0); uvJ.set(0, -scY);	break;
		case 1: uvI.set(0, -scY); uvJ.set(scX, 0);	break;
		case 2: uvI.set(scX, 0); uvJ.set(0, scY);	break;
		case 3: uvI.set(0, scY); uvJ.set(-scX, 0);	break;
		}


		// Find the position.
		//=============================
		// Find the uv coord at start of the edge, for 2 patchs.
		CVector2f		uvCenter;
		CVector2f		uvNeighbor;
		float	decal;

		// find the uv at start of edgeCenter, + decal due to bind 1/X.
		float	ocS= patchCenter->getOrderS();
		float	ocT= patchCenter->getOrderT();
		// Manage Bind 1/X.
		if(_NPatchs>1)
		{
			// Move uvCenter, so it is near the position at start of edgeNeighbor.
			decal= (float)i / _NPatchs;
		}
		else
			decal= 0;
		// Manage rotation.
		switch(edgeCenter)
		{
		case 0: uvCenter.set(0, decal*ocT);		break;
		case 1: uvCenter.set(decal*ocS, ocT);	break;
		case 2: uvCenter.set(ocS, (1-decal)*ocT);	break;
		case 3: uvCenter.set((1-decal)*ocS, 0);	break;
		};

		// find the uv at start of edgeNeighbor, + decal due to bind X/1.
		float	onS= paNeighbor->getOrderS();
		float	onT= paNeighbor->getOrderT();
		// Manage Bind X/1.
		if(bindInfo.MultipleBindNum!=0)
		{
			// Must invert the id, because of mirror.... (make a draw).
			sint	id= (bindInfo.MultipleBindNum-1) - bindInfo.MultipleBindId;
			// Move uvNeighbor, so it is near the position at start of edgeCenter.
			decal= (float)id / bindInfo.MultipleBindNum;
		}
		else
			decal= 0;
		// Manage rotation.
		switch(edgeNeighbor)
		{
		case 0: uvNeighbor.set(0, (1-decal)*onT);		break;
		case 1: uvNeighbor.set((1-decal)*onS, onT);	break;
		case 2: uvNeighbor.set(onS, decal*onT);		break;
		case 3: uvNeighbor.set(decal*onS, 0);		break;
		};



		// uvOut= uvIn.x * uvI + uvIn.y * uvJ + uvP.
		// So uvP  = uvOut - uvIn.x * uvI - uvIn.y * uvJ
		uvP= uvNeighbor - uvCenter.x * uvI - uvCenter.y * uvJ;

	}
}
Example #2
0
//*********************************************************************************************************
void CInstanceMapDeco::onUpdate(CGroupMap &groupMap)
{
	//H_AUTO(R2_CInstanceMapDeco_onUpdate)
	if (!_Active) return;
	nlassert(_Instance);
	_GlowStarActive = false;
	if (!_Main || !_Over || !_OverInvalid) return;
	sint32 x;
	sint32 y;
	CVector2f worldPos = getWorldPos();
	// if not in current map then don't disply anything
	CIslandCollision &col = getEditor().getIslandCollision();
	R2::CScenarioEntryPoints::CCompleteIsland	*currIsland = col.getCurrIslandDesc();
	if (currIsland)
	{
		if (!currIsland->isIn(worldPos))
		{
			setActive(false);
			return;
		}
	}
	groupMap.worldToWindowSnapped(x, y, getWorldPos());
	_Main->setX(x);
	_Main->setY(y);
	CDisplayerVisual *vd = _Instance->getDisplayerVisual();
	if (!vd)
	{
		_Over->setActive(false);
		_OverInvalid->setActive(false);
		return;
	}
	//
	bool closeView = _CloseTexture.empty() ? false : groupMap.getMeterPerPixel() < CV_MapEntityCloseDist.get();
	//
	bool selected = vd->getDisplayFlag(CDisplayerVisual::FlagSelected);
	bool hasFocus = vd->getDisplayFlag(CDisplayerVisual::FlagHasFocus);
	//
	setTextureAndFit(closeView ? _CloseTexture : CV_MapEntitySmallTexture.get());
	_Main->setColor((selected && ! closeView) ? CV_MapEntitySelectColor.get() : vd->getDisplayModeColorInMap()); // if small icon, then change the icon color directly, because no over will be displayed
	//
	if (selected || hasFocus)
	{
		// if the selection is out of the window, then draw an arrow to locate it
		const CVector2f &wmin = groupMap.getVisibleWorldMin();
		const CVector2f &wmax = groupMap.getVisibleWorldMax();
		if (worldPos.x < wmin.x || worldPos.x > wmax.x ||
			worldPos.y < wmin.y || worldPos.y > wmax.y)
		{
			// OUT OF VISIBLE REGION CASE
			_Over->setActive(true);
			_Over->setColorRGBA(selected ? CV_MapEntitySelectColor.get() : CV_MapEntityHighlightColor.get());
			// out of the visible portion, so draw an arrow instead
			_Over->setTexture(CV_MapEntityFarTexture.get());
			// snap position to inner visible world rect
			CVector2f m = 0.5f * (wmin + wmax);
			CVector2f dir = worldPos - m;
			CVector2f inter;
			float d0;
			float d1;
			if (dir.x > 0.f)
			{
				d0 = (wmax.x - m.x) / dir.x;
				if (dir.y > 0.f)
				{
					d1 = (wmax.y - m.y) / dir.y;
					inter = m + std::min(d0, d1) * dir;
				}
				else if (dir.y < 0.f)
				{
					d1 = (wmin.y - m.y) / dir.y;
					inter = m + std::min(d0, d1) * dir;
				}
				else
				{
					inter.set(wmax.x, m.y);
				}
			}
			else if (dir.x < 0.f)
			{
				d0 = (wmin.x - m.x) / dir.x;
				if (dir.y > 0.f)
				{
					d1 = (wmax.y - m.y) / dir.y;
					inter = m + std::min(d0, d1) * dir;
				}
				else if (dir.y < 0.f)
				{
					d1 = (wmin.y - m.y) / dir.y;
					inter = m + std::min(d0, d1) * dir;
				}
				else
				{
					inter.set(wmin.x, m.y);
				}
			}
			else
			{
				if (dir.y > 0.f)
				{
					inter.set(m.x, wmax.y);
				}
				else if (dir.y < 0.f)
				{
					inter.set(m.x, wmin.y);
				}
				else
				{
					inter = m;
				}
			}
			float size = CV_MapEntityFarArrowSize.get();
			// TMP TMP
			size = size;
			float bias = 1.f;
			dir.normalize();
			CVector2f winInter;
			groupMap.worldToWindow(winInter, inter);

			_Over->setRenderLayer(3);
			_Over->setQuad(winInter - (size + bias) * dir, winInter - bias * dir, 0.5f * size);
			//
			if (_GlowStar[0])
			{
				sint32 screenInterX, screenInterY;
				groupMap.windowToScreen(screenInterX, screenInterY, (sint32) winInter.x, (sint32) winInter.y);
				sint32 refCornerX, refCornerY;
				_GlowStar[0]->getParent()->getCorner(refCornerX, refCornerY, Hotspot_BL);
				_GlowStarPos.set((float) (screenInterX - refCornerX), (float) (screenInterY - refCornerY), 0.f);
				_GlowStarActive = true;
			}
		}
		else
		{
			// VISIBLE CASE
			_GlowStar[0]->setActive(false);
			_GlowStar[1]->setActive(false);
			if (closeView || hasFocus)
			{
				_Over->setActive(true);
				if (!closeView)
				{
					_Over->setColorRGBA(CV_MapEntitySelectColor.get());
				}
				else
				{
					_Over->setColorRGBA(selected ? CV_MapEntitySelectColor.get() : CV_MapEntityHighlightColor.get());
				}
				const std::string &tex = closeView ? CV_MapEntitySelectTexture.get() : CV_MapEntitySmallHighlightTexture.get();
				_Over->setTexture(tex);
				_Over->setRenderLayer(2);
				_Over->setQuad(tex, CVector((float) x, (float) y, 0.f));
			}
			else
			{
				_Over->setActive(false);
			}
		}
	}
	else
	{
		// no focus
		_Over->setActive(false);
		_GlowStar[0]->setActive(false);
		_GlowStar[1]->setActive(false);
	}
	// update 'quad that signal invalid pos'
	if (_OverInvalid->getActive())
	{
		const std::string &tex = closeView ? CV_MapEntityInvalidTexture.get() : CV_MapEntityInvalidTextureSmall.get();
		_OverInvalid->setTexture(tex);
		_OverInvalid->setQuad(tex, CVector((float) x, (float) y, 0.f));
	}
}