mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 19:15:14 -04:00
Make Textures a component too, move some texture specific out of Game.c and into TexturePack.c
This commit is contained in:
parent
664428682c
commit
dcc6a12946
68
src/Game.c
68
src/Game.c
@ -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) {
|
||||
distance = min(distance, Game_MaxViewDistance);
|
||||
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) {
|
||||
if (Game_UserViewDistance <= 16) Logger_Abort("Out of video memory!");
|
||||
Game_UserViewDistance /= 2;
|
||||
@ -372,16 +333,12 @@ static void Game_Load(void) {
|
||||
Gfx_Init();
|
||||
LoadOptions();
|
||||
|
||||
Event_RegisterVoid(&WorldEvents.NewMap, NULL, HandleOnNewMap);
|
||||
Event_RegisterVoid(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded);
|
||||
Event_RegisterEntry(&TextureEvents.FileChanged, NULL, HandleTextureChanged);
|
||||
Event_RegisterVoid(&GfxEvents.LowVRAMDetected, NULL, HandleLowVRAMDetected);
|
||||
Event_RegisterVoid(&WorldEvents.NewMap, NULL, HandleOnNewMap);
|
||||
Event_RegisterVoid(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded);
|
||||
Event_RegisterVoid(&GfxEvents.LowVRAMDetected, NULL, HandleLowVRAMDetected);
|
||||
|
||||
Event_RegisterVoid(&WindowEvents.Resized, NULL, Game_OnResize);
|
||||
Event_RegisterVoid(&WindowEvents.Closing, NULL, Game_Free);
|
||||
|
||||
TextureCache_Init();
|
||||
/* TODO: Survival vs Creative game mode */
|
||||
Event_RegisterVoid(&WindowEvents.Resized, NULL, Game_OnResize);
|
||||
Event_RegisterVoid(&WindowEvents.Closing, NULL, Game_Free);
|
||||
|
||||
InputHandler_Init();
|
||||
Game_AddComponent(&Blocks_Component);
|
||||
@ -398,6 +355,7 @@ static void Game_Load(void) {
|
||||
|
||||
Game_AddComponent(&Animations_Component);
|
||||
Game_AddComponent(&Inventory_Component);
|
||||
Game_AddComponent(&Textures_Component);
|
||||
World_Reset();
|
||||
|
||||
Game_AddComponent(&Builder_Component);
|
||||
@ -602,16 +560,16 @@ static void Game_RenderFrame(double delta) {
|
||||
|
||||
void Game_Free(void* obj) {
|
||||
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;
|
||||
|
||||
Event_UnregisterVoid(&WorldEvents.NewMap, NULL, HandleOnNewMap);
|
||||
Event_UnregisterVoid(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded);
|
||||
Event_UnregisterEntry(&TextureEvents.FileChanged, NULL, HandleTextureChanged);
|
||||
Event_UnregisterVoid(&GfxEvents.LowVRAMDetected, NULL, HandleLowVRAMDetected);
|
||||
Event_UnregisterVoid(&WorldEvents.NewMap, NULL, HandleOnNewMap);
|
||||
Event_UnregisterVoid(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded);
|
||||
Event_UnregisterVoid(&GfxEvents.LowVRAMDetected, NULL, HandleLowVRAMDetected);
|
||||
|
||||
Event_UnregisterVoid(&WindowEvents.Resized, NULL, Game_OnResize);
|
||||
Event_UnregisterVoid(&WindowEvents.Closing, NULL, Game_Free);
|
||||
Event_UnregisterVoid(&WindowEvents.Resized, NULL, Game_OnResize);
|
||||
Event_UnregisterVoid(&WindowEvents.Closing, NULL, Game_Free);
|
||||
|
||||
for (comp = comps_head; comp; comp = comp->next) {
|
||||
if (comp->Free) comp->Free();
|
||||
|
@ -49,8 +49,6 @@ enum FpsLimitMethod {
|
||||
};
|
||||
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_UserSetViewDistance(int distance);
|
||||
void Game_SetFov(int fov);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "ExtMath.h"
|
||||
#include "Options.h"
|
||||
#include "Logger.h"
|
||||
#include "Chat.h" /* TODO avoid this include */
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------TerrainAtlas-------------------------------------------------------*
|
||||
@ -71,7 +72,8 @@ static void Atlas_Update1D(void) {
|
||||
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.TileSize = bmp->Width / ATLAS2D_TILES_PER_ROW;
|
||||
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;
|
||||
Mem_Free(Atlas2D.Bmp.Scan0);
|
||||
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-------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
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(&deniedList, "texturecache/deniedurls.txt", ' ');
|
||||
EntryList_Init(&etagCache, "texturecache/etags.txt", ' ');
|
||||
@ -295,7 +322,7 @@ static cc_result TexturePack_ExtractPng(struct Stream* stream) {
|
||||
|
||||
if (!res) {
|
||||
Event_RaiseVoid(&TextureEvents.PackChanged);
|
||||
if (Game_ChangeTerrainAtlas(&bmp)) return 0;
|
||||
if (Atlas_TryChange(&bmp)) return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------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 */
|
||||
};
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
struct Stream;
|
||||
struct HttpRequest;
|
||||
struct IGameComponent;
|
||||
extern struct IGameComponent Textures_Component;
|
||||
|
||||
/* Number of tiles in each row */
|
||||
#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 */
|
||||
#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. */
|
||||
GfxResourceID Atlas2D_LoadTile(TextureLoc texLoc);
|
||||
/* Frees the atlas and 1D atlas textures. */
|
||||
void Atlas_Free(void);
|
||||
/* Attempts to change the terrain atlas. (bitmap containing textures for all blocks) */
|
||||
cc_bool Atlas_TryChange(Bitmap* bmp);
|
||||
/* 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. */
|
||||
/* index is set to the index of the 1D atlas that the tile is in. */
|
||||
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. */
|
||||
cc_bool TextureCache_HasAccepted(const String* url);
|
||||
/* Whether the given URL is in list of denied URLs. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user