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 + -
显示快捷键?