mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-06 20:45:54 +01:00
snapshot (with textfield broken)
This commit is contained in:
parent
c57471364f
commit
40e72f8b29
3 changed files with 145 additions and 95 deletions
|
@ -69,7 +69,7 @@ EM_JS(bool, call_mqttSend, (const char* topic, const uint8_t* ptr, int len), {
|
|||
return mqttSend(topStr, buffer);
|
||||
});
|
||||
|
||||
static void updateScreen( Globals* globals );
|
||||
static void updateScreen( Globals* globals, bool doSave );
|
||||
|
||||
static Globals* sGlobals;
|
||||
|
||||
|
@ -162,24 +162,37 @@ startGame( Globals* globals )
|
|||
comms_resendAll( globals->game.comms, NULL, COMMS_CONN_MQTT, XP_TRUE );
|
||||
}
|
||||
|
||||
updateScreen( globals );
|
||||
updateScreen( globals, true );
|
||||
LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
static bool
|
||||
gameFromInvite( Globals* globals, const NetLaunchInfo* invite )
|
||||
{
|
||||
bool success = false;
|
||||
if ( ! call_confirm( "Invitation received; replace current game?" ) ) {
|
||||
bool loaded = false;
|
||||
bool needsLoad = true;
|
||||
XP_LOGFF( "model: %p", globals->game.model );
|
||||
if ( NULL != globals->game.model ) {
|
||||
XP_LOGFF( "have game: TRUE" );
|
||||
/* there's a current game. Ignore the invitation if it has the same
|
||||
gameID. Otherwise ask to replace */
|
||||
if ( globals->gi.gameID == invite->gameID ) {
|
||||
XP_LOGFF( "duplicate invite; ignoring" );
|
||||
needsLoad = false;
|
||||
} else if ( ! call_confirm( "Invitation received; replace current game?" ) ) {
|
||||
needsLoad = false;
|
||||
}
|
||||
} else if ( invite->lang != 1 ) {
|
||||
call_alert( "Invitations are only supported for play in English right now." );
|
||||
} else {
|
||||
needsLoad = false;
|
||||
}
|
||||
|
||||
if ( needsLoad ) {
|
||||
if ( !!globals->util ) {
|
||||
game_dispose( &globals->game, NULL );
|
||||
wasm_util_destroy( globals->util );
|
||||
globals->util = NULL;
|
||||
}
|
||||
XP_LOGFF( "done with cleanup" ); /* not reaching this */
|
||||
|
||||
gi_disposePlayerInfo( MPPARM(globals->mpool) &globals->gi );
|
||||
XP_MEMSET( &globals->gi, 0, sizeof(globals->gi) );
|
||||
|
@ -187,18 +200,48 @@ gameFromInvite( Globals* globals, const NetLaunchInfo* invite )
|
|||
globals->util = wasm_util_make( globals->mpool, &globals->gi,
|
||||
globals->dutil, globals );
|
||||
|
||||
success = game_makeFromInvite( MPPARM(globals->mpool) NULL, invite,
|
||||
&globals->game, &globals->gi,
|
||||
globals->dict, NULL,
|
||||
globals->util, globals->draw,
|
||||
&globals->cp, &globals->procs );
|
||||
loaded = game_makeFromInvite( MPPARM(globals->mpool) NULL, invite,
|
||||
&globals->game, &globals->gi,
|
||||
globals->dict, NULL,
|
||||
globals->util, globals->draw,
|
||||
&globals->cp, &globals->procs );
|
||||
|
||||
} else {
|
||||
loaded = true;
|
||||
}
|
||||
return success;
|
||||
LOG_RETURNF( "%d", loaded );
|
||||
return loaded;
|
||||
}
|
||||
|
||||
static bool
|
||||
loadSavedGame( Globals* globals )
|
||||
{
|
||||
bool loaded = false;
|
||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(globals->mpool)
|
||||
globals->vtMgr );
|
||||
dutil_loadStream( globals->dutil, NULL, KEY_GAME, NULL, stream );
|
||||
if ( 0 < stream_getSize( stream ) ) {
|
||||
XP_ASSERT( !globals->util );
|
||||
globals->util = wasm_util_make( globals->mpool, &globals->gi,
|
||||
globals->dutil, globals );
|
||||
|
||||
XP_LOGFF( "there's a saved game!!" );
|
||||
loaded = game_makeFromStream( MPPARM(globals->mpool) NULL, stream,
|
||||
&globals->game, &globals->gi,
|
||||
globals->dict, NULL,
|
||||
globals->util, globals->draw,
|
||||
&globals->cp, &globals->procs );
|
||||
|
||||
if ( loaded ) {
|
||||
updateScreen( globals, false );
|
||||
}
|
||||
}
|
||||
stream_destroy( stream, NULL );
|
||||
return loaded;
|
||||
}
|
||||
|
||||
static void
|
||||
makeAndDraw( Globals* globals, const NetLaunchInfo* invite,
|
||||
loadAndDraw( Globals* globals, const NetLaunchInfo* invite,
|
||||
bool forceNew, bool p0robot, bool p1robot )
|
||||
{
|
||||
if ( !!globals->util ) {
|
||||
|
@ -207,46 +250,36 @@ makeAndDraw( Globals* globals, const NetLaunchInfo* invite,
|
|||
globals->util = NULL;
|
||||
}
|
||||
|
||||
globals->gi.serverRole = SERVER_STANDALONE;
|
||||
globals->gi.phoniesAction = PHONIES_WARN;
|
||||
|
||||
globals->gi.nPlayers = 2;
|
||||
globals->gi.boardSize = 15;
|
||||
// globals->gi.dictName = "myDict";
|
||||
globals->gi.players[0].name = copyString( globals->mpool, "Player 1" );
|
||||
globals->gi.players[0].isLocal = XP_TRUE;
|
||||
globals->gi.players[0].robotIQ = p0robot ? 99 : 0;
|
||||
|
||||
globals->gi.players[1].name = copyString( globals->mpool, "Player 2" );
|
||||
globals->gi.players[1].isLocal = XP_TRUE;
|
||||
globals->gi.players[1].robotIQ = p1robot ? 99 : 0;
|
||||
|
||||
globals->util = wasm_util_make( globals->mpool, &globals->gi,
|
||||
globals->dutil, globals );
|
||||
|
||||
XP_Bool loaded = XP_FALSE;
|
||||
XP_ASSERT( !forceNew || !invite ); /* won't both be set */
|
||||
|
||||
if ( !!invite ) {
|
||||
loaded = gameFromInvite( globals, invite );
|
||||
} else if ( ! forceNew ) {
|
||||
/* Let's see if there's a saved game */
|
||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(globals->mpool)
|
||||
globals->vtMgr );
|
||||
dutil_loadStream( globals->dutil, NULL, KEY_GAME, NULL, stream );
|
||||
if ( 0 < stream_getSize( stream ) ) {
|
||||
XP_LOGFF( "there's a saved game!!" );
|
||||
loaded = game_makeFromStream( MPPARM(globals->mpool) NULL, stream,
|
||||
&globals->game, &globals->gi,
|
||||
globals->dict, NULL,
|
||||
globals->util, globals->draw,
|
||||
&globals->cp, &globals->procs );
|
||||
bool haveGame;
|
||||
if ( forceNew ) {
|
||||
haveGame = false;
|
||||
} else {
|
||||
/* First, load any saved game. We need it e.g. to confirm that an incoming
|
||||
invite is a dup and should be dropped. */
|
||||
haveGame = loadSavedGame( globals );
|
||||
|
||||
if ( !!invite ) {
|
||||
haveGame = gameFromInvite( globals, invite );
|
||||
}
|
||||
stream_destroy( stream, NULL );
|
||||
}
|
||||
|
||||
if ( !loaded ) {
|
||||
if ( !haveGame ) {
|
||||
globals->gi.serverRole = SERVER_STANDALONE;
|
||||
globals->gi.phoniesAction = PHONIES_WARN;
|
||||
globals->gi.gameID = 0;
|
||||
globals->gi.nPlayers = 2;
|
||||
globals->gi.boardSize = 15;
|
||||
globals->gi.players[0].name = copyString( globals->mpool, "Player 1" );
|
||||
globals->gi.players[0].isLocal = XP_TRUE;
|
||||
globals->gi.players[0].robotIQ = p0robot ? 99 : 0;
|
||||
|
||||
globals->gi.players[1].name = copyString( globals->mpool, "Player 2" );
|
||||
globals->gi.players[1].isLocal = XP_TRUE;
|
||||
globals->gi.players[1].robotIQ = p1robot ? 99 : 0;
|
||||
|
||||
globals->util = wasm_util_make( globals->mpool, &globals->gi,
|
||||
globals->dutil, globals );
|
||||
|
||||
XP_LOGFF( "calling game_makeNewGame()" );
|
||||
game_makeNewGame( MPPARM(globals->mpool) NULL,
|
||||
&globals->game, &globals->gi,
|
||||
|
@ -271,7 +304,7 @@ main_onGameMessage( Globals* globals, XP_U32 gameID,
|
|||
{
|
||||
XP_Bool draw = game_receiveMessage( &globals->game, NULL, stream, from );
|
||||
if ( draw ) {
|
||||
updateScreen( globals );
|
||||
updateScreen( globals, true );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -398,29 +431,23 @@ checkForEvent( Globals* globals )
|
|||
}
|
||||
|
||||
static void
|
||||
updateScreen( Globals* globals )
|
||||
updateScreen( Globals* globals, bool doSave )
|
||||
{
|
||||
LOG_FUNC();
|
||||
SDL_RenderClear( globals->renderer );
|
||||
XP_LOGFF( "calling board_draw" );
|
||||
board_draw( globals->game.board, NULL );
|
||||
XP_LOGFF( "calling wasm_draw_render" );
|
||||
wasm_draw_render( globals->draw, globals->renderer );
|
||||
XP_LOGFF( "calling SDL_RenderPresent" );
|
||||
SDL_RenderPresent( globals->renderer );
|
||||
|
||||
/* Let's save state here too, though likely too often */
|
||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(globals->mpool)
|
||||
globals->vtMgr );
|
||||
XP_LOGFF( "calling game_saveToStream" );
|
||||
game_saveToStream( &globals->game, NULL, &globals->gi,
|
||||
stream, ++globals->saveToken );
|
||||
XP_LOGFF( "calling dutil_storeStream" );
|
||||
dutil_storeStream( globals->dutil, NULL, KEY_GAME, stream );
|
||||
stream_destroy( stream, NULL );
|
||||
XP_LOGFF( "calling game_saveSucceeded" );
|
||||
game_saveSucceeded( &globals->game, NULL, globals->saveToken );
|
||||
LOG_RETURN_VOID();
|
||||
if ( doSave ) {
|
||||
XWStreamCtxt* stream = mem_stream_make_raw( MPPARM(globals->mpool)
|
||||
globals->vtMgr );
|
||||
game_saveToStream( &globals->game, NULL, &globals->gi,
|
||||
stream, ++globals->saveToken );
|
||||
dutil_storeStream( globals->dutil, NULL, KEY_GAME, stream );
|
||||
stream_destroy( stream, NULL );
|
||||
game_saveSucceeded( &globals->game, NULL, globals->saveToken );
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -432,7 +459,7 @@ looper( void* closure )
|
|||
draw = checkForEvent( globals ) || draw;
|
||||
|
||||
if ( draw ) {
|
||||
updateScreen( globals );
|
||||
updateScreen( globals, true );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,6 +475,11 @@ button( const char* msg )
|
|||
draw = board_requestHint( board, NULL, XP_TRUE, &redo );
|
||||
} else if ( 0 == strcmp(msg, "hintup") ) {
|
||||
draw = board_requestHint( board, NULL, XP_FALSE, &redo );
|
||||
} else if ( 0 == strcmp(msg, "trade") ) {
|
||||
// draw = board_beginTrade( board, NULL );
|
||||
call_alert("not implemented");
|
||||
} else if ( 0 == strcmp(msg, "commit") ) {
|
||||
draw = board_commitTurn( board, NULL, XP_FALSE, XP_FALSE, NULL );
|
||||
} else if ( 0 == strcmp(msg, "flip") ) {
|
||||
draw = board_flip( board );
|
||||
} else if ( 0 == strcmp(msg, "redo") ) {
|
||||
|
@ -458,7 +490,7 @@ button( const char* msg )
|
|||
}
|
||||
|
||||
if ( draw ) {
|
||||
updateScreen( globals );
|
||||
updateScreen( globals, true );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -560,7 +592,7 @@ initNoReturn( int argc, const char** argv )
|
|||
|
||||
initDeviceGlobals( globals );
|
||||
|
||||
makeAndDraw( globals, nlip, false, false, true );
|
||||
loadAndDraw( globals, nlip, false, false, true );
|
||||
|
||||
emscripten_set_main_loop_arg( looper, globals, -1, 1 );
|
||||
}
|
||||
|
@ -570,7 +602,9 @@ newgame(bool p0, bool p1)
|
|||
{
|
||||
XP_LOGFF( "(args: %d,%d)", p0, p1 );
|
||||
XP_ASSERT( !!sGlobals );
|
||||
makeAndDraw( sGlobals, NULL, true, p0, p1 );
|
||||
if ( call_confirm("Are you sure you want to replace the current game?") ) {
|
||||
loadAndDraw( sGlobals, NULL, true, p0, p1 );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -58,11 +58,13 @@
|
|||
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
|
||||
</div>
|
||||
<div>
|
||||
<button onclick="Module.ccall('button', null, ['string'], ['hintdown']);">Prev Hint</button>
|
||||
<button onclick="Module.ccall('button', null, ['string'], ['hintup']);">Next Hint</button>
|
||||
<button onclick="Module.ccall('button', null, ['string'], ['flip']);">Flip</button>
|
||||
<button onclick="Module.ccall('button', null, ['string'], ['redo']);">Un/Redo</button>
|
||||
<button onclick="Module.ccall('button', null, ['string'], ['vals']);">Vals</button>
|
||||
<button onclick="callButton('hintdown');">Prev Hint</button>
|
||||
<button onclick="callButton('hintup');">Next Hint</button>
|
||||
<button onclick="callButton('trade');">Trade</button>
|
||||
<button onclick="callButton('commit');">Commit</button>
|
||||
<button onclick="callButton('flip');">Flip</button>
|
||||
<button onclick="callButton('redo');">Un/Redo</button>
|
||||
<button onclick="callButton('vals');">Vals</button>
|
||||
</div>
|
||||
<div>
|
||||
<span>Player 1</span>
|
||||
|
@ -72,16 +74,20 @@
|
|||
<span>Player 2</span>
|
||||
<input type="checkbox" id="player1Checked">Is Robot</input>
|
||||
</div>
|
||||
<div>
|
||||
<span>Local player name:</span>
|
||||
<input type="textarea" id="playerName">Player 1</input>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" onclick="callNewGame();">New Local Game</button>
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<button type="button" onclick="localStorage.clear();">Clear Local Storage</button>
|
||||
</div>
|
||||
|
||||
<div><span>MQTT Dev ID:</span><span id="mqtt_span"></span></div>
|
||||
<div><span>MQTT Status:</span><span id="mqtt_status">Unconnected</span></div>
|
||||
<div>
|
||||
<button type="button" onclick="localStorage.clear();">Clear Local Storage</button>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="emscripten">
|
||||
<input type="checkbox" id="resize">Resize canvas
|
||||
|
@ -182,10 +188,16 @@
|
|||
function callNewGame() {
|
||||
var args = [
|
||||
document.getElementById("player0Checked").checked,
|
||||
document.getElementById("player1Checked").checked,
|
||||
document.getElementById("player1Checked").checked,
|
||||
document.getElementById("playerName").checked,
|
||||
]
|
||||
Module.ccall('newgame', null, ['boolean', 'boolean'], args);
|
||||
Module.ccall('newgame', null, ['boolean', 'boolean', 'string'], args);
|
||||
}
|
||||
|
||||
function callButton(name) {
|
||||
Module.ccall('button', null, ['string'], [name]);
|
||||
}
|
||||
|
||||
function onHaveDevID(closure, devid) {
|
||||
console.log('got ' + devid);
|
||||
state.closure = closure;
|
||||
|
|
|
@ -23,6 +23,8 @@ typedef struct _WasmDrawCtx {
|
|||
|
||||
int trayOwner;
|
||||
XP_Bool inTrade;
|
||||
|
||||
MPSLOT;
|
||||
} WasmDrawCtx;
|
||||
|
||||
static SDL_Color sBonusColors[4] = {
|
||||
|
@ -216,12 +218,20 @@ static void
|
|||
wasm_draw_destroyCtxt( DrawCtx* dctx, XWEnv xwe )
|
||||
{
|
||||
LOG_FUNC();
|
||||
WasmDrawCtx* wdctx = (WasmDrawCtx*)dctx;
|
||||
|
||||
TTF_CloseFont( wdctx->font12 );
|
||||
TTF_CloseFont( wdctx->font20 );
|
||||
TTF_CloseFont( wdctx->font36 );
|
||||
TTF_CloseFont( wdctx->font48 );
|
||||
|
||||
XP_FREEP( wdctx->mpool, &wdctx->vtable );
|
||||
XP_FREEP( wdctx->mpool, &wdctx );
|
||||
}
|
||||
|
||||
static void
|
||||
wasm_draw_endDraw( DrawCtx* dctx, XWEnv xwe )
|
||||
{
|
||||
LOG_FUNC();
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
|
@ -230,14 +240,15 @@ wasm_draw_boardBegin( DrawCtx* dctx, XWEnv xwe,
|
|||
XP_U16 hScale, XP_U16 vScale,
|
||||
DrawFocusState dfs )
|
||||
{
|
||||
// LOG_FUNC();
|
||||
return XP_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
wasm_draw_objFinished( DrawCtx* dctx, XWEnv xwe, BoardObjectType typ,
|
||||
const XP_Rect* rect,
|
||||
DrawFocusState dfs ){ LOG_FUNC(); }
|
||||
DrawFocusState dfs )
|
||||
{
|
||||
}
|
||||
|
||||
static XP_Bool
|
||||
wasm_draw_vertScrollBoard(DrawCtx* dctx, XWEnv xwe, XP_Rect* rect,
|
||||
|
@ -252,7 +263,6 @@ wasm_draw_trayBegin( DrawCtx* dctx, XWEnv xwe, const XP_Rect* rect,
|
|||
XP_U16 owner, XP_S16 score,
|
||||
DrawFocusState dfs )
|
||||
{
|
||||
XP_LOGFF( "(owner=%d)", owner );
|
||||
WasmDrawCtx* wdctx = (WasmDrawCtx*)dctx;
|
||||
wdctx->trayOwner = owner;
|
||||
return XP_TRUE;
|
||||
|
@ -264,7 +274,6 @@ wasm_draw_scoreBegin( DrawCtx* dctx, XWEnv xwe, const XP_Rect* rect,
|
|||
const XP_S16* const scores,
|
||||
XP_S16 remCount, DrawFocusState dfs )
|
||||
{
|
||||
LOG_FUNC();
|
||||
WasmDrawCtx* wdctx = (WasmDrawCtx*)dctx;
|
||||
clearRect( wdctx, rect );
|
||||
return XP_TRUE;
|
||||
|
@ -275,7 +284,6 @@ wasm_draw_measureRemText( DrawCtx* dctx, XWEnv xwe, const XP_Rect* rect,
|
|||
XP_S16 nTilesLeft,
|
||||
XP_U16* width, XP_U16* height )
|
||||
{
|
||||
LOG_FUNC();
|
||||
XP_Bool drawIt = 0 <= nTilesLeft;
|
||||
if ( drawIt ) {
|
||||
XP_UCHAR buf[4];
|
||||
|
@ -293,7 +301,6 @@ wasm_draw_drawRemText( DrawCtx* dctx, XWEnv xwe, const XP_Rect* rInner,
|
|||
const XP_Rect* rOuter,
|
||||
XP_S16 nTilesLeft, XP_Bool focussed )
|
||||
{
|
||||
LOG_FUNC();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -302,7 +309,6 @@ wasm_draw_measureScoreText( DrawCtx* dctx, XWEnv xwe,
|
|||
const DrawScoreInfo* dsi,
|
||||
XP_U16* width, XP_U16* height )
|
||||
{
|
||||
LOG_FUNC();
|
||||
*width = rect->width / 2;
|
||||
*height = rect->height;
|
||||
}
|
||||
|
@ -314,7 +320,6 @@ wasm_draw_score_drawPlayer( DrawCtx* dctx, XWEnv xwe,
|
|||
XP_U16 gotPct,
|
||||
const DrawScoreInfo* dsi )
|
||||
{
|
||||
XP_LOGFF( "(playerNum: %d)", dsi->playerNum );
|
||||
WasmDrawCtx* wdctx = (WasmDrawCtx*)dctx;
|
||||
XP_UCHAR buf[32];
|
||||
XP_SNPRINTF( buf, VSIZE(buf), "%s: %d", dsi->name, dsi->totalScore );
|
||||
|
@ -346,7 +351,10 @@ wasm_draw_score_pendingScore( DrawCtx* dctx, XWEnv xwe,
|
|||
static void
|
||||
wasm_draw_drawTimer( DrawCtx* dctx, XWEnv xwe, const XP_Rect* rect,
|
||||
XP_U16 player, XP_S16 secondsLeft,
|
||||
XP_Bool turnDone ){ LOG_FUNC(); }
|
||||
XP_Bool turnDone )
|
||||
{
|
||||
LOG_FUNC();
|
||||
}
|
||||
|
||||
static void
|
||||
markBlank( WasmDrawCtx* wdctx, const XP_Rect* rect, const SDL_Color* backColor )
|
||||
|
@ -470,7 +478,6 @@ wasm_draw_drawTileMidDrag( DrawCtx* dctx, XWEnv xwe,
|
|||
XP_U16 val, XP_U16 owner,
|
||||
CellFlags flags )
|
||||
{
|
||||
LOG_FUNC();
|
||||
WasmDrawCtx* wdctx = (WasmDrawCtx*)dctx;
|
||||
drawTile( wdctx, text, val, wdctx->trayOwner, rect );
|
||||
return XP_TRUE;
|
||||
|
@ -481,7 +488,6 @@ static XP_Bool
|
|||
wasm_draw_drawTileBack( DrawCtx* dctx, XWEnv xwe, const XP_Rect* rect,
|
||||
CellFlags flags )
|
||||
{
|
||||
LOG_FUNC();
|
||||
WasmDrawCtx* wdctx = (WasmDrawCtx*)dctx;
|
||||
drawTile( wdctx, "?", -1, wdctx->trayOwner, rect );
|
||||
return XP_TRUE;
|
||||
|
@ -538,11 +544,8 @@ createSurface( WasmDrawCtx* wdctx, int width, int height )
|
|||
void
|
||||
wasm_draw_render( DrawCtx* dctx, SDL_Renderer* dest )
|
||||
{
|
||||
LOG_FUNC();
|
||||
WasmDrawCtx* wdctx = (WasmDrawCtx*)dctx;
|
||||
|
||||
// SDL_RenderPresent( wdctx->renderer );
|
||||
|
||||
SDL_Texture* texture =
|
||||
SDL_CreateTextureFromSurface( dest, wdctx->surface );
|
||||
SDL_RenderCopyEx( dest, texture, NULL, NULL, 0,
|
||||
|
@ -555,6 +558,7 @@ wasm_draw_make( MPFORMAL int width, int height )
|
|||
{
|
||||
LOG_FUNC();
|
||||
WasmDrawCtx* wdctx = XP_MALLOC( mpool, sizeof(*wdctx) );
|
||||
MPASSIGN( wdctx->mpool, mpool );
|
||||
|
||||
wdctx->font12 = TTF_OpenFont( "assets_dir/FreeSans.ttf", 12 );
|
||||
XP_ASSERT( !!wdctx->font12 );
|
||||
|
|
Loading…
Add table
Reference in a new issue