Make Textures a component too, move some texture specific out of Game.c and into TexturePack.c

This commit is contained in:
UnknownShadow200 2020-06-26 22:37:14 +10:00
parent 664428682c
commit dcc6a12946
4 changed files with 82 additions and 68 deletions

View File

@ -91,29 +91,6 @@ int ScheduledTask_Add(double interval, ScheduledTaskCallback callback) {
} }
cc_bool Game_ChangeTerrainAtlas(Bitmap* atlas) {
static const String terrain = String_FromConst("terrain.png");
if (!Game_ValidateBitmap(&terrain, atlas)) return false;
if (atlas->Height < atlas->Width) {
Chat_AddRaw("&cUnable to use terrain.png from the texture pack.");
Chat_AddRaw("&c Its height is less than its width.");
return false;
}
if (atlas->Width < ATLAS2D_TILES_PER_ROW) {
Chat_AddRaw("&cUnable to use terrain.png from the texture pack.");
Chat_AddRaw("&c It must be 16 or more pixels wide.");
return false;
}
if (Gfx.LostContext) return false;
Atlas_Free();
Atlas_Update(atlas);
Event_RaiseVoid(&TextureEvents.AtlasChanged);
return true;
}
void Game_SetViewDistance(int distance) { void Game_SetViewDistance(int distance) {
distance = min(distance, Game_MaxViewDistance); distance = min(distance, Game_MaxViewDistance);
if (distance == Game_ViewDistance) return; if (distance == Game_ViewDistance) return;
@ -260,22 +237,6 @@ static void HandleOnNewMapLoaded(void* obj) {
} }
} }
static void HandleTextureChanged(void* obj, struct Stream* src, const String* name) {
Bitmap bmp;
cc_result res;
if (String_CaselessEqualsConst(name, "terrain.png")) {
res = Png_Decode(&bmp, src);
if (res) {
Logger_Warn2(res, "decoding", name);
Mem_Free(bmp.Scan0);
} else if (!Game_ChangeTerrainAtlas(&bmp)) {
Mem_Free(bmp.Scan0);
}
}
}
static void HandleLowVRAMDetected(void* obj) { static void HandleLowVRAMDetected(void* obj) {
if (Game_UserViewDistance <= 16) Logger_Abort("Out of video memory!"); if (Game_UserViewDistance <= 16) Logger_Abort("Out of video memory!");
Game_UserViewDistance /= 2; Game_UserViewDistance /= 2;
@ -372,16 +333,12 @@ static void Game_Load(void) {
Gfx_Init(); Gfx_Init();
LoadOptions(); LoadOptions();
Event_RegisterVoid(&WorldEvents.NewMap, NULL, HandleOnNewMap); Event_RegisterVoid(&WorldEvents.NewMap, NULL, HandleOnNewMap);
Event_RegisterVoid(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded); Event_RegisterVoid(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded);
Event_RegisterEntry(&TextureEvents.FileChanged, NULL, HandleTextureChanged); Event_RegisterVoid(&GfxEvents.LowVRAMDetected, NULL, HandleLowVRAMDetected);
Event_RegisterVoid(&GfxEvents.LowVRAMDetected, NULL, HandleLowVRAMDetected);
Event_RegisterVoid(&WindowEvents.Resized, NULL, Game_OnResize); Event_RegisterVoid(&WindowEvents.Resized, NULL, Game_OnResize);
Event_RegisterVoid(&WindowEvents.Closing, NULL, Game_Free); Event_RegisterVoid(&WindowEvents.Closing, NULL, Game_Free);
TextureCache_Init();
/* TODO: Survival vs Creative game mode */
InputHandler_Init(); InputHandler_Init();
Game_AddComponent(&Blocks_Component); Game_AddComponent(&Blocks_Component);
@ -398,6 +355,7 @@ static void Game_Load(void) {
Game_AddComponent(&Animations_Component); Game_AddComponent(&Animations_Component);
Game_AddComponent(&Inventory_Component); Game_AddComponent(&Inventory_Component);
Game_AddComponent(&Textures_Component);
World_Reset(); World_Reset();
Game_AddComponent(&Builder_Component); Game_AddComponent(&Builder_Component);
@ -602,16 +560,16 @@ static void Game_RenderFrame(double delta) {
void Game_Free(void* obj) { void Game_Free(void* obj) {
struct IGameComponent* comp; struct IGameComponent* comp;
Atlas_Free(); /* Most components will call OnContextLost in their Free functions */
/* Set to false so components will always free managed textures too */
Gfx.ManagedTextures = false; Gfx.ManagedTextures = false;
Event_UnregisterVoid(&WorldEvents.NewMap, NULL, HandleOnNewMap); Event_UnregisterVoid(&WorldEvents.NewMap, NULL, HandleOnNewMap);
Event_UnregisterVoid(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded); Event_UnregisterVoid(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded);
Event_UnregisterEntry(&TextureEvents.FileChanged, NULL, HandleTextureChanged); Event_UnregisterVoid(&GfxEvents.LowVRAMDetected, NULL, HandleLowVRAMDetected);
Event_UnregisterVoid(&GfxEvents.LowVRAMDetected, NULL, HandleLowVRAMDetected);
Event_UnregisterVoid(&WindowEvents.Resized, NULL, Game_OnResize); Event_UnregisterVoid(&WindowEvents.Resized, NULL, Game_OnResize);
Event_UnregisterVoid(&WindowEvents.Closing, NULL, Game_Free); Event_UnregisterVoid(&WindowEvents.Closing, NULL, Game_Free);
for (comp = comps_head; comp; comp = comp->next) { for (comp = comps_head; comp; comp = comp->next) {
if (comp->Free) comp->Free(); if (comp->Free) comp->Free();

View File

@ -49,8 +49,6 @@ enum FpsLimitMethod {
}; };
extern const char* const FpsLimit_Names[FPS_LIMIT_COUNT]; extern const char* const FpsLimit_Names[FPS_LIMIT_COUNT];
/* Attempts to change the terrain atlas. (bitmap containing textures for all blocks) */
cc_bool Game_ChangeTerrainAtlas(Bitmap* atlas);
void Game_SetViewDistance(int distance); void Game_SetViewDistance(int distance);
void Game_UserSetViewDistance(int distance); void Game_UserSetViewDistance(int distance);
void Game_SetFov(int fov); void Game_SetFov(int fov);

View File

@ -12,6 +12,7 @@
#include "ExtMath.h" #include "ExtMath.h"
#include "Options.h" #include "Options.h"
#include "Logger.h" #include "Logger.h"
#include "Chat.h" /* TODO avoid this include */
/*########################################################################################################################* /*########################################################################################################################*
*------------------------------------------------------TerrainAtlas-------------------------------------------------------* *------------------------------------------------------TerrainAtlas-------------------------------------------------------*
@ -71,7 +72,8 @@ static void Atlas_Update1D(void) {
Atlas1D.Shift = Math_Log2(Atlas1D.TilesPerAtlas); Atlas1D.Shift = Math_Log2(Atlas1D.TilesPerAtlas);
} }
void Atlas_Update(Bitmap* bmp) { /* Loads the given atlas and converts it into an array of 1D atlases. */
static void Atlas_Update(Bitmap* bmp) {
Atlas2D.Bmp = *bmp; Atlas2D.Bmp = *bmp;
Atlas2D.TileSize = bmp->Width / ATLAS2D_TILES_PER_ROW; Atlas2D.TileSize = bmp->Width / ATLAS2D_TILES_PER_ROW;
Atlas2D.RowsCount = bmp->Height / Atlas2D.TileSize; Atlas2D.RowsCount = bmp->Height / Atlas2D.TileSize;
@ -108,7 +110,8 @@ GfxResourceID Atlas2D_LoadTile(TextureLoc texLoc) {
} }
} }
void Atlas_Free(void) { /* Frees the atlas and 1D atlas textures */
static void Atlas_Free(void) {
int i; int i;
Mem_Free(Atlas2D.Bmp.Scan0); Mem_Free(Atlas2D.Bmp.Scan0);
Atlas2D.Bmp.Scan0 = NULL; Atlas2D.Bmp.Scan0 = NULL;
@ -118,13 +121,37 @@ void Atlas_Free(void) {
} }
} }
cc_bool Atlas_TryChange(Bitmap* atlas) {
static const String terrain = String_FromConst("terrain.png");
if (!Game_ValidateBitmap(&terrain, atlas)) return false;
if (atlas->Height < atlas->Width) {
Chat_AddRaw("&cUnable to use terrain.png from the texture pack.");
Chat_AddRaw("&c Its height is less than its width.");
return false;
}
if (atlas->Width < ATLAS2D_TILES_PER_ROW) {
Chat_AddRaw("&cUnable to use terrain.png from the texture pack.");
Chat_AddRaw("&c It must be 16 or more pixels wide.");
return false;
}
if (Gfx.LostContext) return false;
Atlas_Free();
Atlas_Update(atlas);
Event_RaiseVoid(&TextureEvents.AtlasChanged);
return true;
}
/*########################################################################################################################* /*########################################################################################################################*
*------------------------------------------------------TextureCache-------------------------------------------------------* *------------------------------------------------------TextureCache-------------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
static struct EntryList acceptedList, deniedList, etagCache, lastModifiedCache; static struct EntryList acceptedList, deniedList, etagCache, lastModifiedCache;
void TextureCache_Init(void) { /* Initialises cache state (loading various lists) */
static void TextureCache_Init(void) {
EntryList_Init(&acceptedList, "texturecache/acceptedurls.txt", ' '); EntryList_Init(&acceptedList, "texturecache/acceptedurls.txt", ' ');
EntryList_Init(&deniedList, "texturecache/deniedurls.txt", ' '); EntryList_Init(&deniedList, "texturecache/deniedurls.txt", ' ');
EntryList_Init(&etagCache, "texturecache/etags.txt", ' '); EntryList_Init(&etagCache, "texturecache/etags.txt", ' ');
@ -295,7 +322,7 @@ static cc_result TexturePack_ExtractPng(struct Stream* stream) {
if (!res) { if (!res) {
Event_RaiseVoid(&TextureEvents.PackChanged); Event_RaiseVoid(&TextureEvents.PackChanged);
if (Game_ChangeTerrainAtlas(&bmp)) return 0; if (Atlas_TryChange(&bmp)) return 0;
} }
Mem_Free(bmp.Scan0); Mem_Free(bmp.Scan0);
@ -406,3 +433,37 @@ void TexturePack_DownloadAsync(const String* url, const String* id) {
} }
Http_AsyncGetDataEx(url, true, id, &time, &etag, NULL); Http_AsyncGetDataEx(url, true, id, &time, &etag, NULL);
} }
/*########################################################################################################################*
*---------------------------------------------------Textures component----------------------------------------------------*
*#########################################################################################################################*/
static void OnFileChanged(void* obj, struct Stream* stream, const String* name) {
Bitmap bmp;
cc_result res;
if (!String_CaselessEqualsConst(name, "terrain.png")) return;
res = Png_Decode(&bmp, stream);
if (res) {
Logger_Warn2(res, "decoding", name);
Mem_Free(bmp.Scan0);
} else if (!Atlas_TryChange(&bmp)) {
Mem_Free(bmp.Scan0);
}
}
static void Textures_Init(void) {
Event_RegisterEntry(&TextureEvents.FileChanged, NULL, OnFileChanged);
TextureCache_Init();
}
static void Textures_Free(void) {
Event_UnregisterEntry(&TextureEvents.FileChanged, NULL, OnFileChanged);
Atlas_Free();
}
struct IGameComponent Textures_Component = {
Textures_Init, /* Init */
Textures_Free /* Free */
};

View File

@ -11,6 +11,8 @@
struct Stream; struct Stream;
struct HttpRequest; struct HttpRequest;
struct IGameComponent;
extern struct IGameComponent Textures_Component;
/* Number of tiles in each row */ /* Number of tiles in each row */
#define ATLAS2D_TILES_PER_ROW 16 #define ATLAS2D_TILES_PER_ROW 16
@ -56,20 +58,15 @@ CC_VAR extern struct _Atlas1DData {
/* Returns the index of the 1D atlas within the array of 1D atlases that contains the given tile id */ /* Returns the index of the 1D atlas within the array of 1D atlases that contains the given tile id */
#define Atlas1D_Index(texLoc) ((texLoc) >> Atlas1D.Shift) /* texLoc / Atlas1D_TilesPerAtlas */ #define Atlas1D_Index(texLoc) ((texLoc) >> Atlas1D.Shift) /* texLoc / Atlas1D_TilesPerAtlas */
/* Loads the given atlas and converts it into an array of 1D atlases. */
/* NOTE: Use Game_ChangeTerrainAtlas to change atlas, because that raises TextureEvents.AtlasChanged */
void Atlas_Update(Bitmap* bmp);
/* Loads the given tile into a new separate texture. */ /* Loads the given tile into a new separate texture. */
GfxResourceID Atlas2D_LoadTile(TextureLoc texLoc); GfxResourceID Atlas2D_LoadTile(TextureLoc texLoc);
/* Frees the atlas and 1D atlas textures. */ /* Attempts to change the terrain atlas. (bitmap containing textures for all blocks) */
void Atlas_Free(void); cc_bool Atlas_TryChange(Bitmap* bmp);
/* Returns the UV rectangle of the given tile id in the 1D atlases. */ /* Returns the UV rectangle of the given tile id in the 1D atlases. */
/* That is, returns U1/U2/V1/V2 coords that make up the tile in a 1D atlas. */ /* That is, returns U1/U2/V1/V2 coords that make up the tile in a 1D atlas. */
/* index is set to the index of the 1D atlas that the tile is in. */ /* index is set to the index of the 1D atlas that the tile is in. */
TextureRec Atlas1D_TexRec(TextureLoc texLoc, int uCount, int* index); TextureRec Atlas1D_TexRec(TextureLoc texLoc, int uCount, int* index);
/* Initialises cache state. (e.g. loading accepted/denied lists) */
void TextureCache_Init(void);
/* Whether the given URL is in list of accepted URLs. */ /* Whether the given URL is in list of accepted URLs. */
cc_bool TextureCache_HasAccepted(const String* url); cc_bool TextureCache_HasAccepted(const String* url);
/* Whether the given URL is in list of denied URLs. */ /* Whether the given URL is in list of denied URLs. */