chasctxt.cpp

来自「Windows上的MUD客户端程序」· C++ 代码 · 共 993 行 · 第 1/2 页

CPP
993
字号

			#if defined(CH_USE_D3D)
			//ChColor chromaKey = pTxt->GetChromaKey();
			pTxt->GetHandle()->SetDecalTransparency(true);
			pTxt->GetHandle()->SetDecalTransparentColor(*(chromaKey.GetNative()));
			#endif
			ChNrMeshSetTexture( mesh, pTxt->GetHandle());
			D3DRelease(pTxt->GetHandle());

			if(numFacesAdded) boolFilled = true;

			unsigned int iface = 0;
			ChNrFace elt;
			int count = ChNrFaceGetVertexCount(GetElement(facesAdded,iface,elt));

			for(int k = 0; k < count; k++)
			{				
				int index = ChNrFaceGetVertexIndex(elt, k);
				float y = k < 2 ? 0 : 1;
				float x = (k == 0 || k == 3) ? 0 : 1; 
				ChNrMeshSetTextureCoordinates(mesh, index, x, y);
			}

			D3DRelease(elt);
			ChNrFree(facesAdded);							  
		}
		// end textured text
		 
		#else	// don't USE_TEXTURE_TEXT


				  // Do it with facets or wireframes
		ChNrMeshSetQuality(mesh,RenderWireframe);  

		// Decide how many normals to store; we need both front and back if not backculled
		int numNorms = 0;

		// Need to reserve space for vertices, normals, and faces - ?? but how much?


		int iAscent = 30;
		bool boolWireframe = true;

		hFont = CreateFont(iAscent);

		int xAdvance, yAdvance;

		ChQvAsciiTextMaterials materialMap( this);
		pRC->AdjustTransparency(materialMap);

		float fontSize = GetFontStyle()->size.value;

		for(int line = 0; line < pNode->string.num; line++)
		{
												// 'string' field is really QvMFString
			string text = pNode->string.values[line].getString();

			int numChars = text.GetLength();

			float width = GetTextWidth(hFont, line);

			GxVec3f p;
			switch(pNode->justification.value)
			{
				case QvAsciiText::LEFT:
					 p.x() = 0.;	
					break;
				case QvAsciiText::RIGHT:
					p.x() = -width;
					break;
				case QvAsciiText::CENTER:
					p.x() = -width / 2;
					break;
			}
			p.y() = /*-GetBaselineOffset()*/ - line * pNode->spacing.value * fontSize;	// chars ought be on baseline 
			p.z() = 0;
	  		float xChar = 0, yChar = 0; 	  // current character position
			for( int j = 0; j < numChars; j++ )
			{
				// Do a glyph
	  			unsigned int letter = text[j];
	  			ChPolyPolygonGx3 *pPoly;
				pPoly = CreateGlyphPolyPoly (hFont, letter, iAscent, xAdvance, yAdvance);
				if(pPoly && pPoly->GetPointCount())
				{
					boolFilled = true;
					// Convexify pPoly if not wireframe
					if (!boolWireframe) {
						// Replace pPoly with a convexified version of itself
						ChPolyPolygonGx3 *pPoly2 = pPoly->Convexify();
						delete pPoly;
						pPoly = pPoly2;
					}
					
					int numVertsTotal = pPoly->GetPointCount();
					int numFaces = pPoly->GetPolyCount();
					int face_data_size = numVertsTotal * 2 		// point indices; no normals - 2 is for backs
										+ numFaces * 2 				// face counts
										+ 1;					// terminator

					int * face_data = new int[face_data_size];

					GxVec3f *points 	= new GxVec3f[numVertsTotal];
					
					int vertIndex = 0;
					int ifd = 0;	// Index to Face Data
					
					for(int poly = 0; poly < pPoly->GetPolyCount(); poly++)
					{
						int nVerts = pPoly->GetPointCount(poly);
						if(nVerts)
						{	
							face_data[ifd]  = face_data[ifd + nVerts + 1] = nVerts; 
							ifd ++;

							for(int k = 0; k < nVerts; k++)
							{
								GxVec3f ip = pPoly->GetPoint(poly, k);
								points[vertIndex].x() = p.x() + xChar + float(ip.x()) / iAscent * fontSize;
								points[vertIndex].y() = p.y() + yChar + float(ip.y()) / iAscent * fontSize;
								points[vertIndex].z() = 0;
								face_data[ifd+k] = vertIndex;
								int reverseIndex = ifd + nVerts + nVerts - k;
								face_data[reverseIndex] = vertIndex;
								vertIndex++;
							}

							ifd += nVerts + nVerts + 1;
						}
					}
					face_data[ifd] = 0;

					ChNrFace *facesAdded;
					int numFacesAdded;
					ChNrMeshAddFaces(m_mesh,
							       numVertsTotal,
							       (ChNrVector*) points,
							       0,
							       (ChNrVector*) 0,
							       face_data,
							       &numFacesAdded,
							       &facesAdded);

					for(int j = 0; j < numFacesAdded; j ++)
					{
						materialMap.Set(m_mesh, facesAdded[j]);
					}

			 		ChNrFree(facesAdded);							  
					delete [] face_data; 
					delete [] points; 
				}

				delete pPoly;
			
				xChar += float(xAdvance) / iAscent * fontSize;
				yChar += float(yAdvance) / iAscent * fontSize;
	
			}
		}
		#endif
		if(!boolFilled)
		{
			ChNrFrame parent;
			ChNrFrameGetParent(m_frame, parent);
			ChNrFrameRemoveChild(parent, m_frame);
			m_frame = 0;
			m_mesh = 0;
		}
		DeleteObject(hFont);

		pIterator->DidAShape();
		pRC->UnlockScene();		
		pRC->UnlockQv();		   // Unlock tree 
	}
#endif
	return true;
}

bool ChQvAsciiTextInstance::Draw(ChRenderContext *pRC, ChDrawIterator *pIterator)
{
#if defined( CH_USE_3DR )
	{
		Fixed32_t On = 1;
		Fixed32_t Off = 0;
		static  PointF_t norm =		{ 0, 0, 1};
		G3dHandle_t hGC = pRC->GetGC();
		Dword_t  hRC = pRC->GetRC();
		QvAsciiText *pNode = (QvAsciiText *)GetNode();
		pRC->SetModelTransform(GetTransform());
		bool boolWireframe = 1;

		Fixed32_t oldShading;
	    G3dGetState( hGC, G3DL_FLAT_SHADING, &oldShading);
	    G3dSetState( hGC, G3DL_FLAT_SHADING, &On);
		Dword_t disabled = ( hRC, R3D_STA_DISABLES );
		Dword_t enabled = ( hRC, R3D_STA_ENABLES );
		R3dSetState( hRC, R3D_STA_ENABLES, R3D_SE_CLIPPING);  // I need them to clip for me too
															  // because I'm not pixel accurate

		pRC->SetShading(this);
	    R3dSetState( hRC, R3D_STA_DISABLES, R3D_SE_SHADING);

		Float_t		cull = 0;	   // never backcull text
		Fixed32_t wMattNum = 0;	  // always use material 0
		G3dSetMatt( hGC,  wMattNum, G3DM_BACK_CULL,	(Float_t *)&cull );
	
		// Check for cache
		bool boolFirst = false;
		if(!m_pCache)
		{
			boolFirst = true;
			m_pCache = new ChPtrList<ChAsciiCharCache>;
		}
		ChPosition pos = 0;
		if (!boolFirst)
		{
			pos = m_pCache->GetHeadPosition();	 // Initial position if reading cache
		}
	 
		bool boolUseTexture = SetupTexture(pRC);

		int iAscent = 20;	// LOD later

		// LOD computation
		// Base it on a 1 char square at the origin
		//iAscent = int(GetFontLODHeight(pRC));	 - we're caching instead now

		HFONT hFont = CreateFont(iAscent);
		// cache more intelligently later

		int xAdvance, yAdvance;

		Fixed32_t lCCW;
		G3dGetState( hGC, G3DL_FRONT_CCW, &lCCW);
		G3dSetState( hGC, G3DL_FRONT_CCW, &On);

		bool boolPureEmissive;
		ChQvAsciiTextMaterials materialMap( this);
		materialMap.Set(hRC, hGC, &boolPureEmissive);

		ColorFA_t color, diff, emissive;
		G3dGetMatt(hGC, 0, G3DM_DIFFUSE, (float*)&diff);
		G3dGetMatt(hGC, 0, G3DM_EMIT, (float*)&emissive);
		ColorFA_t black = {0.,0., 0., 0.};

		// We're using prelit colors
		// Bogus em up by assuming a light value of  white .5
		// ignoring specular and Lambertian effects
		// Conversely, you could assume light = 1 and cos(theta) = .5 for diffuse
		// These are so dinky nobody's gonna notice
		//color.r = diff.r / 2 + emissive.r;
		//color.g = diff.g / 2 + emissive.g;
		//color.b = diff.b / 2 + emissive.b;
		color.r = max(diff.r, emissive.r);
		color.g = max(diff.g, emissive.g);
		color.b = max(diff.b, emissive.b);
		color.a = 1.0;
		unsigned long r, g, b, val;
		G3dSetMatt(hGC, 0, G3DM_EMIT, (float*)&color);
		G3dSetMatt(hGC, 0, G3DM_DIFFUSE, (float*)&black);
		G3dSetMatt(hGC, 0, G3DM_BACK_EMIT, (float*)&color);
		G3dSetMatt(hGC, 0, G3DM_BACK_DIFFUSE, (float*)&black);

		r = long( color.r * 255.0 );
		g = long( color.g * 255.0 );
		b = long( color.b * 255.0 );
		val = r | (g << 8) | (b << 16) | 0xff000000;

		R3dSetState( hRC, R3D_STA_FG_COLOR, val); 


		pRC->SetModulation( boolUseTexture, boolPureEmissive);  // 
		float fontSize = GetFontStyle()->size.value;

		for(int line = 0; line < pNode->string.num; line++)
		{
												// 'string' field is really QvMFString
			string text = pNode->string.values[line].getString();

			int numChars = text.GetLength();


			float width = GetTextWidth(hFont, line);
			ColorFA_t purple = {.8, 0., .8, 1.};

			PointF_t p;
			switch(pNode->justification.value)
			{
				case QvAsciiText::LEFT:
					 p.x = 0.;	
					break;
				case QvAsciiText::RIGHT:
					p.x = -width;
					break;
				case QvAsciiText::CENTER:
					p.x = -width / 2;
					break;
			}
			p.y = /*-GetBaselineOffset()*/ - line * pNode->spacing.value * fontSize;	// chars ought be on baseline 
			p.z = 0;
	  		float xChar = 0, yChar = 0; 	  // current character position
			for( int j = 0; j < numChars; j++ )
			{
	  			unsigned int letter = text[j];
	  			ChPolyPolygonGx3 *pPoly;
				if(boolFirst)
				{
					pPoly = CreateGlyphPolyPoly (hFont, letter, iAscent, xAdvance, yAdvance);
					ChAsciiCharCache *pCache = new ChAsciiCharCache(pPoly, letter, xAdvance, yAdvance);
					m_pCache->AddTail(pCache);
				}
				else
				{
					// Get from cache
					ChAsciiCharCache *pCharCache = m_pCache->GetNext(pos);
					pPoly = pCharCache->m_pPoly;
					xAdvance = pCharCache->m_xAdvance;
					yAdvance = pCharCache->m_yAdvance;
				}
				if(pPoly)
				{
					// Convexify pPoly if not wireframe
					if (!boolWireframe) {
						// Replace pPoly with a convexified version of itself
						ChPolyPolygonGx3 *pPoly2 = pPoly->Convexify();
						delete pPoly;
						pPoly = pPoly2;
					}
					for(int poly = 0; poly < pPoly->GetPolyCount(); poly++)
					{
						int nVerts = pPoly->GetPointCount(poly);
						if(nVerts)
						{	
							PointF_t *points 	= new PointF_t[nVerts];
							PointF_t *normals 	= new PointF_t[nVerts];
							#if 0	
							PointF_t *textures 	= new PointF_t[nVerts];
							ColorFA_t *colors 	= new ColorFA_t[nVerts];;
							#endif

							for(int k = 0; k < nVerts; k++)
							{
								GxVec3f ip = pPoly->GetPoint(poly, k);
								points[k].x = p.x + xChar + float(ip.x()) / iAscent * fontSize;
								points[k].y = p.y + yChar + float(ip.y()) / iAscent * fontSize;
								points[k].z = 0;
								normals[k] = norm;
							#if 0	
								colors[k] = color;
								textures[k].x = float(ip.x) / iAscent;
								textures[k].y = float(ip.y) / iAscent;
								textures[k].z = 0.;
							#endif
							}

							if(boolWireframe)
							{
								        G3dSetState( hGC, G3DL_FLAT_SHADING, &On);

								try
								{

								#if 0
									for(int k = 0; k < nVerts - 1; k++)
									{
										G3dPrimitiveF(hGC, G3D_PRM_POLYLINE, 2,
													points + k, sizeof(PointF_t), 
													&norm, sizeof(PointF_t), 
													//0, sizeof(PointF_t), 
													0, sizeof(PointF_t), 
													0, sizeof(ColorFA_t) );

									}
								#else
									G3dPrimitiveF(hGC, G3D_PRM_POLYLINE, nVerts,
												points, sizeof(PointF_t), 
												normals, sizeof(PointF_t), 
												//0, sizeof(PointF_t), 
												0, sizeof(PointF_t), 
												0, sizeof(ColorFA_t) );
								#endif
								}
								catch (...)
								{
									//TRACE("Exception in drawing text polyline caught\r\n");
								}
								        G3dSetState( hGC, G3DL_FLAT_SHADING, &Off);
							}
							else
							{
								#if 0
								// Triangulate here
								try
								{
									G3dPrimitiveF(hGC, G3D_PRM_POLYGON, nVerts,
												points, sizeof(PointF_t), 
												normals, sizeof(PointF_t), 
												textures, sizeof(PointF_t), 
												colors, sizeof(ColorFA_t) );
								}
								catch (...)
								{
									//TRACE("Exception in drawing text polygon caught\r\n");
								}
								#endif
							}
							delete [] points; 
							delete [] normals; 
							#if 0
							delete [] textures;
							delete [] colors;
							#endif
						}
					}
				}
				#if 0
				#endif
				//delete pPoly;	  // cached now
			
				xChar += float(xAdvance) / iAscent * fontSize;
				yChar += float(yAdvance) / iAscent * fontSize;
	
			}
		}
		
		DeleteObject(hFont);
		G3dSetState( hGC, G3DL_FRONT_CCW, &lCCW);
		{
			pRC->SetTexture(0);							// turn off texture
		}
		R3dSetState( hRC, R3D_STA_DISABLES, disabled ); 
		R3dSetState( hRC, R3D_STA_ENABLES, enabled);
	    G3dSetState( hGC, G3DL_FLAT_SHADING, &oldShading);
	}
#else
#endif
	return true;
}

HFONT ChQvAsciiTextInstance::CreateFont(int iAscent, float aspect)		// very Windows-y
{	
	HFONT	hMyFont;
	LOGFONT lf;

	GetObject(GetStockObject(SYSTEM_FONT), sizeof(lf), &lf);
	lf.lfHeight = iAscent;
	lf.lfWidth = 0;
	switch(GetFontStyle()->family.value)
	{
		case QvFontStyle::SERIF:
		{
			strcpy(lf.lfFaceName, "Times New Roman");
			break;
		}
		case QvFontStyle::TYPEWRITER:
		{
			strcpy(lf.lfFaceName, "Courier New");
			break;
		}
		default:	// QvFontStyle::SANS or whatever
		{
			strcpy(lf.lfFaceName, "Arial");
			break;
		}
	}
	if(GetFontStyle()->style.value	& QvFontStyle::BOLD)
	{
		lf.lfWeight = 700; 
	}
	if(GetFontStyle()->style.value	& QvFontStyle::ITALIC)
	{
		lf.lfItalic = true;
	}
	hMyFont = CreateFontIndirect(&lf);

	if(aspect != 0.0)
	{
		// Tweak the aspect ratio to fit our mutated shape
		TEXTMETRIC tm;
		CDC dc;
		dc.CreateCompatibleDC(0);
		CFont *pOldFont = dc.SelectObject(CFont::FromHandle(hMyFont));
		dc.GetTextMetrics(&tm);
		dc.SelectObject(pOldFont);

		lf.lfWidth = int(tm.tmAveCharWidth * aspect);

		DeleteObject(hMyFont);
		hMyFont = CreateFontIndirect(&lf);

	}

	return hMyFont;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?