1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #pragma hdrstop
- #include "../idlib/precompiled.h"
- #include "../renderer/tr_local.h"
- idCVar swf_timescale( "swf_timescale", "1", CVAR_FLOAT, "timescale for swf files" );
- idCVar swf_stopat( "swf_stopat", "0", CVAR_FLOAT, "stop at a specific frame" );
- idCVar swf_titleSafe( "swf_titleSafe", "0.005", CVAR_FLOAT, "space between UI elements and screen edge", 0.0f, 0.075f );
- idCVar swf_forceAlpha( "swf_forceAlpha", "0", CVAR_FLOAT, "force an alpha value on all elements, useful to show invisible animating elements", 0.0f, 1.0f );
- extern idCVar swf_textStrokeSize;
- extern idCVar swf_textStrokeSizeGlyphSpacer;
- extern idCVar in_useJoystick;
- #define ALPHA_EPSILON 0.001f
- #define STENCIL_DECR -1
- #define STENCIL_INCR -2
- /*
- ========================
- idSWF::DrawStretchPic
- ========================
- */
- void idSWF::DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial *material ) {
- renderSystem->DrawStretchPic( x * scaleToVirtual.x, y * scaleToVirtual.y, w * scaleToVirtual.x, h * scaleToVirtual.y, s1, t1, s2, t2, material );
- }
- /*
- ========================
- idSWF::DrawStretchPic
- ========================
- */
- void idSWF::DrawStretchPic( const idVec4 & topLeft, const idVec4 & topRight, const idVec4 & bottomRight, const idVec4 & bottomLeft, const idMaterial * material ) {
- renderSystem->DrawStretchPic(
- idVec4( topLeft.x * scaleToVirtual.x, topLeft.y * scaleToVirtual.y, topLeft.z, topLeft.w ),
- idVec4( topRight.x * scaleToVirtual.x, topRight.y * scaleToVirtual.y, topRight.z, topRight.w ),
- idVec4( bottomRight.x * scaleToVirtual.x, bottomRight.y * scaleToVirtual.y, bottomRight.z, bottomRight.w ),
- idVec4( bottomLeft.x * scaleToVirtual.x, bottomLeft.y * scaleToVirtual.y, bottomLeft.z, bottomLeft.w ),
- material );
- }
- /*
- ========================
- idSWF::Render
- ========================
- */
- void idSWF::Render( idRenderSystem * gui, int time, bool isSplitscreen ) {
- if ( !IsLoaded() ) {
- return;
- }
- if ( !IsActive() ) {
- return;
- }
- if ( swf_stopat.GetInteger() > 0 ) {
- if ( mainspriteInstance->currentFrame == swf_stopat.GetInteger() ) {
- swf_timescale.SetFloat( 0.0f );
- }
- }
- int currentTime = Sys_Milliseconds();
- int framesToRun = 0;
- if ( paused ) {
- lastRenderTime = currentTime;
- }
- if ( swf_timescale.GetFloat() > 0.0f ) {
- if ( lastRenderTime == 0 ) {
- lastRenderTime = currentTime;
- framesToRun = 1;
- } else {
- float deltaTime = ( currentTime - lastRenderTime );
- float fr = ( (float)frameRate / 256.0f ) * swf_timescale.GetFloat();
- framesToRun = idMath::Ftoi( ( fr * deltaTime ) / 1000.0f );
- lastRenderTime += ( framesToRun * ( 1000.0f / fr ) );
- if ( framesToRun > 10 ) {
- framesToRun = 10;
- }
- }
- for ( int i = 0; i < framesToRun; i++ ) {
- mainspriteInstance->Run();
- mainspriteInstance->RunActions();
- }
- }
- const float pixelAspect = renderSystem->GetPixelAspect();
- const float sysWidth = renderSystem->GetWidth() * ( pixelAspect > 1.0f ? pixelAspect : 1.0f );
- const float sysHeight = renderSystem->GetHeight() / ( pixelAspect < 1.0f ? pixelAspect : 1.0f );
- float scale = swfScale * sysHeight / (float)frameHeight;
- swfRenderState_t renderState;
- renderState.stereoDepth = (stereoDepthType_t)mainspriteInstance->GetStereoDepth();
- renderState.matrix.xx = scale;
- renderState.matrix.yy = scale;
- renderState.matrix.tx = 0.5f * ( sysWidth - ( frameWidth * scale ) );
- renderState.matrix.ty = 0.5f * ( sysHeight - ( frameHeight * scale ) );
- renderBorder = renderState.matrix.tx / scale;
- scaleToVirtual.Set( (float)SCREEN_WIDTH / sysWidth, (float)SCREEN_HEIGHT / sysHeight );
- RenderSprite( gui, mainspriteInstance, renderState, time, isSplitscreen );
- if ( blackbars ) {
- float barWidth = renderState.matrix.tx + 0.5f;
- float barHeight = renderState.matrix.ty + 0.5f;
- if ( barWidth > 0.0f ) {
- gui->SetColor( idVec4( 0.0f, 0.0f, 0.0f, 1.0f ) );
- DrawStretchPic( 0.0f, 0.0f, barWidth, sysHeight, 0, 0, 1, 1, white );
- DrawStretchPic( sysWidth - barWidth, 0.0f, barWidth, sysHeight, 0, 0, 1, 1, white );
- }
- if ( barHeight > 0.0f ) {
- gui->SetColor( idVec4( 0.0f, 0.0f, 0.0f, 1.0f ) );
- DrawStretchPic( 0.0f, 0.0f, sysWidth, barHeight, 0, 0, 1, 1, white );
- DrawStretchPic( 0.0f, sysHeight - barHeight, sysWidth, barHeight, 0, 0, 1, 1, white );
- }
- }
- if ( isMouseInClientArea && ( mouseEnabled && useMouse ) && ( InhibitControl() || ( !InhibitControl() && !useInhibtControl ) ) ) {
- gui->SetGLState( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
- gui->SetColor( idVec4( 1.0f, 1.0f, 1.0f, 1.0f ) );
- idVec2 mouse = renderState.matrix.Transform( idVec2( mouseX - 1, mouseY - 2 ) );
- //idSWFScriptObject * hitObject = HitTest( mainspriteInstance, swfRenderState_t(), mouseX, mouseY, NULL );
- if ( !hasHitObject ) { //hitObject == NULL ) {
- DrawStretchPic( mouse.x, mouse.y, 32.0f, 32.0f, 0, 0, 1, 1, guiCursor_arrow );
- } else {
- DrawStretchPic( mouse.x, mouse.y, 32.0f, 32.0f, 0, 0, 1, 1, guiCursor_hand );
- }
- }
- // restore the GL State
- gui->SetGLState( 0 );
- }
- /*
- ========================
- idSWF::RenderMask
- ========================
- */
- void idSWF::RenderMask( idRenderSystem * gui, const swfDisplayEntry_t * mask, const swfRenderState_t & renderState, const int stencilMode ) {
- swfRenderState_t renderState2;
- renderState2.stereoDepth = renderState.stereoDepth;
- renderState2.matrix = mask->matrix.Multiply( renderState.matrix );
- renderState2.cxf = mask->cxf.Multiply( renderState.cxf );
- renderState2.ratio = mask->ratio;
- renderState2.material = guiSolid;
- renderState2.activeMasks = stencilMode;
- idSWFDictionaryEntry & entry = dictionary[ mask->characterID ];
- if ( entry.type == SWF_DICT_SHAPE ) {
- RenderShape( gui, entry.shape, renderState2 );
- } else if ( entry.type == SWF_DICT_MORPH ) {
- RenderMorphShape( gui, entry.shape, renderState2 );
- }
- }
- /*
- ========================
- idSWF::RenderSprite
- ========================
- */
- void idSWF::RenderSprite( idRenderSystem * gui, idSWFSpriteInstance * spriteInstance, const swfRenderState_t & renderState, int time, bool isSplitscreen ) {
- if ( spriteInstance == NULL ) {
- idLib::Warning( "%s: RenderSprite: spriteInstance == NULL", filename.c_str() );
- return;
- }
- if ( !spriteInstance->isVisible ) {
- return;
- }
- if ( ( ( renderState.cxf.mul.w + renderState.cxf.add.w ) <= ALPHA_EPSILON ) && ( swf_forceAlpha.GetFloat() <= 0.0f ) ) {
- return;
- }
- idStaticList<const swfDisplayEntry_t *, 256> activeMasks;
- for ( int i = 0; i < spriteInstance->displayList.Num(); i++ ) {
- const swfDisplayEntry_t & display = spriteInstance->displayList[i];
- for ( int j = 0; j < activeMasks.Num(); j++ ) {
- const swfDisplayEntry_t * mask = activeMasks[ j ];
- if ( display.depth > mask->clipDepth ) {
- RenderMask( gui, mask, renderState, STENCIL_DECR );
- activeMasks.RemoveIndexFast( j );
- }
- }
- if ( display.clipDepth > 0 ) {
- activeMasks.Append( &display );
- RenderMask( gui, &display, renderState, STENCIL_INCR );
- continue;
- }
- idSWFDictionaryEntry * entry = FindDictionaryEntry( display.characterID );
- if ( entry == NULL ) {
- continue;
- }
- swfRenderState_t renderState2;
- if ( spriteInstance->stereoDepth != STEREO_DEPTH_TYPE_NONE ) {
- renderState2.stereoDepth = ( stereoDepthType_t )spriteInstance->stereoDepth;
- } else if ( renderState.stereoDepth != STEREO_DEPTH_TYPE_NONE ) {
- renderState2.stereoDepth = renderState.stereoDepth;
- }
- renderState2.matrix = display.matrix.Multiply( renderState.matrix );
- renderState2.cxf = display.cxf.Multiply( renderState.cxf );
- renderState2.ratio = display.ratio;
- if ( display.blendMode != 0 ) {
- renderState2.blendMode = display.blendMode;
- } else {
- renderState2.blendMode = renderState.blendMode;
- }
- renderState2.activeMasks = renderState.activeMasks + activeMasks.Num();
- if ( spriteInstance->materialOverride != NULL ) {
- renderState2.material = spriteInstance->materialOverride;
- renderState2.materialWidth = spriteInstance->materialWidth;
- renderState2.materialHeight = spriteInstance->materialHeight;
- } else {
- renderState2.material = renderState.material;
- renderState2.materialWidth = renderState.materialWidth;
- renderState2.materialHeight = renderState.materialHeight;
- }
- float xOffset = 0.0f;
- float yOffset = 0.0f;
- if ( entry->type == SWF_DICT_SPRITE ) {
- display.spriteInstance->SetAlignment( spriteInstance->xOffset, spriteInstance->yOffset );
- if ( display.spriteInstance->name[0] == '_' ) {
- //if ( display.spriteInstance->name.Icmp( "_leftAlign" ) == 0 ) {
- // float adj = (float)frameWidth * 0.10;
- // renderState2.matrix.tx = ( display.matrix.tx - adj ) * renderState.matrix.xx;
- //}
- //if ( display.spriteInstance->name.Icmp( "_rightAlign" ) == 0 ) {
- // renderState2.matrix.tx = ( (float)renderSystem->GetWidth() - ( ( (float)frameWidth - display.matrix.tx - adj ) * renderState.matrix.xx ) );
- //}
-
- float widthAdj = swf_titleSafe.GetFloat() * frameWidth;
- float heightAdj = swf_titleSafe.GetFloat() * frameHeight;
- const float pixelAspect = renderSystem->GetPixelAspect();
- const float sysWidth = renderSystem->GetWidth() * ( pixelAspect > 1.0f ? pixelAspect : 1.0f );
- const float sysHeight = renderSystem->GetHeight() / ( pixelAspect < 1.0f ? pixelAspect : 1.0f );
- if ( display.spriteInstance->name.Icmp( "_fullScreen" ) == 0 ) {
- renderState2.matrix.tx = display.matrix.tx * renderState.matrix.xx;
- renderState2.matrix.ty = display.matrix.ty * renderState.matrix.yy;
- float xScale = sysWidth / (float)frameWidth;
- float yScale = sysHeight / (float)frameHeight;
- renderState2.matrix.xx = xScale;
- renderState2.matrix.yy = yScale;
- }
- if ( display.spriteInstance->name.Icmp( "_absTop" ) == 0 ) {
- renderState2.matrix.ty = display.matrix.ty * renderState.matrix.yy;
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_top" ) == 0 ) {
- renderState2.matrix.ty = ( display.matrix.ty + heightAdj ) * renderState.matrix.yy;
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_topLeft" ) == 0 ) {
- renderState2.matrix.tx = ( display.matrix.tx + widthAdj ) * renderState.matrix.xx;
- renderState2.matrix.ty = ( display.matrix.ty + heightAdj ) * renderState.matrix.yy;
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_left" ) == 0 ) {
- float prevX = renderState2.matrix.tx;
- renderState2.matrix.tx = ( display.matrix.tx + widthAdj ) * renderState.matrix.xx;
- xOffset = (( renderState2.matrix.tx - prevX ) / renderState.matrix.xx );
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( idStr::FindText( display.spriteInstance->name, "_absLeft", false ) >= 0 ) {
- float prevX = renderState2.matrix.tx;
- renderState2.matrix.tx = display.matrix.tx * renderState.matrix.xx;
- xOffset = (( renderState2.matrix.tx - prevX ) / renderState.matrix.xx );
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_bottomLeft" ) == 0 ) {
- float prevX = renderState2.matrix.tx;
- renderState2.matrix.tx = ( display.matrix.tx + widthAdj ) * renderState.matrix.xx;
- xOffset = (( renderState2.matrix.tx - prevX ) / renderState.matrix.xx );
-
- float prevY = renderState2.matrix.ty;
- renderState2.matrix.ty = ( (float)sysHeight - ( ( (float)frameHeight - display.matrix.ty + heightAdj ) * renderState.matrix.yy ) );
- yOffset = (( renderState2.matrix.ty - prevY ) / renderState.matrix.yy );
-
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_absBottom" ) == 0 ) {
- renderState2.matrix.ty = ( (float)sysHeight - ( ( (float)frameHeight - display.matrix.ty ) * renderState.matrix.yy ) );
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_bottom" ) == 0 ) {
- renderState2.matrix.ty = ( (float)sysHeight - ( ( (float)frameHeight - display.matrix.ty + heightAdj ) * renderState.matrix.yy ) );
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_topRight" ) == 0 ) {
- renderState2.matrix.tx = ( (float)sysWidth - ( ( (float)frameWidth - display.matrix.tx + widthAdj ) * renderState.matrix.xx ) );
- renderState2.matrix.ty = ( display.matrix.ty + heightAdj ) * renderState.matrix.yy;
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_right" ) == 0 ) {
- float prevX = renderState2.matrix.tx;
- renderState2.matrix.tx = ( (float)sysWidth - ( ( (float)frameWidth - display.matrix.tx + widthAdj ) * renderState.matrix.xx ) );
- xOffset = (( renderState2.matrix.tx - prevX ) / renderState.matrix.xx );
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( idStr::FindText( display.spriteInstance->name, "_absRight", true ) >= 0 ) {
- float prevX = renderState2.matrix.tx;
- renderState2.matrix.tx = ( (float)sysWidth - ( ( (float)frameWidth - display.matrix.tx ) * renderState.matrix.xx ) );
- xOffset = (( renderState2.matrix.tx - prevX ) / renderState.matrix.xx );
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_bottomRight" ) == 0 ) {
- renderState2.matrix.tx = ( (float)sysWidth - ( ( (float)frameWidth - display.matrix.tx + widthAdj ) * renderState.matrix.xx ) );
- renderState2.matrix.ty = ( (float)sysHeight - ( ( (float)frameHeight - display.matrix.ty + heightAdj ) * renderState.matrix.yy ) );
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_absTopLeft" ) == 0 ) { // ABSOLUTE CORNERS OF SCREEN
- renderState2.matrix.tx = display.matrix.tx * renderState.matrix.xx;
- renderState2.matrix.ty = display.matrix.ty * renderState.matrix.yy;
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_absTopRight" ) == 0 ) {
- renderState2.matrix.tx = ( (float)sysWidth - ( ( (float)frameWidth - display.matrix.tx ) * renderState.matrix.xx ) );
- renderState2.matrix.ty = display.matrix.ty * renderState.matrix.yy;
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_absBottomLeft" ) == 0 ) {
- renderState2.matrix.tx = display.matrix.tx * renderState.matrix.xx;
- renderState2.matrix.ty = ( (float)sysHeight - ( ( (float)frameHeight - display.matrix.ty ) * renderState.matrix.yy ) );
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- } else if ( display.spriteInstance->name.Icmp( "_absBottomRight" ) == 0 ) {
- renderState2.matrix.tx = ( (float)sysWidth - ( ( (float)frameWidth - display.matrix.tx ) * renderState.matrix.xx ) );
- renderState2.matrix.ty = ( (float)sysHeight - ( ( (float)frameHeight - display.matrix.ty ) * renderState.matrix.yy ) );
- display.spriteInstance->SetAlignment( spriteInstance->xOffset + xOffset, spriteInstance->yOffset + yOffset );
- }
- }
-
- RenderSprite( gui, display.spriteInstance, renderState2, time, isSplitscreen );
- } else if ( entry->type == SWF_DICT_SHAPE ) {
- RenderShape( gui, entry->shape, renderState2 );
- } else if ( entry->type == SWF_DICT_MORPH ) {
- RenderMorphShape( gui, entry->shape, renderState2 );
- } else if ( entry->type == SWF_DICT_EDITTEXT ) {
- RenderEditText( gui, display.textInstance, renderState2, time, isSplitscreen );
- } else {
- //idLib::Warning( "%s: Tried to render an unrenderable character %d", filename.c_str(), entry->type );
- }
- }
- for ( int j = 0; j < activeMasks.Num(); j++ ) {
- const swfDisplayEntry_t * mask = activeMasks[ j ];
- RenderMask( gui, mask, renderState, STENCIL_DECR );
- }
- }
- /*
- ========================
- idSWF::GLStateForBlendMode
- ========================
- */
- uint64 idSWF::GLStateForRenderState( const swfRenderState_t & renderState ) {
- uint64 extraGLState = GLS_OVERRIDE | GLS_DEPTHFUNC_LESS | GLS_DEPTHMASK; // SWF GL State always overrides what's set in the material
- if ( renderState.activeMasks > 0 ) {
- extraGLState |= GLS_STENCIL_FUNC_EQUAL | GLS_STENCIL_MAKE_REF( 128 + renderState.activeMasks ) | GLS_STENCIL_MAKE_MASK( 255 );
- } else if ( renderState.activeMasks == STENCIL_INCR ) {
- return GLS_COLORMASK | GLS_ALPHAMASK | GLS_STENCIL_OP_FAIL_KEEP | GLS_STENCIL_OP_ZFAIL_KEEP | GLS_STENCIL_OP_PASS_INCR;
- } else if ( renderState.activeMasks == STENCIL_DECR ) {
- return GLS_COLORMASK | GLS_ALPHAMASK | GLS_STENCIL_OP_FAIL_KEEP | GLS_STENCIL_OP_ZFAIL_KEEP | GLS_STENCIL_OP_PASS_DECR;
- }
- switch ( renderState.blendMode ) {
- case 7: // difference : dst = abs( dst - src )
- case 9: // subtract : dst = dst - src
- return extraGLState | ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_BLENDOP_SUB );
- case 8: // add : dst = dst + src
- return extraGLState | ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
- case 6: // darken : dst = min( dst, src )
- return extraGLState | ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_BLENDOP_MIN );
- case 5: // lighten : dst = max( dst, src )
- return extraGLState | ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_BLENDOP_MAX );
- case 4: // screen : dst = dst + src - dst*src ( we only do dst - dst * src, we could do the extra + src with another pass if we need to)
- return extraGLState | ( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_BLENDOP_SUB );
- case 14: // hardlight : src < 0.5 ? multiply : screen
- case 13: // overlay : dst < 0.5 ? multiply : screen
- case 3: // multiply : dst = ( dst * src ) + ( dst * (1-src.a) )
- return extraGLState | ( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
- case 12: // erase
- case 11: // alpha
- case 10: // invert
- case 2: // layer
- case 1: // normal
- case 0: // normaler
- default:
- return extraGLState | ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
- }
- }
- /*
- ========================
- idSWF::RenderMorphShape
- ========================
- */
- void idSWF::RenderMorphShape( idRenderSystem * gui, const idSWFShape * shape, const swfRenderState_t & renderState ) {
- if ( shape == NULL ) {
- idLib::Warning( "%s: RenderMorphShape: shape == NULL", filename.c_str() );
- return;
- }
- for ( int i = 0; i < shape->fillDraws.Num(); i++ ) {
- const idSWFShapeDrawFill & fill = shape->fillDraws[i];
- const idMaterial * material = NULL;
- swfColorXform_t color;
- if ( renderState.material != NULL ) {
- material = renderState.material;
- } else if ( fill.style.type == 0 ) {
- material = guiSolid;
- idVec4 startColor = fill.style.startColor.ToVec4();
- idVec4 endColor = fill.style.endColor.ToVec4();
- color.mul = Lerp( startColor, endColor, renderState.ratio );
- } else if ( fill.style.type == 4 && fill.style.bitmapID != 65535 ) {
- material = dictionary[ fill.style.bitmapID ].material;
- } else {
- material = guiSolid;
- }
- color = color.Multiply( renderState.cxf );
- if ( swf_forceAlpha.GetFloat() > 0.0f ) {
- color.mul.w = swf_forceAlpha.GetFloat();
- color.add.w = 0.0f;
- }
- if ( ( color.mul.w + color.add.w ) <= ALPHA_EPSILON ) {
- continue;
- }
- uint32 packedColorM = LittleLong( PackColor( color.mul ) );
- uint32 packedColorA = LittleLong( PackColor( ( color.add * 0.5f ) + idVec4( 0.5f ) ) ); // Compress from -1..1 to 0..1
- swfRect_t bounds;
- bounds.tl = Lerp( shape->startBounds.tl, shape->endBounds.tl, renderState.ratio );
- bounds.br = Lerp( shape->startBounds.br, shape->endBounds.br, renderState.ratio );
- idVec2 size( material->GetImageWidth(), material->GetImageHeight() );
- if ( renderState.materialWidth > 0 ) {
- size.x = renderState.materialWidth;
- }
- if ( renderState.materialHeight > 0 ) {
- size.y = renderState.materialHeight;
- }
- idVec2 oneOverSize( 1.0f / size.x, 1.0f / size.y );
- swfMatrix_t styleMatrix;
- styleMatrix.xx = Lerp( fill.style.startMatrix.xx, fill.style.endMatrix.xx, renderState.ratio );
- styleMatrix.yy = Lerp( fill.style.startMatrix.yy, fill.style.endMatrix.yy, renderState.ratio );
- styleMatrix.xy = Lerp( fill.style.startMatrix.xy, fill.style.endMatrix.xy, renderState.ratio );
- styleMatrix.yx = Lerp( fill.style.startMatrix.yx, fill.style.endMatrix.yx, renderState.ratio );
- styleMatrix.tx = Lerp( fill.style.startMatrix.tx, fill.style.endMatrix.tx, renderState.ratio );
- styleMatrix.ty = Lerp( fill.style.startMatrix.ty, fill.style.endMatrix.ty, renderState.ratio );
- swfMatrix_t invMatrix = styleMatrix.Inverse();
- gui->SetGLState( GLStateForRenderState( renderState ) );
- idDrawVert * verts = gui->AllocTris( fill.startVerts.Num(), fill.indices.Ptr(), fill.indices.Num(), material, renderState.stereoDepth );
- if ( verts == NULL ) {
- continue;
- }
- for ( int j = 0; j < fill.startVerts.Num(); j++ ) {
- idVec2 xy = Lerp( fill.startVerts[j], fill.endVerts[j], renderState.ratio );
- idVec2 st;
- st.x = ( ( xy.x - bounds.tl.x ) * oneOverSize.x ) * 20.0f;
- st.y = ( ( xy.y - bounds.tl.y ) * oneOverSize.y ) * 20.0f;
- idVec2 adjust( 0.5f * oneOverSize.x, 0.5f * oneOverSize.y );
- ALIGNTYPE16 idDrawVert tempVert;
- tempVert.Clear();
- tempVert.xyz.ToVec2() = renderState.matrix.Transform( xy ).Scale( scaleToVirtual );
- tempVert.xyz.z = 0.0f;
- tempVert.SetTexCoord( invMatrix.Transform( st ) + adjust );
- tempVert.SetNativeOrderColor( packedColorM );
- tempVert.SetNativeOrderColor2( packedColorA );
- WriteDrawVerts16( & verts[j], & tempVert, 1 );
- }
- }
- }
- /*
- ========================
- idSWF::RenderShape
- ========================
- */
- void idSWF::RenderShape( idRenderSystem * gui, const idSWFShape * shape, const swfRenderState_t & renderState ) {
- if ( shape == NULL ) {
- idLib::Warning( "%s: RenderShape: shape == NULL", filename.c_str() );
- return;
- }
- for ( int i = 0; i < shape->fillDraws.Num(); i++ ) {
- const idSWFShapeDrawFill & fill = shape->fillDraws[i];
- const idMaterial * material = NULL;
- swfColorXform_t color;
- swfMatrix_t invMatrix;
- idVec2 atlasScale( 0.0f, 0.0f );
- idVec2 atlasBias( 0.0f, 0.0f );
- bool useAtlas = false;
- idVec2 size( 1.0f, 1.0f );
- if ( renderState.material != NULL ) {
- material = renderState.material;
- invMatrix.xx = invMatrix.yy = ( 1.0f / 20.0f );
- } else if ( fill.style.type == 0 ) {
- material = guiSolid;
- color.mul = fill.style.startColor.ToVec4();
- } else if ( fill.style.type == 4 && fill.style.bitmapID != 65535 ) {
- // everything in a single image atlas
- idSWFDictionaryEntry * entry = &dictionary[ fill.style.bitmapID ];
- material = atlasMaterial;
- idVec2i atlasSize( material->GetImageWidth(), material->GetImageHeight() );
- for ( int i = 0 ; i < 2 ; i++ ) {
- size[i] = entry->imageSize[i];
- atlasScale[i] = (float)size[i] / atlasSize[i];
- atlasBias[i] = (float)entry->imageAtlasOffset[i] / atlasSize[i];
- }
- // de-normalize color channels after DXT decompression
- color.mul = entry->channelScale;
- useAtlas = true;
- const swfMatrix_t & styleMatrix = fill.style.startMatrix;
- invMatrix = styleMatrix.Inverse();
- } else {
- material = guiSolid;
- }
- color = color.Multiply( renderState.cxf );
- if ( swf_forceAlpha.GetFloat() > 0.0f ) {
- color.mul.w = swf_forceAlpha.GetFloat();
- color.add.w = 0.0f;
- }
- if ( ( color.mul.w + color.add.w ) <= ALPHA_EPSILON ) {
- continue;
- }
- uint32 packedColorM = LittleLong( PackColor( color.mul ) );
- uint32 packedColorA = LittleLong( PackColor( ( color.add * 0.5f ) + idVec4( 0.5f ) ) ); // Compress from -1..1 to 0..1
- const swfRect_t & bounds = shape->startBounds;
- if ( renderState.materialWidth > 0 ) {
- size.x = renderState.materialWidth;
- }
- if ( renderState.materialHeight > 0 ) {
- size.y = renderState.materialHeight;
- }
- idVec2 oneOverSize( 1.0f / size.x, 1.0f / size.y );
- gui->SetGLState( GLStateForRenderState( renderState ) );
- idDrawVert * verts = gui->AllocTris( fill.startVerts.Num(), fill.indices.Ptr(), fill.indices.Num(), material, renderState.stereoDepth );
- if ( verts == NULL ) {
- continue;
- }
- ALIGNTYPE16 idDrawVert tempVerts[4];
- for ( int j = 0; j < fill.startVerts.Num(); j++ ) {
- const idVec2 & xy = fill.startVerts[j];
- idDrawVert & vert = tempVerts[j & 3];
- vert.Clear();
- vert.xyz.ToVec2() = renderState.matrix.Transform( xy ).Scale( scaleToVirtual );
- vert.xyz.z = 0.0f;
- vert.SetNativeOrderColor( packedColorM );
- vert.SetNativeOrderColor2( packedColorA );
- // For some reason I don't understand, having texcoords
- // in the range of 2000 or so causes what should be solid
- // fill areas to have horizontal bands on nvidia, but not 360.
- // Forcing the texcoords to zero fixes it.
- if ( fill.style.type != 0 ) {
- idVec2 st;
- // all the swf vertexes have an implicit scale of 1/20 for some reason...
- st.x = ( ( xy.x - bounds.tl.x ) * oneOverSize.x ) * 20.0f;
- st.y = ( ( xy.y - bounds.tl.y ) * oneOverSize.y ) * 20.0f;
- st = invMatrix.Transform( st );
- if ( useAtlas ) {
- st = st.Scale( atlasScale ) + atlasBias;
- }
- // inset the tc - the gui may use a vmtr and the tc might end up
- // crossing page boundaries if using [0.0,1.0]
- st.x = idMath::ClampFloat( 0.001f, 0.999f, st.x );
- st.y = idMath::ClampFloat( 0.001f, 0.999f, st.y );
- vert.SetTexCoord( st );
- }
- // write four verts at a time to video memory
- if ( ( j & 3 ) == 3 ) {
- WriteDrawVerts16( & verts[j & ~3], tempVerts, 4 );
- }
- }
- // write any remaining verts to video memory
- WriteDrawVerts16( & verts[fill.startVerts.Num() & ~3], tempVerts, fill.startVerts.Num() & 3 );
- }
- for ( int i = 0; i < shape->lineDraws.Num(); i++ ) {
- const idSWFShapeDrawLine & line = shape->lineDraws[i];
- swfColorXform_t color;
- color.mul = line.style.startColor.ToVec4();
- color = color.Multiply( renderState.cxf );
- if ( swf_forceAlpha.GetFloat() > 0.0f ) {
- color.mul.w = swf_forceAlpha.GetFloat();
- color.add.w = 0.0f;
- }
- if ( ( color.mul.w + color.add.w ) <= ALPHA_EPSILON ) {
- continue;
- }
- uint32 packedColorM = LittleLong( PackColor( color.mul ) );
- uint32 packedColorA = LittleLong( PackColor( ( color.add * 0.5f ) + idVec4( 0.5f ) ) ); // Compress from -1..1 to 0..1
- gui->SetGLState( GLStateForRenderState( renderState ) | GLS_POLYMODE_LINE );
- idDrawVert * verts = gui->AllocTris( line.startVerts.Num(), line.indices.Ptr(), line.indices.Num(), white, renderState.stereoDepth );
- if ( verts == NULL ) {
- continue;
- }
- for ( int j = 0; j < line.startVerts.Num(); j++ ) {
- const idVec2 & xy = line.startVerts[j];
- ALIGNTYPE16 idDrawVert tempVert;
- tempVert.Clear();
- tempVert.xyz.ToVec2() = renderState.matrix.Transform( xy ).Scale( scaleToVirtual );
- tempVert.xyz.z = 0.0f;
- tempVert.SetTexCoord( 0.0f, 0.0f );
- tempVert.SetNativeOrderColor( packedColorM );
- tempVert.SetNativeOrderColor2( packedColorA );
- WriteDrawVerts16( & verts[j], & tempVert, 1 );
- }
- }
- }
- /*
- ========================
- idSWF::DrawEditCursor
- ========================
- */
- void idSWF::DrawEditCursor( idRenderSystem * gui, float x, float y, float w, float h, const swfMatrix_t & matrix ) {
- idVec2 topl = matrix.Transform( idVec2( x, y ) );
- idVec2 topr = matrix.Transform( idVec2( x + w, y ) );
- idVec2 br = matrix.Transform( idVec2( x + w, y + h ) );
- idVec2 bl = matrix.Transform( idVec2( x, y + h ) );
- DrawStretchPic( idVec4( topl.x, topl.y, 0.0f, 0.0f ), idVec4( topr.x, topr.y, 1.0f, 0.0f ), idVec4( br.x, br.y, 1.0f, 1.0f ), idVec4( bl.x, bl.y, 0.0f, 1.0f ), white );
- }
- /*
- ========================
- idSWF::RenderEditText
- ========================
- */
- void idSWF::RenderEditText( idRenderSystem * gui, idSWFTextInstance * textInstance, const swfRenderState_t & renderState, int time, bool isSplitscreen ) {
- if ( textInstance == NULL ) {
- idLib::Warning( "%s: RenderEditText: textInstance == NULL", filename.c_str() );
- return;
- }
- if ( !textInstance->visible ) {
- return;
- }
- const idSWFEditText * shape = textInstance->editText;
- idStr text;
- if ( textInstance->variable.IsEmpty() ) {
- if ( textInstance->renderMode == SWF_TEXT_RENDER_PARAGRAPH ) {
- if ( textInstance->NeedsGenerateRandomText() ) {
- textInstance->StartParagraphText( Sys_Milliseconds() );
- }
- text = textInstance->GetParagraphText( Sys_Milliseconds() );
- } else if ( textInstance->renderMode == SWF_TEXT_RENDER_RANDOM_APPEAR || textInstance->renderMode == SWF_TEXT_RENDER_RANDOM_APPEAR_CAPS ) {
- if ( textInstance->NeedsGenerateRandomText() ) {
- textInstance->StartRandomText( Sys_Milliseconds() );
- }
- text = textInstance->GetRandomText( Sys_Milliseconds() );
- } else {
- text = idLocalization::GetString( textInstance->text );
- }
- } else {
- idSWFScriptVar var = globals->Get( textInstance->variable );
- if ( var.IsUndefined() ) {
- text = idLocalization::GetString( textInstance->text );
- } else {
- text = idLocalization::GetString( var.ToString() );
- }
- }
- if ( text.Length() == 0 ) {
- textInstance->selectionEnd = -1;
- textInstance->selectionStart = -1;
- }
- if ( textInstance->NeedsSoundPlayed() ) {
- PlaySound( textInstance->GetSoundClip() );
- textInstance->ClearPlaySound();
- }
- if ( textInstance->tooltip ) {
- FindTooltipIcons( &text );
- } else {
- tooltipIconList.Clear();
- }
- int selStart = textInstance->selectionStart;
- int selEnd = textInstance->selectionEnd;
- int cursorPos = selEnd;
- bool inputField = false;
- idSWFScriptVar focusWindow = globals->Get( "focusWindow" );
- if ( focusWindow.IsObject() && focusWindow.GetObject() == &textInstance->scriptObject ) {
- inputField = true;
- }
- bool drawCursor = false;
- if ( inputField && ( ( idLib::frameNumber >> 4 ) & 1 ) == 0 ) {
- cursorPos = selEnd;
- drawCursor = true;
- }
- if ( selStart > selEnd ) {
- SwapValues( selStart, selEnd );
- }
- idVec2 xScaleVec = renderState.matrix.Scale( idVec2( 1.0f, 0.0f ) );
- idVec2 yScaleVec = renderState.matrix.Scale( idVec2( 0.0f, 1.0f ) );
- float xScale = xScaleVec.Length();
- float yScale = yScaleVec.Length();
- if ( isSplitscreen ) {
- yScale *= 0.5f;
- }
- float invXScale = 1.0f / xScale;
- float invYScale = 1.0f / yScale;
- swfMatrix_t matrix = renderState.matrix;
- matrix.xx *= invXScale;
- matrix.xy *= invXScale;
- matrix.yy *= invYScale;
- matrix.yx *= invYScale;
- idSWFDictionaryEntry * fontEntry = FindDictionaryEntry( shape->fontID, SWF_DICT_FONT );
- if ( fontEntry == NULL ) {
- idLib::Warning( "idSWF::RenderEditText: NULL Font" );
- return;
- }
- idSWFFont * swfFont = fontEntry->font;
- float postTransformHeight = SWFTWIP( shape->fontHeight ) * yScale;
- const idFont * fontInfo = swfFont->fontID;
- float glyphScale = postTransformHeight / 48.0f;
- float imageScale = postTransformHeight / 24.0f;
- textInstance->glyphScale = glyphScale;
- idVec4 defaultColor = textInstance->color.ToVec4();
- defaultColor = defaultColor.Multiply( renderState.cxf.mul ) + renderState.cxf.add;
- if ( swf_forceAlpha.GetFloat() > 0.0f ) {
- defaultColor.w = swf_forceAlpha.GetFloat();
- }
- if ( defaultColor.w <= ALPHA_EPSILON ) {
- return;
- }
- idVec4 selColor( defaultColor );
- selColor.w *= 0.5f;
- gui->SetColor( defaultColor );
- gui->SetGLState( GLStateForRenderState( renderState ) );
- swfRect_t bounds;
- bounds.tl.x = xScale * ( shape->bounds.tl.x + SWFTWIP( shape->leftMargin ) );
- bounds.br.x = xScale * ( shape->bounds.br.x - SWFTWIP( shape->rightMargin ) );
- float linespacing = fontInfo->GetAscender( 1.15f * glyphScale );
- if ( shape->leading != 0 ) {
- linespacing += SWFTWIP( shape->leading );
- }
- bounds.tl.y = yScale * ( shape->bounds.tl.y + ( 1.15f * glyphScale ) );
- bounds.br.y = yScale * ( shape->bounds.br.y );
- textInstance->linespacing = linespacing;
- textInstance->bounds = bounds;
-
- if ( shape->flags & SWF_ET_AUTOSIZE ) {
- bounds.br.x = frameWidth;
- bounds.br.y = frameHeight;
- }
-
- if ( drawCursor && cursorPos <= 0 ) {
- float yPos = 0.0f;
- scaledGlyphInfo_t glyph;
- fontInfo->GetScaledGlyph( glyphScale, ' ', glyph );
- yPos = glyph.height / 2.0f;
- DrawEditCursor( gui, bounds.tl.x, yPos, 1.0f, linespacing, matrix );
- }
- if ( textInstance->IsSubtitle() ) {
- if ( text.IsEmpty() && textInstance->subtitleText.IsEmpty() ) {
- return;
- }
- } else if ( text.IsEmpty() ) {
- return;
- }
- float x = bounds.tl.x;
- float y = bounds.tl.y;
- int maxLines = idMath::Ftoi( ( bounds.br.y - bounds.tl.y ) / linespacing );
- if ( maxLines == 0 ) {
- maxLines = 1;
- }
- textInstance->maxLines = maxLines;
- idList< idStr > textLines;
- idStr * currentLine = &textLines.Alloc();
- // tracks the last breakable character we found
- int lastbreak = 0;
- float lastbreakX = 0;
- bool insertingImage = false;
- int iconIndex = 0;
- int charIndex = 0;
- if ( textInstance->IsSubtitle() ) {
- charIndex = textInstance->GetSubStartIndex();
- }
- while ( charIndex < text.Length() ) {
- if ( text[ charIndex ] == '\n' ) {
- if ( shape->flags & SWF_ET_MULTILINE ) {
- currentLine->Append( '\n' );
- x = bounds.tl.x;
- y += linespacing;
- currentLine = &textLines.Alloc();
- lastbreak = 0;
- charIndex++;
- continue;
- } else {
- break;
- }
- }
- int glyphStart = charIndex;
- uint32 tc = text.UTF8Char( charIndex );
- scaledGlyphInfo_t glyph;
- fontInfo->GetScaledGlyph( glyphScale, tc, glyph );
- float glyphSkip = glyph.xSkip;
- if ( textInstance->HasStroke() ) {
- glyphSkip += ( swf_textStrokeSizeGlyphSpacer.GetFloat() * textInstance->GetStrokeWeight() * glyphScale );
- }
- tooltipIcon_t iconCheck;
-
- if ( iconIndex < tooltipIconList.Num() ) {
- iconCheck = tooltipIconList[iconIndex];
- }
- float imageSkip = 0.0f;
- if ( charIndex - 1 == iconCheck.startIndex ) {
- insertingImage = true;
- imageSkip = iconCheck.imageWidth * imageScale;
- } else if ( charIndex - 1 == iconCheck.endIndex ) {
- insertingImage = false;
- iconIndex++;
- glyphSkip = 0.0f;
- }
- if ( insertingImage ) {
- glyphSkip = 0.0f;
- }
- if ( !inputField ) { // only break lines of text when we are not inputting data
- if ( x + glyphSkip > bounds.br.x || x + imageSkip > bounds.br.x ) {
- if ( shape->flags & ( SWF_ET_MULTILINE | SWF_ET_WORDWRAP ) ) {
- if ( lastbreak > 0 ) {
- int curLineIndex = currentLine - &textLines[0];
- idStr * newline = &textLines.Alloc();
- currentLine = &textLines[ curLineIndex ];
- if ( maxLines == 1 ) {
- currentLine->CapLength( currentLine->Length() - 3 );
- currentLine->Append( "..." );
- break;
- } else {
- *newline = currentLine->c_str() + lastbreak;
- currentLine->CapLength( lastbreak );
- currentLine = newline;
- x -= lastbreakX;
- }
- } else {
- currentLine = &textLines.Alloc();
- x = bounds.tl.x;
- }
- lastbreak = 0;
- } else {
- break;
- }
- }
- }
- while ( glyphStart < charIndex && glyphStart < text.Length() ) {
- currentLine->Append( text[ glyphStart++ ] );
- }
- x += glyphSkip + imageSkip;
- if ( tc == ' ' || tc == '-' ) {
- lastbreak = currentLine->Length();
- lastbreakX = x;
- }
- }
- // Subtitle functionality
- if ( textInstance->IsSubtitle() && textInstance->IsUpdatingSubtitle() ) {
- if ( textLines.Num() > 0 && textInstance->SubNeedsSwitch() ) {
- int lastWordIndex = textInstance->GetApporoximateSubtitleBreak( time );
- int newEndChar = textInstance->GetSubStartIndex() + textLines[0].Length();
- int wordCount = 0;
- bool earlyOut = false;
- for ( int index = 0; index < textLines[0].Length(); ++index ) {
- if ( textLines[0][index] == ' ' || textLines[0][index] == '-' ) {
- if ( index != 0 ) {
- if ( wordCount == lastWordIndex ) {
- newEndChar = textInstance->GetSubStartIndex() + index;
- earlyOut = true;
- break;
- }
- // cover the double space at the beginning of sentences
- if ( index > 0 && textLines[0][index - 1 ] != ' ' ) {
- wordCount++;
- }
- }
- } else if ( index == textLines[0].Length() ) {
- if ( wordCount == lastWordIndex ) {
- newEndChar = textInstance->GetSubStartIndex() + index;
- earlyOut = true;
- break;
- }
- wordCount++;
- }
- }
- if ( wordCount <= 0 && textLines[0].Length() > 0 ) {
- wordCount = 1;
- }
-
- if ( !earlyOut ) {
- textInstance->LastWordChanged( wordCount, time );
- }
- textInstance->SetSubEndIndex( newEndChar, time );
-
- idStr subText = textLines[0].Left( newEndChar - textInstance->GetSubStartIndex() );
- idSWFParmList parms;
- parms.Append( subText );
- parms.Append( textInstance->GetSpeaker().c_str() );
- parms.Append( textInstance->GetSubAlignment() );
- Invoke( "subtitleChanged", parms );
- parms.Clear();
- textInstance->SetSubNextStartIndex( textInstance->GetSubEndIndex() );
- textInstance->SwitchSubtitleText( time );
- }
- if ( !textInstance->UpdateSubtitle( time ) ) {
- textInstance->SubtitleComplete();
- idSWFParmList parms;
- parms.Append( textInstance->GetSubAlignment() );
- Invoke( "subtitleComplete", parms );
- parms.Clear();
- textInstance->SubtitleCleanup();
- }
- }
- //*************************************************
- // CALCULATE THE NUMBER OF SCROLLS LINES LEFT
- //*************************************************
- textInstance->CalcMaxScroll( textLines.Num() - maxLines );
- int c = 1;
- int textLine = textInstance->scroll;
- if ( textLine + maxLines > textLines.Num() && maxLines < textLines.Num() ) {
- textLine = textLines.Num() - maxLines;
- textInstance->scroll = textLine;
- } else if ( textLine < 0 || textLines.Num() <= maxLines ) {
- textLine = 0;
- textInstance->scroll = textLine;
- } else if ( textInstance->renderMode == SWF_TEXT_RENDER_AUTOSCROLL ) {
- textLine = textLines.Num() - maxLines;
- textInstance->scroll = textInstance->maxscroll;
- }
- // END SCROLL CALCULATION
- //*************************************************
- int index = 0;
- int startCharacter = 0;
- int endCharacter = 0;
- int inputEndChar = 0;
- iconIndex = 0;
- int overallIndex = 0;
- int curIcon = 0;
- float yPrevBottomOffset = 0.0f;
- float yOffset = 0;
- int strokeXOffsets[] = { -1, 1, -1, 1 };
- int strokeYOffsets[] = { -1, -1, 1, 1 };
- idStr inputText;
- if ( inputField ) {
- if ( textLines.Num() > 0 ) {
- idStr & text = textLines[0];
- float left = bounds.tl.x;
- int startCheckIndex = textInstance->GetInputStartChar();
- if ( startCheckIndex >= text.Length() ) {
- startCheckIndex = 0;
- }
- if ( cursorPos < startCheckIndex && cursorPos >= 0 ) {
- startCheckIndex = cursorPos;
- }
- bool endFound = false;
- int c = startCheckIndex;
- while ( c < text.Length() ) {
- uint32 tc = text.UTF8Char( c );
- scaledGlyphInfo_t glyph;
- fontInfo->GetScaledGlyph( glyphScale, tc, glyph );
- float glyphSkip = glyph.xSkip;
- if ( textInstance->HasStroke() ) {
- glyphSkip += ( swf_textStrokeSizeGlyphSpacer.GetFloat() * textInstance->GetStrokeWeight() * glyphScale );
- }
- if ( left + glyphSkip > bounds.br.x ) {
- if ( cursorPos > c && cursorPos != endCharacter ) {
- float removeSize = 0.0f;
- while ( removeSize < glyphSkip ) {
- if ( endCharacter == c ) {
- break;
- }
- scaledGlyphInfo_t removeGlyph;
- fontInfo->GetScaledGlyph( glyphScale, inputText[ endCharacter++ ], removeGlyph );
- removeSize += removeGlyph.xSkip;
- }
- left -= removeSize;
- } else {
- inputEndChar = c;
- endFound = true;
- break;
- }
- }
- inputText.AppendUTF8Char( tc );
- left += glyphSkip;
- }
- if ( !endFound ) {
- inputEndChar = text.Length();
- }
- startCheckIndex += endCharacter;
- textInstance->SetInputStartCharacter( startCheckIndex );
- endCharacter = startCheckIndex;
- }
- }
-
- for ( int t = 0; t < textLines.Num(); t++ ) {
- if ( textInstance->IsSubtitle() && t > 0 ) {
- break;
- }
-
- if ( t < textLine ) {
- idStr & text = textLines[t];
- c += text.Length();
- startCharacter = endCharacter;
- endCharacter = startCharacter + text.Length();
- overallIndex += text.Length();
- // find the right icon index if we scrolled passed the previous ones
- for ( int iconChar = curIcon; iconChar < tooltipIconList.Num(); ++iconChar ) {
- if ( endCharacter > tooltipIconList[iconChar].startIndex ) {
- curIcon++;
- } else {
- break;
- }
- }
- continue;
- }
- if ( index == maxLines ) {
- break;
- }
- startCharacter = endCharacter;
- idStr & text = textLines[textLine];
- int lastChar = text.Length();
- if ( textInstance->IsSubtitle() ) {
- lastChar = textInstance->GetSubEndIndex();
- }
- textLine++;
- if ( inputField ) {
- if ( inputEndChar == 0 ) {
- inputEndChar += 1;
- }
- selStart -= startCharacter;
- selEnd -= startCharacter;
- cursorPos -= startCharacter;
- endCharacter = inputEndChar;
- lastChar = endCharacter;
- text = text.Mid( startCharacter, endCharacter - startCharacter );
- } else {
- if ( lastChar == 0 ) {
- // blank line so add space char
- endCharacter = startCharacter + 1;
- } else {
- endCharacter = startCharacter + lastChar;
- }
- }
- float width = 0.0f;
- insertingImage = false;
- int i = 0;
- while ( i < lastChar ) {
- if ( curIcon < tooltipIconList.Num() && tooltipIconList[curIcon].startIndex == startCharacter + i ) {
- width += tooltipIconList[curIcon].imageWidth * imageScale;
- i += tooltipIconList[curIcon].endIndex - tooltipIconList[curIcon].startIndex - 1;
- curIcon++;
- } else {
- if ( i < text.Length() ) {
- scaledGlyphInfo_t glyph;
- fontInfo->GetScaledGlyph( glyphScale, text.UTF8Char( i ), glyph );
- width += glyph.xSkip;
- if ( textInstance->HasStroke() ) {
- width += ( swf_textStrokeSizeGlyphSpacer.GetFloat() * textInstance->GetStrokeWeight() * glyphScale );
- }
- } else {
- i++;
- }
- }
- }
- y = bounds.tl.y + ( index * linespacing );
- float biggestGlyphHeight = 0.0f;
- /*for ( int image = 0; image < tooltipIconList.Num(); ++image ) {
- if ( tooltipIconList[image].startIndex >= startCharacter && tooltipIconList[image].endIndex < endCharacter ) {
- biggestGlyphHeight = tooltipIconList[image].imageHeight > biggestGlyphHeight ? tooltipIconList[image].imageHeight : biggestGlyphHeight;
- }
- }*/
- float yBottomOffset = 0.0f;
- float yTopOffset = 0.0f;
- if ( biggestGlyphHeight > 0.0f ) {
-
- float topSpace = 0.0f;
- float bottomSpace = 0.0f;
- int idx = 0;
- scaledGlyphInfo_t glyph;
- fontInfo->GetScaledGlyph( glyphScale, text.UTF8Char( idx ), glyph );
- topSpace = ( ( biggestGlyphHeight * imageScale ) - glyph.height ) / 2.0f;
- bottomSpace = topSpace;
- if ( topSpace > 0.0f && t != 0 ) {
- yTopOffset += topSpace;
- }
- if ( bottomSpace > 0.0f ) {
- yBottomOffset += bottomSpace;
- }
- } else {
- yBottomOffset = 0.0f;
- }
- if ( t != 0 ) {
- if ( yPrevBottomOffset > 0 || yTopOffset > 0 ) {
- yOffset += yTopOffset > yPrevBottomOffset ? yTopOffset : yPrevBottomOffset;
- }
- }
- y += yOffset;
- yPrevBottomOffset = yBottomOffset;
- float extraSpace = 0.0f;
- switch ( shape->align ) {
- case SWF_ET_ALIGN_LEFT:
- x = bounds.tl.x;
- break;
- case SWF_ET_ALIGN_RIGHT:
- x = bounds.br.x - width;
- break;
- case SWF_ET_ALIGN_CENTER:
- x = ( bounds.tl.x + bounds.br.x - width ) * 0.5f;
- break;
- case SWF_ET_ALIGN_JUSTIFY:
- x = bounds.tl.x;
- if ( width > ( bounds.br.x - bounds.tl.x ) * 0.5f && index < textLines.Num() - 1 ) {
- extraSpace = ( ( bounds.br.x - bounds.tl.x ) - width ) / ( (float) lastChar - 1.0f );
- }
- break;
- }
- tooltipIcon_t icon;
- insertingImage = false;
- // find the right icon index if we scrolled passed the previous ones
- for ( int iconChar = iconIndex; iconChar < tooltipIconList.Num(); ++iconChar ) {
- if ( overallIndex > tooltipIconList[iconChar].startIndex ) {
- iconIndex++;
- } else {
- break;
- }
- }
- float baseLine = y + ( fontInfo->GetAscender( glyphScale ) );
- i = 0;
- int overallLineIndex = 0;
- idVec4 textColor = defaultColor;
- while ( i < lastChar ) {
- if ( i >= text.Length() ) {
- break;
- }
- // Support colors
- if ( !textInstance->ignoreColor ) {
- if ( text[ i ] == C_COLOR_ESCAPE ) {
- if ( idStr::IsColor( text.c_str() + i++ ) ) {
- if ( text[ i ] == C_COLOR_DEFAULT ) {
- i++;
- textColor = defaultColor;
- } else {
- textColor = idStr::ColorForIndex( text[ i++ ] );
- textColor.w = defaultColor.w;
- }
- continue;
- }
- }
- }
- uint32 character = text.UTF8Char( i );
- if ( character == '\n' ) {
- c++;
- overallIndex += i - overallLineIndex;
- overallLineIndex = i;;
- continue;
- }
- // Skip a single leading space
- if ( character == ' ' && i == 1 ) {
- c++;
- overallIndex += i - overallLineIndex;
- overallLineIndex = i;
- continue;
- }
- if ( iconIndex < tooltipIconList.Num() ) {
- icon = tooltipIconList[iconIndex];
- }
-
- if ( overallIndex == icon.startIndex ) {
- insertingImage = true;
- scaledGlyphInfo_t glyph;
- fontInfo->GetScaledGlyph( glyphScale, character, glyph );
- float imageHeight = icon.imageHeight * imageScale;
- float glyphHeight = glyph.height;
- float imageY = 0.0f;
- if ( icon.baseline == 0 ) {
- imageY = baseLine - glyph.top;
- imageY += ( glyphHeight - imageHeight ) * 0.5f;
- imageY += 2.0f;
- } else {
- imageY = ( y + glyphHeight ) - ( ( icon.imageHeight * imageScale ) - ( glyphHeight ) );
- }
-
- float imageX = x + glyph.left;
- float imageW = icon.imageWidth * imageScale;
- float imageH = icon.imageHeight * imageScale;
- idVec2 topl = matrix.Transform( idVec2( imageX, imageY ) );
- idVec2 topr = matrix.Transform( idVec2( imageX + imageW, imageY ) );
- idVec2 br = matrix.Transform( idVec2( imageX + imageW, imageY + imageH ) );
- idVec2 bl = matrix.Transform( idVec2( imageX, imageY + imageH ) );
- float s1 = 0.0f;
- float t1 = 0.0f;
- float s2 = 1.0f;
- float t2 = 1.0f;
- //uint32 color = gui->GetColor();
- idVec4 imgColor = colorWhite;
- imgColor.w = defaultColor.w;
- gui->SetColor( imgColor );
- DrawStretchPic( idVec4( topl.x, topl.y, s1, t1 ), idVec4( topr.x, topr.y, s2, t1 ), idVec4( br.x, br.y, s2, t2 ), idVec4( bl.x, bl.y, s1, t2 ), icon.material );
- gui->SetColor( defaultColor );
- x += icon.imageWidth * imageScale;
- x += extraSpace;
- } else if ( overallIndex == icon.endIndex ) {
- insertingImage = false;
- iconIndex++;
- }
- if ( insertingImage ) {
- overallIndex += i - overallLineIndex;
- overallLineIndex = i;
- continue;
- }
- // the glyphs texcoords assume nearest filtering, to get proper
- // bilinear support we need to go an extra half texel on each side
- scaledGlyphInfo_t glyph;
- fontInfo->GetScaledGlyph( glyphScale, character, glyph );
- float glyphSkip = glyph.xSkip;
- if ( textInstance->HasStroke() ) {
- glyphSkip += ( swf_textStrokeSizeGlyphSpacer.GetFloat() * textInstance->GetStrokeWeight() * glyphScale );
- }
- float glyphW = glyph.width + 1.0f; // +1 for bilinear half texel on each side
- float glyphH = glyph.height + 1.0f;
- float glyphY = baseLine - glyph.top;
- float glyphX = x + glyph.left;
- idVec2 topl = matrix.Transform( idVec2( glyphX, glyphY ) );
- idVec2 topr = matrix.Transform( idVec2( glyphX + glyphW, glyphY ) );
- idVec2 br = matrix.Transform( idVec2( glyphX + glyphW, glyphY + glyphH ) );
- idVec2 bl = matrix.Transform( idVec2( glyphX, glyphY + glyphH ) );
- float s1 = glyph.s1;
- float t1 = glyph.t1;
- float s2 = glyph.s2;
- float t2 = glyph.t2;
- if ( c > selStart && c <= selEnd ) {
- idVec2 topl = matrix.Transform( idVec2( x, y ) );
- idVec2 topr = matrix.Transform( idVec2( x + glyphSkip, y ) );
- idVec2 br = matrix.Transform( idVec2( x + glyphSkip, y + linespacing ) );
- idVec2 bl = matrix.Transform( idVec2( x, y + linespacing ) );
- gui->SetColor( selColor );
- DrawStretchPic( idVec4( topl.x, topl.y, 0, 0 ), idVec4( topr.x, topr.y, 1, 0 ), idVec4( br.x, br.y, 1, 1 ), idVec4( bl.x, bl.y, 0, 1 ), white );
- gui->SetColor( textColor );
- }
- if ( textInstance->GetHasDropShadow() ) {
-
- float dsY = glyphY + glyphScale * 2.0f;
- float dsX = glyphX + glyphScale * 2.0f;
- idVec2 dstopl = matrix.Transform( idVec2( dsX, dsY ) );
- idVec2 dstopr = matrix.Transform( idVec2( dsX + glyphW, dsY ) );
- idVec2 dsbr = matrix.Transform( idVec2( dsX + glyphW, dsY + glyphH ) );
- idVec2 dsbl = matrix.Transform( idVec2( dsX, dsY + glyphH ) );
- idVec4 dsColor = colorBlack;
- dsColor.w = defaultColor.w;
- gui->SetColor( dsColor );
- DrawStretchPic( idVec4( dstopl.x, dstopl.y, s1, t1 ), idVec4( dstopr.x, dstopr.y, s2, t1 ), idVec4( dsbr.x, dsbr.y, s2, t2 ), idVec4( dsbl.x, dsbl.y, s1, t2 ), glyph.material );
- gui->SetColor( textColor );
- } else if ( textInstance->HasStroke() ) {
-
- idVec4 strokeColor = colorBlack;
- strokeColor.w = textInstance->GetStrokeStrength() * defaultColor.w;
- gui->SetColor( strokeColor );
- for ( int index = 0; index < 4; ++index ) {
- float xPos = glyphX + ( ( strokeXOffsets[ index ] * textInstance->GetStrokeWeight() ) * glyphScale );
- float yPos = glyphY + ( ( strokeYOffsets[ index ] * textInstance->GetStrokeWeight() ) * glyphScale );
- idVec2 topLeft = matrix.Transform( idVec2( xPos, yPos ) );
- idVec2 topRight = matrix.Transform( idVec2( xPos + glyphW, yPos ) );
- idVec2 botRight = matrix.Transform( idVec2( xPos + glyphW, yPos + glyphH ) );
- idVec2 botLeft = matrix.Transform( idVec2( xPos, yPos + glyphH ) );
- DrawStretchPic( idVec4( topLeft.x, topLeft.y, s1, t1 ), idVec4( topRight.x, topRight.y, s2, t1 ), idVec4( botRight.x, botRight.y, s2, t2 ), idVec4( botLeft.x, botLeft.y, s1, t2 ), glyph.material );
- }
- gui->SetColor( textColor );
- }
- DrawStretchPic( idVec4( topl.x, topl.y, s1, t1 ), idVec4( topr.x, topr.y, s2, t1 ), idVec4( br.x, br.y, s2, t2 ), idVec4( bl.x, bl.y, s1, t2 ), glyph.material );
- x += glyphSkip;
- x += extraSpace;
- if ( cursorPos == c ) {
- DrawEditCursor( gui, x - 1.0f, y, 1.0f, linespacing, matrix );
- }
- c++;
- overallIndex += i - overallLineIndex;
- overallLineIndex = i;
- }
- index++;
- }
- }
- /*
- ========================
- idSWF::FindTooltipIcons
- This replaces text like "_use" with platform specific text like "<JOY1>"
- ========================
- */
- void idSWF::FindTooltipIcons( idStr * text ) {
- tooltipIconList.Clear();
- for ( int i = UB_MAX_BUTTONS - 1; i >= 0; i-- ) {
- //for ( userCmdString_t * ucs = userCmdStrings ; ucs->string ; ucs++ ) {
- userCmdString_t ucs = userCmdStrings[i];
- if ( ucs.string && idStr::FindText( text->c_str(), ucs.string, false ) != idStr::INVALID_POSITION ) {
- idStr replacement;
- keyBindings_t bind = idKeyInput::KeyBindingsFromBinding( ucs.string, true );
- idStr gamepad = "<";
- gamepad.Append( bind.gamepad );
- gamepad.Append( ">" );
- if ( !in_useJoystick.GetBool() ) {
-
- if ( !bind.mouse.IsEmpty() ) {
- replacement.Format( "<%s>", bind.mouse.c_str() );
- } else if ( !bind.keyboard.IsEmpty() ) {
- replacement = bind.keyboard;
- }
- if ( replacement.IsEmpty() ) {
- text->Replace( ucs.string, idStrId( "#str_swf_unbound" ).GetLocalizedString() );
- }
- } else {
- replacement = gamepad;
- }
- if ( !replacement.IsEmpty() ) {
- replacement.ToUpper();
- text->Replace( ucs.string, replacement.c_str() );
- }
- }
- }
- for ( int count = 0; count < tooltipButtonImage.Num(); ++count ) {
- int index = -1;
- while ( ( index = idStr::FindText( text->c_str(), tooltipButtonImage[count].key, false, index + 1 ) ) != idStr::INVALID_POSITION ) {
- tooltipIcon_t icon;
- icon.startIndex = index;
- icon.endIndex = index + idStr::Length(tooltipButtonImage[count].key);
- icon.material = declManager->FindMaterial( tooltipButtonImage[count].xbImage );
- if ( icon.material ) {
- icon.imageWidth = tooltipButtonImage[count].width;
- icon.imageHeight = tooltipButtonImage[count].height;
- icon.baseline = tooltipButtonImage[count].baseline;
- } else {
- icon.imageWidth = 0;
- icon.imageHeight = 0;
- icon.baseline = 0;
- }
- bool inserted = false;
- if ( tooltipIconList.Num() > 0 ) {
- for ( int i = 0; i < tooltipIconList.Num(); ++i ) {
- if ( tooltipIconList[i].startIndex > icon.startIndex ) {
- tooltipIconList.Insert( icon, i );
- inserted = true;
- break;
- }
- }
- }
-
- if ( !inserted ) {
- tooltipIconList.Append( icon );
- }
- }
- }
- }
|