mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 11:35:08 -04:00
Split up TexturePack into Animations and TexturePack (they end up being about equal lines of code anyways), remove a bit more of unused freetype code
This commit is contained in:
parent
f476eee0c1
commit
664428682c
400
src/Animations.c
Normal file
400
src/Animations.c
Normal file
@ -0,0 +1,400 @@
|
||||
#include "TexturePack.h"
|
||||
#include "Constants.h"
|
||||
#include "Stream.h"
|
||||
#include "World.h"
|
||||
#include "Graphics.h"
|
||||
#include "Event.h"
|
||||
#include "Game.h"
|
||||
#include "Funcs.h"
|
||||
#include "Errors.h"
|
||||
#include "Chat.h"
|
||||
#include "ExtMath.h"
|
||||
#include "Options.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#define LIQUID_ANIM_MAX 64
|
||||
#define WATER_TEX_LOC 14
|
||||
#define LAVA_TEX_LOC 30
|
||||
|
||||
#ifndef CC_BUILD_WEB
|
||||
/* Based off the incredible work from https://dl.dropboxusercontent.com/u/12694594/lava.txt
|
||||
mirrored at https://github.com/UnknownShadow200/ClassicalSharp/wiki/Minecraft-Classic-lava-animation-algorithm
|
||||
Water animation originally written by cybertoon, big thanks!
|
||||
*/
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------Lava animation------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static float L_soupHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static float L_potHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static float L_flameHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static RNGState L_rnd;
|
||||
static cc_bool L_rndInited;
|
||||
|
||||
static void LavaAnimation_Tick(BitmapCol* ptr, int size) {
|
||||
int mask = size - 1, shift = Math_Log2(size);
|
||||
float soupHeat, potHeat, col;
|
||||
int x, y, i = 0;
|
||||
|
||||
if (!L_rndInited) {
|
||||
Random_SeedFromCurrentTime(&L_rnd);
|
||||
L_rndInited = true;
|
||||
}
|
||||
|
||||
for (y = 0; y < size; y++) {
|
||||
for (x = 0; x < size; x++) {
|
||||
/* Calculate the colour at this coordinate in the heatmap */
|
||||
|
||||
/* Lookup table for (int)(1.2 * sin([ANGLE] * 22.5 * MATH_DEG2RAD)); */
|
||||
/* [ANGLE] is integer x/y, so repeats every 16 intervals */
|
||||
static cc_int8 sin_adj_table[16] = { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0 };
|
||||
int xx = x + sin_adj_table[y & 0xF], yy = y + sin_adj_table[x & 0xF];
|
||||
|
||||
soupHeat =
|
||||
L_soupHeat[((yy - 1) & mask) << shift | ((xx - 1) & mask)] +
|
||||
L_soupHeat[((yy - 1) & mask) << shift | (xx & mask)] +
|
||||
L_soupHeat[((yy - 1) & mask) << shift | ((xx + 1) & mask)] +
|
||||
|
||||
L_soupHeat[(yy & mask) << shift | ((xx - 1) & mask)] +
|
||||
L_soupHeat[(yy & mask) << shift | (xx & mask)] +
|
||||
L_soupHeat[(yy & mask) << shift | ((xx + 1) & mask)] +
|
||||
|
||||
L_soupHeat[((yy + 1) & mask) << shift | ((xx - 1) & mask)] +
|
||||
L_soupHeat[((yy + 1) & mask) << shift | (xx & mask)] +
|
||||
L_soupHeat[((yy + 1) & mask) << shift | ((xx + 1) & mask)];
|
||||
|
||||
potHeat =
|
||||
L_potHeat[i] + /* x , y */
|
||||
L_potHeat[y << shift | ((x + 1) & mask)] + /* x + 1, y */
|
||||
L_potHeat[((y + 1) & mask) << shift | x] + /* x , y + 1 */
|
||||
L_potHeat[((y + 1) & mask) << shift | ((x + 1) & mask)];/* x + 1, y + 1 */
|
||||
|
||||
L_soupHeat[i] = soupHeat * 0.1f + potHeat * 0.2f;
|
||||
|
||||
L_potHeat[i] += L_flameHeat[i];
|
||||
if (L_potHeat[i] < 0.0f) L_potHeat[i] = 0.0f;
|
||||
|
||||
L_flameHeat[i] -= 0.06f * 0.01f;
|
||||
if (Random_Float(&L_rnd) <= 0.005f) L_flameHeat[i] = 1.5f * 0.01f;
|
||||
|
||||
/* Output the pixel */
|
||||
col = 2.0f * L_soupHeat[i];
|
||||
Math_Clamp(col, 0.0f, 1.0f);
|
||||
|
||||
*ptr = BitmapCol_Make(
|
||||
col * 100.0f + 155.0f,
|
||||
col * col * 255.0f,
|
||||
col * col * col * col * 128.0f,
|
||||
255);
|
||||
|
||||
ptr++; i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Water animation------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static float W_soupHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static float W_potHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static float W_flameHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static RNGState W_rnd;
|
||||
static cc_bool W_rndInited;
|
||||
|
||||
static void WaterAnimation_Tick(BitmapCol* ptr, int size) {
|
||||
int mask = size - 1, shift = Math_Log2(size);
|
||||
float soupHeat, col;
|
||||
int x, y, i = 0;
|
||||
|
||||
if (!W_rndInited) {
|
||||
Random_SeedFromCurrentTime(&W_rnd);
|
||||
W_rndInited = true;
|
||||
}
|
||||
|
||||
for (y = 0; y < size; y++) {
|
||||
for (x = 0; x < size; x++) {
|
||||
/* Calculate the colour at this coordinate in the heatmap */
|
||||
soupHeat =
|
||||
W_soupHeat[y << shift | ((x - 1) & mask)] +
|
||||
W_soupHeat[y << shift | x ] +
|
||||
W_soupHeat[y << shift | ((x + 1) & mask)];
|
||||
|
||||
W_soupHeat[i] = soupHeat / 3.3f + W_potHeat[i] * 0.8f;
|
||||
|
||||
W_potHeat[i] += W_flameHeat[i];
|
||||
if (W_potHeat[i] < 0.0f) W_potHeat[i] = 0.0f;
|
||||
|
||||
W_flameHeat[i] -= 0.1f * 0.05f;
|
||||
if (Random_Float(&W_rnd) <= 0.05f) W_flameHeat[i] = 0.5f * 0.05f;
|
||||
|
||||
/* Output the pixel */
|
||||
col = W_soupHeat[i];
|
||||
Math_Clamp(col, 0.0f, 1.0f);
|
||||
col = col * col;
|
||||
|
||||
*ptr = BitmapCol_Make(
|
||||
32.0f + col * 32.0f,
|
||||
50.0f + col * 64.0f,
|
||||
255,
|
||||
146.0f + col * 50.0f);
|
||||
|
||||
ptr++; i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Animations--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
struct AnimationData {
|
||||
TextureLoc texLoc; /* Tile (not pixel) coordinates in terrain.png */
|
||||
cc_uint16 frameX, frameY; /* Top left pixel coordinates of start frame in animatons.png */
|
||||
cc_uint16 frameSize; /* Size of each frame in pixel coordinates */
|
||||
cc_uint16 state; /* Current animation frame index */
|
||||
cc_uint16 statesCount; /* Total number of animation frames */
|
||||
cc_uint16 delay; /* Delay in ticks until next frame is drawn */
|
||||
cc_uint16 frameDelay; /* Delay between each frame */
|
||||
};
|
||||
|
||||
static Bitmap anims_bmp;
|
||||
static struct AnimationData anims_list[ATLAS1D_MAX_ATLASES];
|
||||
static int anims_count;
|
||||
static cc_bool anims_validated, useLavaAnim, useWaterAnim, alwaysLavaAnim, alwaysWaterAnim;
|
||||
#define ANIM_MIN_ARGS 7
|
||||
|
||||
static void Animations_ReadDescription(struct Stream* stream, const String* path) {
|
||||
String line; char lineBuffer[STRING_SIZE * 2];
|
||||
String parts[ANIM_MIN_ARGS];
|
||||
int count;
|
||||
struct AnimationData data = { 0 };
|
||||
cc_uint8 tileX, tileY;
|
||||
|
||||
cc_uint8 buffer[2048];
|
||||
struct Stream buffered;
|
||||
cc_result res;
|
||||
|
||||
String_InitArray(line, lineBuffer);
|
||||
/* ReadLine reads single byte at a time */
|
||||
Stream_ReadonlyBuffered(&buffered, stream, buffer, sizeof(buffer));
|
||||
|
||||
for (;;) {
|
||||
res = Stream_ReadLine(&buffered, &line);
|
||||
if (res == ERR_END_OF_STREAM) break;
|
||||
if (res) { Logger_Warn2(res, "reading from", path); break; }
|
||||
|
||||
if (!line.length || line.buffer[0] == '#') continue;
|
||||
count = String_UNSAFE_Split(&line, ' ', parts, ANIM_MIN_ARGS);
|
||||
if (count < ANIM_MIN_ARGS) {
|
||||
Chat_Add1("&cNot enough arguments for anim: %s", &line); continue;
|
||||
}
|
||||
|
||||
if (!Convert_ParseUInt8(&parts[0], &tileX) || tileX >= ATLAS2D_TILES_PER_ROW) {
|
||||
Chat_Add1("&cInvalid anim tile X coord: %s", &parts[0]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt8(&parts[1], &tileY) || tileY >= ATLAS2D_MAX_ROWS_COUNT) {
|
||||
Chat_Add1("&cInvalid anim tile Y coord: %s", &parts[1]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[2], &data.frameX)) {
|
||||
Chat_Add1("&cInvalid anim frame X coord: %s", &parts[2]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[3], &data.frameY)) {
|
||||
Chat_Add1("&cInvalid anim frame Y coord: %s", &parts[3]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[4], &data.frameSize) || !data.frameSize) {
|
||||
Chat_Add1("&cInvalid anim frame size: %s", &parts[4]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[5], &data.statesCount)) {
|
||||
Chat_Add1("&cInvalid anim states count: %s", &parts[5]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[6], &data.frameDelay)) {
|
||||
Chat_Add1("&cInvalid anim frame delay: %s", &parts[6]); continue;
|
||||
}
|
||||
|
||||
if (anims_count == Array_Elems(anims_list)) {
|
||||
Chat_AddRaw("&cCannot show over 512 animations"); return;
|
||||
}
|
||||
|
||||
data.texLoc = tileX + (tileY * ATLAS2D_TILES_PER_ROW);
|
||||
anims_list[anims_count++] = data;
|
||||
}
|
||||
}
|
||||
|
||||
#define ANIMS_FAST_SIZE 64
|
||||
static void Animations_Draw(struct AnimationData* data, TextureLoc texLoc, int size) {
|
||||
int dstX = Atlas1D_Index(texLoc), srcX;
|
||||
int dstY = Atlas1D_RowId(texLoc) * Atlas2D.TileSize;
|
||||
GfxResourceID tex;
|
||||
|
||||
cc_uint8 buffer[Bitmap_DataSize(ANIMS_FAST_SIZE, ANIMS_FAST_SIZE)];
|
||||
cc_uint8* ptr = buffer;
|
||||
Bitmap frame;
|
||||
|
||||
/* cannot allocate memory on the stack for very big animation.png frames */
|
||||
if (size > ANIMS_FAST_SIZE) {
|
||||
ptr = (cc_uint8*)Mem_Alloc(size * size, 4, "anim frame");
|
||||
}
|
||||
Bitmap_Init(frame, size, size, ptr);
|
||||
|
||||
if (!data) {
|
||||
#ifndef CC_BUILD_WEB
|
||||
if (texLoc == LAVA_TEX_LOC) {
|
||||
LavaAnimation_Tick((BitmapCol*)frame.Scan0, size);
|
||||
} else if (texLoc == WATER_TEX_LOC) {
|
||||
WaterAnimation_Tick((BitmapCol*)frame.Scan0, size);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
srcX = data->frameX + data->state * size;
|
||||
Bitmap_UNSAFE_CopyBlock(srcX, data->frameY, 0, 0, &anims_bmp, &frame, size);
|
||||
}
|
||||
|
||||
tex = Atlas1D.TexIds[dstX];
|
||||
if (tex) { Gfx_UpdateTexturePart(tex, 0, dstY, &frame, Gfx.Mipmaps); }
|
||||
if (size > ANIMS_FAST_SIZE) Mem_Free(ptr);
|
||||
}
|
||||
|
||||
static void Animations_Apply(struct AnimationData* data) {
|
||||
TextureLoc loc;
|
||||
if (data->delay) { data->delay--; return; }
|
||||
|
||||
data->state++;
|
||||
data->state %= data->statesCount;
|
||||
data->delay = data->frameDelay;
|
||||
|
||||
loc = data->texLoc;
|
||||
#ifndef CC_BUILD_WEB
|
||||
if (loc == LAVA_TEX_LOC && useLavaAnim) return;
|
||||
if (loc == WATER_TEX_LOC && useWaterAnim) return;
|
||||
#endif
|
||||
Animations_Draw(data, loc, data->frameSize);
|
||||
}
|
||||
|
||||
static cc_bool Animations_IsDefaultZip(void) {
|
||||
String texPack;
|
||||
cc_bool optExists;
|
||||
if (World_TextureUrl.length) return false;
|
||||
|
||||
optExists = Options_UNSAFE_Get(OPT_DEFAULT_TEX_PACK, &texPack);
|
||||
return !optExists || String_CaselessEqualsConst(&texPack, "default.zip");
|
||||
}
|
||||
|
||||
static void Animations_Clear(void) {
|
||||
Mem_Free(anims_bmp.Scan0);
|
||||
anims_count = 0;
|
||||
anims_bmp.Scan0 = NULL;
|
||||
anims_validated = false;
|
||||
}
|
||||
|
||||
static void Animations_Validate(void) {
|
||||
struct AnimationData data;
|
||||
int maxX, maxY, tileX, tileY;
|
||||
int i, j;
|
||||
|
||||
anims_validated = true;
|
||||
for (i = 0; i < anims_count; i++) {
|
||||
data = anims_list[i];
|
||||
|
||||
maxX = data.frameX + data.frameSize * data.statesCount;
|
||||
maxY = data.frameY + data.frameSize;
|
||||
tileX = Atlas2D_TileX(data.texLoc);
|
||||
tileY = Atlas2D_TileY(data.texLoc);
|
||||
|
||||
if (data.frameSize > Atlas2D.TileSize || tileY >= Atlas2D.RowsCount) {
|
||||
Chat_Add2("&cAnimation frames for tile (%i, %i) are bigger than the size of a tile in terrain.png", &tileX, &tileY);
|
||||
} else if (maxX > anims_bmp.Width || maxY > anims_bmp.Height) {
|
||||
Chat_Add2("&cSome of the animation frames for tile (%i, %i) are at coordinates outside animations.png", &tileX, &tileY);
|
||||
} else {
|
||||
/* if user has water/lava animations in their default.zip, disable built-in */
|
||||
/* However, 'usewateranim' and 'uselavaanim' files should always disable use */
|
||||
/* of custom water/lava animations, even when they exist in animations.png */
|
||||
if (data.texLoc == LAVA_TEX_LOC && !alwaysLavaAnim) useLavaAnim = false;
|
||||
if (data.texLoc == WATER_TEX_LOC && !alwaysWaterAnim) useWaterAnim = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove this animation from the list */
|
||||
for (j = i; j < anims_count - 1; j++) {
|
||||
anims_list[j] = anims_list[j + 1];
|
||||
}
|
||||
i--; anims_count--;
|
||||
}
|
||||
}
|
||||
|
||||
static void Animations_Tick(struct ScheduledTask* task) {
|
||||
int i, size;
|
||||
|
||||
#ifndef CC_BUILD_WEB
|
||||
if (useLavaAnim) {
|
||||
size = min(Atlas2D.TileSize, 64);
|
||||
Animations_Draw(NULL, LAVA_TEX_LOC, size);
|
||||
}
|
||||
if (useWaterAnim) {
|
||||
size = min(Atlas2D.TileSize, 64);
|
||||
Animations_Draw(NULL, WATER_TEX_LOC, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!anims_count) return;
|
||||
if (!anims_bmp.Scan0) {
|
||||
Chat_AddRaw("&cCurrent texture pack specifies it uses animations,");
|
||||
Chat_AddRaw("&cbut is missing animations.png");
|
||||
anims_count = 0; return;
|
||||
}
|
||||
|
||||
/* deferred, because when reading animations.txt, might not have read animations.png yet */
|
||||
if (!anims_validated) Animations_Validate();
|
||||
for (i = 0; i < anims_count; i++) {
|
||||
Animations_Apply(&anims_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------Animations component---------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void OnPackChanged(void* obj) {
|
||||
Animations_Clear();
|
||||
useLavaAnim = Animations_IsDefaultZip();
|
||||
useWaterAnim = useLavaAnim;
|
||||
alwaysLavaAnim = false;
|
||||
alwaysWaterAnim = false;
|
||||
}
|
||||
|
||||
static void OnFileChanged(void* obj, struct Stream* stream, const String* name) {
|
||||
cc_result res;
|
||||
if (String_CaselessEqualsConst(name, "animations.png")) {
|
||||
res = Png_Decode(&anims_bmp, stream);
|
||||
if (!res) return;
|
||||
|
||||
Logger_Warn2(res, "decoding", name);
|
||||
Mem_Free(anims_bmp.Scan0);
|
||||
anims_bmp.Scan0 = NULL;
|
||||
} else if (String_CaselessEqualsConst(name, "animations.txt")) {
|
||||
Animations_ReadDescription(stream, name);
|
||||
} else if (String_CaselessEqualsConst(name, "uselavaanim")) {
|
||||
useLavaAnim = true;
|
||||
alwaysLavaAnim = true;
|
||||
} else if (String_CaselessEqualsConst(name, "usewateranim")) {
|
||||
useWaterAnim = true;
|
||||
alwaysWaterAnim = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void Animations_Init(void) {
|
||||
ScheduledTask_Add(GAME_DEF_TICKS, Animations_Tick);
|
||||
Event_RegisterVoid(&TextureEvents.PackChanged, NULL, OnPackChanged);
|
||||
Event_RegisterEntry(&TextureEvents.FileChanged, NULL, OnFileChanged);
|
||||
}
|
||||
|
||||
static void Animations_Free(void) {
|
||||
Animations_Clear();
|
||||
Event_UnregisterVoid(&TextureEvents.PackChanged, NULL, OnPackChanged);
|
||||
Event_UnregisterEntry(&TextureEvents.FileChanged, NULL, OnFileChanged);
|
||||
}
|
||||
|
||||
struct IGameComponent Animations_Component = {
|
||||
Animations_Init, /* Init */
|
||||
Animations_Free /* Free */
|
||||
};
|
9
src/Animations.h
Normal file
9
src/Animations.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef CC_ANIMATIONS_H
|
||||
#define CC_ANIMATIONS_H
|
||||
/* Contains everything relating to texture animations (including default water/lava ones)
|
||||
Copyright 2014-2020 ClassiCube | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
struct IGameComponent;
|
||||
extern struct IGameComponent Animations_Component;
|
||||
#endif
|
@ -187,6 +187,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Animations.h" />
|
||||
<ClInclude Include="Http.h" />
|
||||
<ClInclude Include="Audio.h" />
|
||||
<ClInclude Include="AxisLinesRenderer.h" />
|
||||
@ -250,6 +251,7 @@
|
||||
<ClInclude Include="World.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Animations.c" />
|
||||
<ClCompile Include="Http.c" />
|
||||
<ClCompile Include="Audio.c" />
|
||||
<ClCompile Include="Camera.c" />
|
||||
|
@ -309,6 +309,9 @@
|
||||
<ClInclude Include="Graphics.h">
|
||||
<Filter>Header Files\Graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Animations.h">
|
||||
<Filter>Header Files\TexturePack</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="String.c">
|
||||
@ -530,5 +533,8 @@
|
||||
<ClCompile Include="Graphics.c">
|
||||
<Filter>Source Files\Graphics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Animations.c">
|
||||
<Filter>Source Files\TexturePack</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -35,6 +35,7 @@
|
||||
#include "Builder.h"
|
||||
#include "Protocol.h"
|
||||
#include "Picking.h"
|
||||
#include "Animations.h"
|
||||
|
||||
struct _GameData Game;
|
||||
int Game_Port;
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "TexturePack.h"
|
||||
#include "Constants.h"
|
||||
#include "Platform.h"
|
||||
#include "Stream.h"
|
||||
#include "World.h"
|
||||
#include "Graphics.h"
|
||||
@ -9,403 +8,11 @@
|
||||
#include "Http.h"
|
||||
#include "Platform.h"
|
||||
#include "Deflate.h"
|
||||
#include "Stream.h"
|
||||
#include "Funcs.h"
|
||||
#include "Errors.h"
|
||||
#include "Chat.h"
|
||||
#include "ExtMath.h"
|
||||
#include "Chat.h"
|
||||
#include "Options.h"
|
||||
#include "Logger.h"
|
||||
|
||||
#define LIQUID_ANIM_MAX 64
|
||||
#define WATER_TEX_LOC 14
|
||||
#define LAVA_TEX_LOC 30
|
||||
|
||||
#ifndef CC_BUILD_WEB
|
||||
/* Based off the incredible work from https://dl.dropboxusercontent.com/u/12694594/lava.txt
|
||||
mirrored at https://github.com/UnknownShadow200/ClassicalSharp/wiki/Minecraft-Classic-lava-animation-algorithm
|
||||
Water animation originally written by cybertoon, big thanks!
|
||||
*/
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------Lava animation------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static float L_soupHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static float L_potHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static float L_flameHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static RNGState L_rnd;
|
||||
static cc_bool L_rndInited;
|
||||
|
||||
static void LavaAnimation_Tick(BitmapCol* ptr, int size) {
|
||||
int mask = size - 1, shift = Math_Log2(size);
|
||||
float soupHeat, potHeat, col;
|
||||
int x, y, i = 0;
|
||||
|
||||
if (!L_rndInited) {
|
||||
Random_SeedFromCurrentTime(&L_rnd);
|
||||
L_rndInited = true;
|
||||
}
|
||||
|
||||
for (y = 0; y < size; y++) {
|
||||
for (x = 0; x < size; x++) {
|
||||
/* Calculate the colour at this coordinate in the heatmap */
|
||||
|
||||
/* Lookup table for (int)(1.2 * sin([ANGLE] * 22.5 * MATH_DEG2RAD)); */
|
||||
/* [ANGLE] is integer x/y, so repeats every 16 intervals */
|
||||
static cc_int8 sin_adj_table[16] = { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0 };
|
||||
int xx = x + sin_adj_table[y & 0xF], yy = y + sin_adj_table[x & 0xF];
|
||||
|
||||
soupHeat =
|
||||
L_soupHeat[((yy - 1) & mask) << shift | ((xx - 1) & mask)] +
|
||||
L_soupHeat[((yy - 1) & mask) << shift | (xx & mask)] +
|
||||
L_soupHeat[((yy - 1) & mask) << shift | ((xx + 1) & mask)] +
|
||||
|
||||
L_soupHeat[(yy & mask) << shift | ((xx - 1) & mask)] +
|
||||
L_soupHeat[(yy & mask) << shift | (xx & mask)] +
|
||||
L_soupHeat[(yy & mask) << shift | ((xx + 1) & mask)] +
|
||||
|
||||
L_soupHeat[((yy + 1) & mask) << shift | ((xx - 1) & mask)] +
|
||||
L_soupHeat[((yy + 1) & mask) << shift | (xx & mask)] +
|
||||
L_soupHeat[((yy + 1) & mask) << shift | ((xx + 1) & mask)];
|
||||
|
||||
potHeat =
|
||||
L_potHeat[i] + /* x , y */
|
||||
L_potHeat[y << shift | ((x + 1) & mask)] + /* x + 1, y */
|
||||
L_potHeat[((y + 1) & mask) << shift | x] + /* x , y + 1 */
|
||||
L_potHeat[((y + 1) & mask) << shift | ((x + 1) & mask)];/* x + 1, y + 1 */
|
||||
|
||||
L_soupHeat[i] = soupHeat * 0.1f + potHeat * 0.2f;
|
||||
|
||||
L_potHeat[i] += L_flameHeat[i];
|
||||
if (L_potHeat[i] < 0.0f) L_potHeat[i] = 0.0f;
|
||||
|
||||
L_flameHeat[i] -= 0.06f * 0.01f;
|
||||
if (Random_Float(&L_rnd) <= 0.005f) L_flameHeat[i] = 1.5f * 0.01f;
|
||||
|
||||
/* Output the pixel */
|
||||
col = 2.0f * L_soupHeat[i];
|
||||
Math_Clamp(col, 0.0f, 1.0f);
|
||||
|
||||
*ptr = BitmapCol_Make(
|
||||
col * 100.0f + 155.0f,
|
||||
col * col * 255.0f,
|
||||
col * col * col * col * 128.0f,
|
||||
255);
|
||||
|
||||
ptr++; i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Water animation------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static float W_soupHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static float W_potHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static float W_flameHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
|
||||
static RNGState W_rnd;
|
||||
static cc_bool W_rndInited;
|
||||
|
||||
static void WaterAnimation_Tick(BitmapCol* ptr, int size) {
|
||||
int mask = size - 1, shift = Math_Log2(size);
|
||||
float soupHeat, col;
|
||||
int x, y, i = 0;
|
||||
|
||||
if (!W_rndInited) {
|
||||
Random_SeedFromCurrentTime(&W_rnd);
|
||||
W_rndInited = true;
|
||||
}
|
||||
|
||||
for (y = 0; y < size; y++) {
|
||||
for (x = 0; x < size; x++) {
|
||||
/* Calculate the colour at this coordinate in the heatmap */
|
||||
soupHeat =
|
||||
W_soupHeat[y << shift | ((x - 1) & mask)] +
|
||||
W_soupHeat[y << shift | x ] +
|
||||
W_soupHeat[y << shift | ((x + 1) & mask)];
|
||||
|
||||
W_soupHeat[i] = soupHeat / 3.3f + W_potHeat[i] * 0.8f;
|
||||
|
||||
W_potHeat[i] += W_flameHeat[i];
|
||||
if (W_potHeat[i] < 0.0f) W_potHeat[i] = 0.0f;
|
||||
|
||||
W_flameHeat[i] -= 0.1f * 0.05f;
|
||||
if (Random_Float(&W_rnd) <= 0.05f) W_flameHeat[i] = 0.5f * 0.05f;
|
||||
|
||||
/* Output the pixel */
|
||||
col = W_soupHeat[i];
|
||||
Math_Clamp(col, 0.0f, 1.0f);
|
||||
col = col * col;
|
||||
|
||||
*ptr = BitmapCol_Make(
|
||||
32.0f + col * 32.0f,
|
||||
50.0f + col * 64.0f,
|
||||
255,
|
||||
146.0f + col * 50.0f);
|
||||
|
||||
ptr++; i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Animations--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
struct AnimationData {
|
||||
TextureLoc texLoc; /* Tile (not pixel) coordinates in terrain.png */
|
||||
cc_uint16 frameX, frameY; /* Top left pixel coordinates of start frame in animatons.png */
|
||||
cc_uint16 frameSize; /* Size of each frame in pixel coordinates */
|
||||
cc_uint16 state; /* Current animation frame index */
|
||||
cc_uint16 statesCount; /* Total number of animation frames */
|
||||
cc_uint16 delay; /* Delay in ticks until next frame is drawn */
|
||||
cc_uint16 frameDelay; /* Delay between each frame */
|
||||
};
|
||||
|
||||
static Bitmap anims_bmp;
|
||||
static struct AnimationData anims_list[ATLAS1D_MAX_ATLASES];
|
||||
static int anims_count;
|
||||
static cc_bool anims_validated, useLavaAnim, useWaterAnim, alwaysLavaAnim, alwaysWaterAnim;
|
||||
#define ANIM_MIN_ARGS 7
|
||||
|
||||
static void Animations_ReadDescription(struct Stream* stream, const String* path) {
|
||||
String line; char lineBuffer[STRING_SIZE * 2];
|
||||
String parts[ANIM_MIN_ARGS];
|
||||
int count;
|
||||
struct AnimationData data = { 0 };
|
||||
cc_uint8 tileX, tileY;
|
||||
|
||||
cc_uint8 buffer[2048];
|
||||
struct Stream buffered;
|
||||
cc_result res;
|
||||
|
||||
String_InitArray(line, lineBuffer);
|
||||
/* ReadLine reads single byte at a time */
|
||||
Stream_ReadonlyBuffered(&buffered, stream, buffer, sizeof(buffer));
|
||||
|
||||
for (;;) {
|
||||
res = Stream_ReadLine(&buffered, &line);
|
||||
if (res == ERR_END_OF_STREAM) break;
|
||||
if (res) { Logger_Warn2(res, "reading from", path); break; }
|
||||
|
||||
if (!line.length || line.buffer[0] == '#') continue;
|
||||
count = String_UNSAFE_Split(&line, ' ', parts, ANIM_MIN_ARGS);
|
||||
if (count < ANIM_MIN_ARGS) {
|
||||
Chat_Add1("&cNot enough arguments for anim: %s", &line); continue;
|
||||
}
|
||||
|
||||
if (!Convert_ParseUInt8(&parts[0], &tileX) || tileX >= ATLAS2D_TILES_PER_ROW) {
|
||||
Chat_Add1("&cInvalid anim tile X coord: %s", &parts[0]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt8(&parts[1], &tileY) || tileY >= ATLAS2D_MAX_ROWS_COUNT) {
|
||||
Chat_Add1("&cInvalid anim tile Y coord: %s", &parts[1]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[2], &data.frameX)) {
|
||||
Chat_Add1("&cInvalid anim frame X coord: %s", &parts[2]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[3], &data.frameY)) {
|
||||
Chat_Add1("&cInvalid anim frame Y coord: %s", &parts[3]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[4], &data.frameSize) || !data.frameSize) {
|
||||
Chat_Add1("&cInvalid anim frame size: %s", &parts[4]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[5], &data.statesCount)) {
|
||||
Chat_Add1("&cInvalid anim states count: %s", &parts[5]); continue;
|
||||
}
|
||||
if (!Convert_ParseUInt16(&parts[6], &data.frameDelay)) {
|
||||
Chat_Add1("&cInvalid anim frame delay: %s", &parts[6]); continue;
|
||||
}
|
||||
|
||||
if (anims_count == Array_Elems(anims_list)) {
|
||||
Chat_AddRaw("&cCannot show over 512 animations"); return;
|
||||
}
|
||||
|
||||
data.texLoc = tileX + (tileY * ATLAS2D_TILES_PER_ROW);
|
||||
anims_list[anims_count++] = data;
|
||||
}
|
||||
}
|
||||
|
||||
#define ANIMS_FAST_SIZE 64
|
||||
static void Animations_Draw(struct AnimationData* data, TextureLoc texLoc, int size) {
|
||||
int dstX = Atlas1D_Index(texLoc), srcX;
|
||||
int dstY = Atlas1D_RowId(texLoc) * Atlas2D.TileSize;
|
||||
GfxResourceID tex;
|
||||
|
||||
cc_uint8 buffer[Bitmap_DataSize(ANIMS_FAST_SIZE, ANIMS_FAST_SIZE)];
|
||||
cc_uint8* ptr = buffer;
|
||||
Bitmap frame;
|
||||
|
||||
/* cannot allocate memory on the stack for very big animation.png frames */
|
||||
if (size > ANIMS_FAST_SIZE) {
|
||||
ptr = (cc_uint8*)Mem_Alloc(size * size, 4, "anim frame");
|
||||
}
|
||||
Bitmap_Init(frame, size, size, ptr);
|
||||
|
||||
if (!data) {
|
||||
#ifndef CC_BUILD_WEB
|
||||
if (texLoc == LAVA_TEX_LOC) {
|
||||
LavaAnimation_Tick((BitmapCol*)frame.Scan0, size);
|
||||
} else if (texLoc == WATER_TEX_LOC) {
|
||||
WaterAnimation_Tick((BitmapCol*)frame.Scan0, size);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
srcX = data->frameX + data->state * size;
|
||||
Bitmap_UNSAFE_CopyBlock(srcX, data->frameY, 0, 0, &anims_bmp, &frame, size);
|
||||
}
|
||||
|
||||
tex = Atlas1D.TexIds[dstX];
|
||||
if (tex) { Gfx_UpdateTexturePart(tex, 0, dstY, &frame, Gfx.Mipmaps); }
|
||||
if (size > ANIMS_FAST_SIZE) Mem_Free(ptr);
|
||||
}
|
||||
|
||||
static void Animations_Apply(struct AnimationData* data) {
|
||||
TextureLoc loc;
|
||||
if (data->delay) { data->delay--; return; }
|
||||
|
||||
data->state++;
|
||||
data->state %= data->statesCount;
|
||||
data->delay = data->frameDelay;
|
||||
|
||||
loc = data->texLoc;
|
||||
#ifndef CC_BUILD_WEB
|
||||
if (loc == LAVA_TEX_LOC && useLavaAnim) return;
|
||||
if (loc == WATER_TEX_LOC && useWaterAnim) return;
|
||||
#endif
|
||||
Animations_Draw(data, loc, data->frameSize);
|
||||
}
|
||||
|
||||
static cc_bool Animations_IsDefaultZip(void) {
|
||||
String texPack;
|
||||
cc_bool optExists;
|
||||
if (World_TextureUrl.length) return false;
|
||||
|
||||
optExists = Options_UNSAFE_Get(OPT_DEFAULT_TEX_PACK, &texPack);
|
||||
return !optExists || String_CaselessEqualsConst(&texPack, "default.zip");
|
||||
}
|
||||
|
||||
static void Animations_Clear(void) {
|
||||
Mem_Free(anims_bmp.Scan0);
|
||||
anims_count = 0;
|
||||
anims_bmp.Scan0 = NULL;
|
||||
anims_validated = false;
|
||||
}
|
||||
|
||||
static void Animations_Validate(void) {
|
||||
struct AnimationData data;
|
||||
int maxX, maxY, tileX, tileY;
|
||||
int i, j;
|
||||
|
||||
anims_validated = true;
|
||||
for (i = 0; i < anims_count; i++) {
|
||||
data = anims_list[i];
|
||||
|
||||
maxX = data.frameX + data.frameSize * data.statesCount;
|
||||
maxY = data.frameY + data.frameSize;
|
||||
tileX = Atlas2D_TileX(data.texLoc);
|
||||
tileY = Atlas2D_TileY(data.texLoc);
|
||||
|
||||
if (data.frameSize > Atlas2D.TileSize || tileY >= Atlas2D.RowsCount) {
|
||||
Chat_Add2("&cAnimation frames for tile (%i, %i) are bigger than the size of a tile in terrain.png", &tileX, &tileY);
|
||||
} else if (maxX > anims_bmp.Width || maxY > anims_bmp.Height) {
|
||||
Chat_Add2("&cSome of the animation frames for tile (%i, %i) are at coordinates outside animations.png", &tileX, &tileY);
|
||||
} else {
|
||||
/* if user has water/lava animations in their default.zip, disable built-in */
|
||||
/* However, 'usewateranim' and 'uselavaanim' files should always disable use */
|
||||
/* of custom water/lava animations, even when they exist in animations.png */
|
||||
if (data.texLoc == LAVA_TEX_LOC && !alwaysLavaAnim) useLavaAnim = false;
|
||||
if (data.texLoc == WATER_TEX_LOC && !alwaysWaterAnim) useWaterAnim = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove this animation from the list */
|
||||
for (j = i; j < anims_count - 1; j++) {
|
||||
anims_list[j] = anims_list[j + 1];
|
||||
}
|
||||
i--; anims_count--;
|
||||
}
|
||||
}
|
||||
|
||||
static void Animations_Tick(struct ScheduledTask* task) {
|
||||
int i, size;
|
||||
|
||||
#ifndef CC_BUILD_WEB
|
||||
if (useLavaAnim) {
|
||||
size = min(Atlas2D.TileSize, 64);
|
||||
Animations_Draw(NULL, LAVA_TEX_LOC, size);
|
||||
}
|
||||
if (useWaterAnim) {
|
||||
size = min(Atlas2D.TileSize, 64);
|
||||
Animations_Draw(NULL, WATER_TEX_LOC, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!anims_count) return;
|
||||
if (!anims_bmp.Scan0) {
|
||||
Chat_AddRaw("&cCurrent texture pack specifies it uses animations,");
|
||||
Chat_AddRaw("&cbut is missing animations.png");
|
||||
anims_count = 0; return;
|
||||
}
|
||||
|
||||
/* deferred, because when reading animations.txt, might not have read animations.png yet */
|
||||
if (!anims_validated) Animations_Validate();
|
||||
for (i = 0; i < anims_count; i++) {
|
||||
Animations_Apply(&anims_list[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------Animations component---------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void OnPackChanged(void* obj) {
|
||||
Animations_Clear();
|
||||
useLavaAnim = Animations_IsDefaultZip();
|
||||
useWaterAnim = useLavaAnim;
|
||||
alwaysLavaAnim = false;
|
||||
alwaysWaterAnim = false;
|
||||
}
|
||||
|
||||
static void OnFileChanged(void* obj, struct Stream* stream, const String* name) {
|
||||
cc_result res;
|
||||
if (String_CaselessEqualsConst(name, "animations.png")) {
|
||||
res = Png_Decode(&anims_bmp, stream);
|
||||
if (!res) return;
|
||||
|
||||
Logger_Warn2(res, "decoding", name);
|
||||
Mem_Free(anims_bmp.Scan0);
|
||||
anims_bmp.Scan0 = NULL;
|
||||
} else if (String_CaselessEqualsConst(name, "animations.txt")) {
|
||||
Animations_ReadDescription(stream, name);
|
||||
} else if (String_CaselessEqualsConst(name, "uselavaanim")) {
|
||||
useLavaAnim = true;
|
||||
alwaysLavaAnim = true;
|
||||
} else if (String_CaselessEqualsConst(name, "usewateranim")) {
|
||||
useWaterAnim = true;
|
||||
alwaysWaterAnim = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void Animations_Init(void) {
|
||||
ScheduledTask_Add(GAME_DEF_TICKS, Animations_Tick);
|
||||
Event_RegisterVoid(&TextureEvents.PackChanged, NULL, OnPackChanged);
|
||||
Event_RegisterEntry(&TextureEvents.FileChanged, NULL, OnFileChanged);
|
||||
}
|
||||
|
||||
static void Animations_Free(void) {
|
||||
Animations_Clear();
|
||||
Event_UnregisterVoid(&TextureEvents.PackChanged, NULL, OnPackChanged);
|
||||
Event_UnregisterEntry(&TextureEvents.FileChanged, NULL, OnFileChanged);
|
||||
}
|
||||
|
||||
struct IGameComponent Animations_Component = {
|
||||
Animations_Init, /* Init */
|
||||
Animations_Free /* Free */
|
||||
};
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------TerrainAtlas-------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
|
@ -6,13 +6,11 @@
|
||||
- Extracting the textures from a .zip archive
|
||||
- Caching terrain atlases and texture packs to avoid redundant downloads
|
||||
- Terrain atlas (including breaking it down into multiple 1D atlases)
|
||||
- Texture animations (including default water/lava ones)
|
||||
Copyright 2014-2020 ClassiCube | Licensed under BSD-3 */
|
||||
Copyright 2014-2020 ClassiCube | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
struct Stream;
|
||||
struct HttpRequest;
|
||||
struct IGameComponent;
|
||||
extern struct IGameComponent Animations_Component;
|
||||
|
||||
/* Number of tiles in each row */
|
||||
#define ATLAS2D_TILES_PER_ROW 16
|
||||
|
@ -36,40 +36,6 @@
|
||||
#define FT_COMPONENT trace_afmodule
|
||||
|
||||
|
||||
static FT_Error
|
||||
af_property_get_face_globals( FT_Face face,
|
||||
AF_FaceGlobals* aglobals,
|
||||
AF_Module module )
|
||||
{
|
||||
FT_Error error = FT_Err_Ok;
|
||||
AF_FaceGlobals globals;
|
||||
|
||||
|
||||
if ( !face )
|
||||
return FT_THROW( Invalid_Face_Handle );
|
||||
|
||||
globals = (AF_FaceGlobals)face->autohint.data;
|
||||
if ( !globals )
|
||||
{
|
||||
/* trigger computation of the global style data */
|
||||
/* in case it hasn't been done yet */
|
||||
error = af_face_globals_new( face, &globals, module );
|
||||
if ( !error )
|
||||
{
|
||||
face->autohint.data =
|
||||
(FT_Pointer)globals;
|
||||
face->autohint.finalizer =
|
||||
(FT_Generic_Finalizer)af_face_globals_free;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !error )
|
||||
*aglobals = globals;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static const FT_ServiceDescRec af_services[] =
|
||||
{
|
||||
{ NULL, NULL }
|
||||
|
@ -374,24 +374,6 @@
|
||||
}
|
||||
|
||||
|
||||
FT_BASE_DEF( FT_ULong )
|
||||
FT_Stream_GetUOffset( FT_Stream stream )
|
||||
{
|
||||
FT_Byte* p;
|
||||
FT_ULong result;
|
||||
|
||||
|
||||
FT_ASSERT( stream && stream->cursor );
|
||||
|
||||
result = 0;
|
||||
p = stream->cursor;
|
||||
if ( p + 2 < stream->limit )
|
||||
result = FT_NEXT_UOFF3( p );
|
||||
stream->cursor = p;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FT_BASE_DEF( FT_ULong )
|
||||
FT_Stream_GetULong( FT_Stream stream )
|
||||
{
|
||||
@ -410,24 +392,6 @@
|
||||
}
|
||||
|
||||
|
||||
FT_BASE_DEF( FT_ULong )
|
||||
FT_Stream_GetULongLE( FT_Stream stream )
|
||||
{
|
||||
FT_Byte* p;
|
||||
FT_ULong result;
|
||||
|
||||
|
||||
FT_ASSERT( stream && stream->cursor );
|
||||
|
||||
result = 0;
|
||||
p = stream->cursor;
|
||||
if ( p + 3 < stream->limit )
|
||||
result = FT_NEXT_ULONG_LE( p );
|
||||
stream->cursor = p;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
FT_BASE_DEF( FT_Char )
|
||||
FT_Stream_ReadChar( FT_Stream stream,
|
||||
FT_Error* error )
|
||||
|
@ -205,10 +205,6 @@ FT_BEGIN_HEADER
|
||||
FT_BYTE_U32( p, 1, 8 ) | \
|
||||
FT_BYTE_U32( p, 0, 0 ) )
|
||||
|
||||
#define FT_PEEK_OFF3_LE( p ) FT_INT32( FT_BYTE_U32( p, 2, 16 ) | \
|
||||
FT_BYTE_U32( p, 1, 8 ) | \
|
||||
FT_BYTE_U32( p, 0, 0 ) )
|
||||
|
||||
#define FT_PEEK_UOFF3_LE( p ) FT_UINT32( FT_BYTE_U32( p, 2, 16 ) | \
|
||||
FT_BYTE_U32( p, 1, 8 ) | \
|
||||
FT_BYTE_U32( p, 0, 0 ) )
|
||||
@ -245,9 +241,6 @@ FT_BEGIN_HEADER
|
||||
#define FT_NEXT_USHORT_LE( buffer ) \
|
||||
( (unsigned short)( buffer += 2, FT_PEEK_USHORT_LE( buffer - 2 ) ) )
|
||||
|
||||
#define FT_NEXT_OFF3_LE( buffer ) \
|
||||
( (long)( buffer += 3, FT_PEEK_OFF3_LE( buffer - 3 ) ) )
|
||||
|
||||
#define FT_NEXT_UOFF3_LE( buffer ) \
|
||||
( (unsigned long)( buffer += 3, FT_PEEK_UOFF3_LE( buffer - 3 ) ) )
|
||||
|
||||
@ -269,16 +262,12 @@ FT_BEGIN_HEADER
|
||||
#define FT_GET_BYTE() FT_GET_MACRO( BYTE )
|
||||
#define FT_GET_SHORT() FT_GET_MACRO( SHORT )
|
||||
#define FT_GET_USHORT() FT_GET_MACRO( USHORT )
|
||||
#define FT_GET_OFF3() FT_GET_MACRO( OFF3 )
|
||||
#define FT_GET_UOFF3() FT_GET_MACRO( UOFF3 )
|
||||
#define FT_GET_LONG() FT_GET_MACRO( LONG )
|
||||
#define FT_GET_ULONG() FT_GET_MACRO( ULONG )
|
||||
#define FT_GET_TAG4() FT_GET_MACRO( ULONG )
|
||||
|
||||
#define FT_GET_SHORT_LE() FT_GET_MACRO( SHORT_LE )
|
||||
#define FT_GET_USHORT_LE() FT_GET_MACRO( USHORT_LE )
|
||||
#define FT_GET_LONG_LE() FT_GET_MACRO( LONG_LE )
|
||||
#define FT_GET_ULONG_LE() FT_GET_MACRO( ULONG_LE )
|
||||
|
||||
#else
|
||||
#define FT_GET_MACRO( func, type ) ( (type)func( stream ) )
|
||||
@ -287,16 +276,12 @@ FT_BEGIN_HEADER
|
||||
#define FT_GET_BYTE() FT_GET_MACRO( FT_Stream_GetChar, FT_Byte )
|
||||
#define FT_GET_SHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_Short )
|
||||
#define FT_GET_USHORT() FT_GET_MACRO( FT_Stream_GetUShort, FT_UShort )
|
||||
#define FT_GET_OFF3() FT_GET_MACRO( FT_Stream_GetUOffset, FT_Long )
|
||||
#define FT_GET_UOFF3() FT_GET_MACRO( FT_Stream_GetUOffset, FT_ULong )
|
||||
#define FT_GET_LONG() FT_GET_MACRO( FT_Stream_GetULong, FT_Long )
|
||||
#define FT_GET_ULONG() FT_GET_MACRO( FT_Stream_GetULong, FT_ULong )
|
||||
#define FT_GET_TAG4() FT_GET_MACRO( FT_Stream_GetULong, FT_ULong )
|
||||
|
||||
#define FT_GET_SHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_Short )
|
||||
#define FT_GET_USHORT_LE() FT_GET_MACRO( FT_Stream_GetUShortLE, FT_UShort )
|
||||
#define FT_GET_LONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_Long )
|
||||
#define FT_GET_ULONG_LE() FT_GET_MACRO( FT_Stream_GetULongLE, FT_ULong )
|
||||
#endif
|
||||
|
||||
#define FT_READ_MACRO( func, type, var ) \
|
||||
@ -418,10 +403,6 @@ FT_BEGIN_HEADER
|
||||
FT_BASE( FT_UShort )
|
||||
FT_Stream_GetUShort( FT_Stream stream );
|
||||
|
||||
/* read a 24-bit big-endian unsigned integer from an entered frame */
|
||||
FT_BASE( FT_ULong )
|
||||
FT_Stream_GetUOffset( FT_Stream stream );
|
||||
|
||||
/* read a 32-bit big-endian unsigned integer from an entered frame */
|
||||
FT_BASE( FT_ULong )
|
||||
FT_Stream_GetULong( FT_Stream stream );
|
||||
@ -430,10 +411,6 @@ FT_BEGIN_HEADER
|
||||
FT_BASE( FT_UShort )
|
||||
FT_Stream_GetUShortLE( FT_Stream stream );
|
||||
|
||||
/* read a 32-bit little-endian unsigned integer from an entered frame */
|
||||
FT_BASE( FT_ULong )
|
||||
FT_Stream_GetULongLE( FT_Stream stream );
|
||||
|
||||
|
||||
/* read a byte from a stream */
|
||||
FT_BASE( FT_Char )
|
||||
|
Loading…
x
Reference in New Issue
Block a user