mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -04:00
yet more c90 rewrite
This commit is contained in:
parent
514174f2bf
commit
feaf213fa2
@ -23,7 +23,8 @@ void GZipHeader_Init(struct GZipHeader* header) {
|
||||
}
|
||||
|
||||
ReturnCode GZipHeader_Read(struct Stream* s, struct GZipHeader* header) {
|
||||
ReturnCode res; uint8_t tmp;
|
||||
uint8_t tmp;
|
||||
ReturnCode res;
|
||||
switch (header->State) {
|
||||
|
||||
case GZIP_STATE_HEADER1:
|
||||
@ -104,7 +105,8 @@ void ZLibHeader_Init(struct ZLibHeader* header) {
|
||||
}
|
||||
|
||||
ReturnCode ZLibHeader_Read(struct Stream* s, struct ZLibHeader* header) {
|
||||
ReturnCode res; uint8_t tmp;
|
||||
uint8_t tmp;
|
||||
ReturnCode res;
|
||||
switch (header->State) {
|
||||
|
||||
case ZLIB_STATE_COMPRESSIONMETHOD:
|
||||
@ -196,7 +198,8 @@ static void Huffman_Build(struct HuffmanTable* table, uint8_t* bitLens, int coun
|
||||
offset += bl_count[i];
|
||||
|
||||
/* Last codeword is actually: code + (bl_count[i] - 1) */
|
||||
/* When decoding we peform < against this value though, so we need to add 1 here */
|
||||
/* When decoding we peform < against this value though, so need to add 1 here */
|
||||
/* This way, don't need to special case bit lengths with 0 codewords when decoding */
|
||||
if (bl_count[i]) {
|
||||
table->EndCodewords[i] = code + bl_count[i];
|
||||
} else {
|
||||
@ -306,7 +309,7 @@ void Inflate_Init(struct InflateState* state, struct Stream* source) {
|
||||
state->LastBlock = false;
|
||||
state->Bits = 0;
|
||||
state->NumBits = 0;
|
||||
state->NextIn = state->Input;
|
||||
state->NextIn = state->Input;
|
||||
state->AvailIn = 0;
|
||||
state->Output = NULL;
|
||||
state->AvailOut = 0;
|
||||
@ -420,7 +423,7 @@ void Inflate_Process(struct InflateState* state) {
|
||||
} break;
|
||||
|
||||
case 1: { /* Fixed/static huffman compressed */
|
||||
Huffman_Build(&state->Table.Lits, fixed_lits, INFLATE_MAX_LITS);
|
||||
Huffman_Build(&state->Table.Lits, fixed_lits, INFLATE_MAX_LITS);
|
||||
Huffman_Build(&state->TableDists, fixed_dists, INFLATE_MAX_DISTS);
|
||||
state->State = Inflate_NextCompressState(state);
|
||||
} break;
|
||||
|
@ -75,8 +75,8 @@ NOINLINE_ void Inflate_MakeStream(struct Stream* stream, struct InflateState* st
|
||||
#define DEFLATE_HASH_SIZE 0x1000UL
|
||||
#define DEFLATE_HASH_MASK 0x0FFFUL
|
||||
struct DeflateState {
|
||||
uint32_t Bits; /* Holds bits across byte boundaries*/
|
||||
uint32_t NumBits; /* Number of bits in Bits buffer*/
|
||||
uint32_t Bits; /* Holds bits across byte boundaries */
|
||||
uint32_t NumBits; /* Number of bits in Bits buffer */
|
||||
uint32_t InputPosition;
|
||||
|
||||
uint8_t* NextOut; /* Pointer within Output buffer to next byte that can be written */
|
||||
|
@ -40,8 +40,9 @@ void Drawer2D_Make2DTexture(struct Texture* tex, Bitmap* bmp, Size2D used, int X
|
||||
|
||||
bool Drawer2D_ValidColCodeAt(const String* text, int i);
|
||||
bool Drawer2D_ValidColCode(char c);
|
||||
/* Whether text is empty or consists purely of valid colour codes. */
|
||||
bool Drawer2D_IsEmptyText(const String* text);
|
||||
/* Returns the last valid colour code in the given input, or \0 if no valid colour code was found. */
|
||||
/* Returns the last valid colour code in the given input, or \0 if not found. */
|
||||
char Drawer2D_LastCol(const String* text, int start);
|
||||
bool Drawer2D_IsWhiteCol(char c);
|
||||
|
||||
|
81
src/Entity.c
81
src/Entity.c
@ -528,6 +528,7 @@ static void Player_DrawName(struct Player* player) {
|
||||
struct Model* model = e->Model;
|
||||
Vector3 pos;
|
||||
float scale;
|
||||
VertexP3fT2fC4b vertices[4];
|
||||
|
||||
if (player->NameTex.X == PLAYER_NAME_EMPTY_TEX) return;
|
||||
if (!player->NameTex.ID) Player_MakeNameTexture(player);
|
||||
@ -548,7 +549,6 @@ static void Player_DrawName(struct Player* player) {
|
||||
size.X *= tempW * 0.2f; size.Y *= tempW * 0.2f;
|
||||
}
|
||||
|
||||
VertexP3fT2fC4b vertices[4];
|
||||
TextureRec rec = { 0.0f, 0.0f, player->NameTex.U2, player->NameTex.V2 };
|
||||
PackedCol col = PACKEDCOL_WHITE;
|
||||
Particle_DoRender(&size, &pos, &rec, col, vertices);
|
||||
@ -664,26 +664,27 @@ static void Player_ClearHat(Bitmap* bmp, uint8_t skinType) {
|
||||
}
|
||||
}
|
||||
|
||||
static void Player_EnsurePow2(struct Player* player, Bitmap* bmp) {
|
||||
int width = Math_NextPowOf2(bmp->Width);
|
||||
int height = Math_NextPowOf2(bmp->Height);
|
||||
static void Player_EnsurePow2(struct Player* p, Bitmap* bmp) {
|
||||
uint32_t stride;
|
||||
int width, height;
|
||||
Bitmap scaled;
|
||||
int y;
|
||||
|
||||
width = Math_NextPowOf2(bmp->Width);
|
||||
height = Math_NextPowOf2(bmp->Height);
|
||||
if (width == bmp->Width && height == bmp->Height) return;
|
||||
|
||||
Bitmap_Allocate(&scaled, width, height);
|
||||
int y;
|
||||
uint32_t stride = (uint32_t)(bmp->Width) * BITMAP_SIZEOF_PIXEL;
|
||||
p->Base.uScale = (float)bmp->Width / width;
|
||||
p->Base.vScale = (float)bmp->Height / height;
|
||||
stride = bmp->Width * BITMAP_SIZEOF_PIXEL;
|
||||
|
||||
for (y = 0; y < bmp->Height; y++) {
|
||||
uint32_t* src = Bitmap_GetRow(bmp, y);
|
||||
uint32_t* dst = Bitmap_GetRow(&scaled, y);
|
||||
Mem_Copy(dst, src, stride);
|
||||
}
|
||||
|
||||
struct Entity* entity = &player->Base;
|
||||
entity->uScale = (float)bmp->Width / width;
|
||||
entity->vScale = (float)bmp->Height / height;
|
||||
|
||||
Mem_Free(bmp->Scan0);
|
||||
*bmp = scaled;
|
||||
}
|
||||
@ -831,16 +832,18 @@ static void LocalPlayer_SetLocation(struct Entity* e, struct LocationUpdate* upd
|
||||
}
|
||||
|
||||
void LocalPlayer_Tick(struct Entity* e, double delta) {
|
||||
if (!World_Blocks) return;
|
||||
struct LocalPlayer* p = (struct LocalPlayer*)e;
|
||||
struct HacksComp* hacks = &p->Hacks;
|
||||
|
||||
e->StepSize = hacks->FullBlockStep && hacks->Enabled && hacks->CanAnyHacks && hacks->CanSpeed ? 1.0f : 0.5f;
|
||||
p->OldVelocity = e->Velocity;
|
||||
float xMoving = 0, zMoving = 0;
|
||||
LocalInterpComp_AdvanceState(&p->Interp);
|
||||
bool wasOnGround = e->OnGround;
|
||||
bool wasOnGround;
|
||||
Vector3 headingVelocity;
|
||||
|
||||
if (!World_Blocks) return;
|
||||
e->StepSize = hacks->FullBlockStep && hacks->Enabled && hacks->CanAnyHacks && hacks->CanSpeed ? 1.0f : 0.5f;
|
||||
p->OldVelocity = e->Velocity;
|
||||
wasOnGround = e->OnGround;
|
||||
|
||||
LocalInterpComp_AdvanceState(&p->Interp);
|
||||
LocalPlayer_HandleInput(&xMoving, &zMoving);
|
||||
hacks->Floating = hacks->Noclip || hacks->Flying;
|
||||
if (!hacks->Floating && hacks->CanBePushed) PhysicsComp_DoEntityPush(e);
|
||||
@ -851,7 +854,7 @@ void LocalPlayer_Tick(struct Entity* e, double delta) {
|
||||
}
|
||||
|
||||
PhysicsComp_UpdateVelocityState(&p->Physics);
|
||||
Vector3 headingVelocity = Vector3_RotateY3(xMoving, 0, zMoving, e->HeadY * MATH_DEG2RAD);
|
||||
headingVelocity = Vector3_RotateY3(xMoving, 0, zMoving, e->HeadY * MATH_DEG2RAD);
|
||||
PhysicsComp_PhysicsTick(&p->Physics, headingVelocity);
|
||||
|
||||
/* Fixes high jump, when holding down a movement key, jump, fly, then let go of fly key */
|
||||
@ -861,7 +864,7 @@ void LocalPlayer_Tick(struct Entity* e, double delta) {
|
||||
AnimatedComp_Update(e, p->Interp.Prev.Pos, p->Interp.Next.Pos, delta);
|
||||
TiltComp_Update(&p->Tilt, delta);
|
||||
|
||||
Player_CheckSkin((struct Player*)p);
|
||||
Player_CheckSkin(&p->Base);
|
||||
SoundComp_Tick(wasOnGround);
|
||||
}
|
||||
|
||||
@ -928,7 +931,7 @@ struct EntityVTABLE localPlayer_VTABLE = {
|
||||
void LocalPlayer_Init(void) {
|
||||
struct LocalPlayer* p = &LocalPlayer_Instance;
|
||||
Player_Init(&p->Base);
|
||||
Player_SetName((struct Player*)p, &Game_Username, &Game_Username);
|
||||
Player_SetName(&p->Base, &Game_Username, &Game_Username);
|
||||
|
||||
p->Collisions.Entity = &p->Base;
|
||||
HacksComp_Init(&p->Hacks);
|
||||
@ -944,22 +947,26 @@ void LocalPlayer_Init(void) {
|
||||
static bool LocalPlayer_IsSolidCollide(BlockID b) { return Block_Collide[b] == COLLIDE_SOLID; }
|
||||
static void LocalPlayer_DoRespawn(void) {
|
||||
struct LocalPlayer* p = &LocalPlayer_Instance;
|
||||
Vector3 spawn = p->Spawn;
|
||||
Vector3I P;
|
||||
struct LocationUpdate update;
|
||||
struct AABB bb;
|
||||
Vector3 spawn = p->Spawn;
|
||||
Vector3I pos;
|
||||
BlockID block;
|
||||
float height, spawnY;
|
||||
int y;
|
||||
|
||||
if (!World_Blocks) return;
|
||||
Vector3I_Floor(&P, &spawn);
|
||||
Vector3I_Floor(&pos, &spawn);
|
||||
|
||||
/* Spawn player at highest valid position */
|
||||
if (World_IsValidPos_3I(P)) {
|
||||
if (World_IsValidPos_3I(pos)) {
|
||||
AABB_Make(&bb, &spawn, &p->Base.Size);
|
||||
int y;
|
||||
for (y = P.Y; y <= World_Height; y++) {
|
||||
float spawnY = Respawn_HighestFreeY(&bb);
|
||||
for (y = pos.Y; y <= World_Height; y++) {
|
||||
spawnY = Respawn_HighestFreeY(&bb);
|
||||
|
||||
if (spawnY == RESPAWN_NOT_FOUND) {
|
||||
BlockID block = World_GetPhysicsBlock(P.X, y, P.Z);
|
||||
float height = Block_Collide[block] == COLLIDE_SOLID ? Block_MaxBB[block].Y : 0.0f;
|
||||
block = World_GetPhysicsBlock(pos.X, y, pos.Z);
|
||||
height = Block_Collide[block] == COLLIDE_SOLID ? Block_MaxBB[block].Y : 0.0f;
|
||||
spawn.Y = y + height + ENTITY_ADJUSTMENT;
|
||||
break;
|
||||
}
|
||||
@ -967,8 +974,8 @@ static void LocalPlayer_DoRespawn(void) {
|
||||
}
|
||||
}
|
||||
|
||||
spawn.Y += 2.0f / 16.0f;
|
||||
struct LocationUpdate update; LocationUpdate_MakePosAndOri(&update, spawn, p->SpawnRotY, p->SpawnHeadX, false);
|
||||
spawn.Y += 2.0f/16.0f;
|
||||
LocationUpdate_MakePosAndOri(&update, spawn, p->SpawnRotY, p->SpawnHeadX, false);
|
||||
p->Base.VTABLE->SetLocation(&p->Base, &update, false);
|
||||
p->Base.Velocity = Vector3_Zero;
|
||||
|
||||
@ -1063,7 +1070,7 @@ static void NetPlayer_SetLocation(struct Entity* e, struct LocationUpdate* updat
|
||||
|
||||
static void NetPlayer_Tick(struct Entity* e, double delta) {
|
||||
struct NetPlayer* p = (struct NetPlayer*)e;
|
||||
Player_CheckSkin((struct Player*)p);
|
||||
Player_CheckSkin(&p->Base);
|
||||
NetInterpComp_AdvanceState(&p->Interp);
|
||||
AnimatedComp_Update(e, p->Interp.Prev.Pos, p->Interp.Next.Pos, delta);
|
||||
}
|
||||
@ -1086,16 +1093,16 @@ static void NetPlayer_RenderName(struct Entity* e) {
|
||||
|
||||
distance = Model_RenderDistance(e);
|
||||
threshold = Entities_NameMode == NAME_MODE_ALL_UNSCALED ? 8192 * 8192 : 32 * 32;
|
||||
if (distance <= (float)threshold) Player_DrawName((struct Player*)p);
|
||||
if (distance <= (float)threshold) Player_DrawName(&p->Base);
|
||||
}
|
||||
|
||||
struct EntityVTABLE netPlayer_VTABLE = {
|
||||
NetPlayer_Tick, Player_Despawn, NetPlayer_SetLocation, Entity_GetCol,
|
||||
NetPlayer_RenderModel, NetPlayer_RenderName, Player_ContextLost, Player_ContextRecreated,
|
||||
};
|
||||
void NetPlayer_Init(struct NetPlayer* player, const String* displayName, const String* skinName) {
|
||||
Mem_Set(player, 0, sizeof(struct NetPlayer));
|
||||
Player_Init(&player->Base);
|
||||
Player_SetName((struct Player*)player, displayName, skinName);
|
||||
player->Base.VTABLE = &netPlayer_VTABLE;
|
||||
void NetPlayer_Init(struct NetPlayer* p, const String* displayName, const String* skinName) {
|
||||
Mem_Set(p, 0, sizeof(struct NetPlayer));
|
||||
Player_Init(&p->Base);
|
||||
Player_SetName(&p->Base, displayName, skinName);
|
||||
p->Base.VTABLE = &netPlayer_VTABLE;
|
||||
}
|
||||
|
@ -166,8 +166,7 @@ void HacksComp_Init(struct HacksComp* hacks) {
|
||||
hacks->NoclipSlide = true;
|
||||
hacks->CanBePushed = true;
|
||||
|
||||
String str = String_FromArray(hacks->__HacksFlagsBuffer);
|
||||
hacks->HacksFlags = str;
|
||||
String_InitArray(hacks->HacksFlags, hacks->__HacksFlagsBuffer);
|
||||
}
|
||||
|
||||
bool HacksComp_CanJumpHigher(struct HacksComp* hacks) {
|
||||
|
@ -485,14 +485,21 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
|
||||
X11Button ok = { 0 };
|
||||
X11Textbox body = { 0 };
|
||||
|
||||
XFontStruct* font;
|
||||
Atom wmDelete;
|
||||
int x, y, width, height;
|
||||
XSizeHints hints = { 0 };
|
||||
int mouseX = -1, mouseY = -1, over;
|
||||
XEvent e;
|
||||
|
||||
X11Window_Init(w);
|
||||
XMapWindow(dpy, w->win);
|
||||
XStoreName(dpy, w->win, title);
|
||||
|
||||
Atom wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
||||
wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
||||
XSetWMProtocols(dpy, w->win, &wmDelete, 1);
|
||||
|
||||
XFontStruct* font = XQueryFont(dpy, XGContextFromGC(w->gc));
|
||||
font = XQueryFont(dpy, XGContextFromGC(w->gc));
|
||||
if (!font) return;
|
||||
|
||||
/* Compute size of widgets */
|
||||
@ -504,10 +511,10 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
|
||||
ok.Height = ok.Text.Height + 10;
|
||||
|
||||
/* Compute size and position of window */
|
||||
int width = body.Width + 20;
|
||||
int height = body.Height + 20 + ok.Height + 20;
|
||||
int x = DisplayWidth (dpy, DefaultScreen(dpy))/2 - width/2;
|
||||
int y = DisplayHeight(dpy, DefaultScreen(dpy))/2 - height/2;
|
||||
width = body.Width + 20;
|
||||
height = body.Height + 20 + ok.Height + 20;
|
||||
x = DisplayWidth (dpy, DefaultScreen(dpy))/2 - width/2;
|
||||
y = DisplayHeight(dpy, DefaultScreen(dpy))/2 - height/2;
|
||||
XMoveResizeWindow(dpy, w->win, x, y, width, height);
|
||||
|
||||
/* Adjust bounds of widgets */
|
||||
@ -518,7 +525,6 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
|
||||
XFreeFontInfo(NULL, font, 1);
|
||||
XUnmapWindow(dpy, w->win); /* Make window non resizeable */
|
||||
|
||||
XSizeHints hints = { 0 };
|
||||
hints.flags = PSize | PMinSize | PMaxSize;
|
||||
hints.min_width = hints.max_width = hints.base_width = width;
|
||||
hints.min_height = hints.max_height = hints.base_height = height;
|
||||
@ -527,9 +533,6 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
|
||||
XMapRaised(dpy, w->win);
|
||||
XFlush(dpy);
|
||||
|
||||
XEvent e;
|
||||
int mouseX = -1, mouseY = -1;
|
||||
|
||||
for (;;) {
|
||||
XNextEvent(dpy, &e);
|
||||
|
||||
@ -538,7 +541,7 @@ static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
if (e.xbutton.button != Button1) break;
|
||||
int over = X11Button_Contains(&ok, mouseX, mouseY);
|
||||
over = X11Button_Contains(&ok, mouseX, mouseY);
|
||||
|
||||
if (ok.Clicked && e.type == ButtonRelease) {
|
||||
if (over) return;
|
||||
|
@ -305,9 +305,10 @@ static ReturnCode Nbt_ReadTag(uint8_t typeId, bool readTagName, struct Stream* s
|
||||
uint32_t i, count;
|
||||
|
||||
if (typeId == NBT_END) return 0;
|
||||
tag.TagID = typeId; tag.Parent = parent;
|
||||
tag.Name = String_Init(tag.NameBuffer, 0, NBT_STRING_SIZE);
|
||||
tag.TagID = typeId;
|
||||
tag.Parent = parent;
|
||||
tag.DataSize = 0;
|
||||
String_InitArray(tag.Name, tag.NameBuffer);
|
||||
|
||||
if (readTagName) {
|
||||
res = Nbt_ReadString(stream, &tag.Name);
|
||||
@ -343,7 +344,7 @@ static ReturnCode Nbt_ReadTag(uint8_t typeId, bool readTagName, struct Stream* s
|
||||
}
|
||||
break;
|
||||
case NBT_STR:
|
||||
tag.Value.Str.Text = String_Init(tag.Value.Str.Buffer, 0, NBT_STRING_SIZE);
|
||||
String_InitArray(tag.Value.Str.Text, tag.Value.Str.Buffer);
|
||||
res = Nbt_ReadString(stream, &tag.Value.Str.Text);
|
||||
break;
|
||||
|
||||
|
21
src/Menus.c
21
src/Menus.c
@ -1267,9 +1267,7 @@ static void SaveLevelScreen_Schematic(void* a, void* b) { SaveLevelScreen_Save(a
|
||||
|
||||
static void SaveLevelScreen_Init(void* screen) {
|
||||
struct SaveLevelScreen* s = screen;
|
||||
String str = String_FromArray(s->__TextPathBuffer);
|
||||
s->TextPath = str;
|
||||
|
||||
String_InitArray(s->TextPath, s->__TextPathBuffer);
|
||||
Key_KeyRepeat = true;
|
||||
MenuScreen_Init(s);
|
||||
}
|
||||
@ -3158,9 +3156,8 @@ struct Screen* UrlWarningOverlay_MakeInstance(const String* url) {
|
||||
s->Widgets = widgets;
|
||||
s->WidgetsCount = Array_Elems(widgets);
|
||||
|
||||
String dstUrl = String_FromArray(s->__UrlBuffer);
|
||||
String_Copy(&dstUrl, url);
|
||||
s->Url = dstUrl;
|
||||
String_InitArray(s->Url, s->__UrlBuffer);
|
||||
String_Copy(&s->Url, url);
|
||||
|
||||
s->VTABLE = &UrlWarningOverlay_VTABLE;
|
||||
return (struct Screen*)s;
|
||||
@ -3225,9 +3222,8 @@ struct Screen* ConfirmDenyOverlay_MakeInstance(const String* url, bool alwaysDen
|
||||
s->Widgets = widgets;
|
||||
s->WidgetsCount = Array_Elems(widgets);
|
||||
|
||||
String dstUrl = String_FromArray(s->__UrlBuffer);
|
||||
String_Copy(&dstUrl, url);
|
||||
s->Url = dstUrl;
|
||||
String_InitArray(s->Url, s->__UrlBuffer);
|
||||
String_Copy(&s->Url, url);
|
||||
s->AlwaysDeny = alwaysDeny;
|
||||
|
||||
s->VTABLE = &ConfirmDenyOverlay_VTABLE;
|
||||
@ -3337,12 +3333,11 @@ struct Screen* TexPackOverlay_MakeInstance(const String* url) {
|
||||
s->Widgets = widgets;
|
||||
s->WidgetsCount = Array_Elems(widgets);
|
||||
|
||||
String identifier = String_FromArray(s->__IdentifierBuffer);
|
||||
String_Format1(&identifier, "CL_%s", url);
|
||||
s->Identifier = identifier;
|
||||
String_InitArray(s->Identifier, s->__IdentifierBuffer);
|
||||
String_Format1(&s->Identifier, "CL_%s", url);
|
||||
s->ContentLength = 0;
|
||||
|
||||
AsyncDownloader_GetContentLength(url, true, &identifier);
|
||||
AsyncDownloader_GetContentLength(url, true, &s->Identifier);
|
||||
s->VTABLE = &TexPackOverlay_VTABLE;
|
||||
return (struct Screen*)s;
|
||||
}
|
||||
|
20
src/Model.c
20
src/Model.c
@ -113,10 +113,14 @@ void Model_Render(struct Model* model, struct Entity* entity) {
|
||||
}
|
||||
|
||||
void Model_SetupState(struct Model* model, struct Entity* entity) {
|
||||
model->index = 0;
|
||||
PackedCol col = entity->VTABLE->GetCol(entity);
|
||||
PackedCol col;
|
||||
bool _64x64;
|
||||
float yawDelta;
|
||||
|
||||
bool _64x64 = entity->SkinType != SKIN_64x32;
|
||||
model->index = 0;
|
||||
col = entity->VTABLE->GetCol(entity);
|
||||
|
||||
_64x64 = entity->SkinType != SKIN_64x32;
|
||||
/* only apply when using humanoid skins */
|
||||
_64x64 &= model->UsesHumanSkin || entity->MobTextureId;
|
||||
|
||||
@ -131,10 +135,11 @@ void Model_SetupState(struct Model* model, struct Entity* entity) {
|
||||
} else {
|
||||
Model_Cols[1] = col; Model_Cols[2] = col; Model_Cols[4] = col;
|
||||
}
|
||||
|
||||
Model_Cols[3] = Model_Cols[2];
|
||||
Model_Cols[5] = Model_Cols[4];
|
||||
yawDelta = entity->HeadY - entity->RotY;
|
||||
|
||||
float yawDelta = entity->HeadY - entity->RotY;
|
||||
Model_cosHead = (float)Math_Cos(yawDelta * MATH_DEG2RAD);
|
||||
Model_sinHead = (float)Math_Sin(yawDelta * MATH_DEG2RAD);
|
||||
Model_ActiveModel = model;
|
||||
@ -148,9 +153,11 @@ void Model_UpdateVB(void) {
|
||||
|
||||
void Model_ApplyTexture(struct Entity* entity) {
|
||||
struct Model* model = Model_ActiveModel;
|
||||
GfxResourceID tex = model->UsesHumanSkin ? entity->TextureId : entity->MobTextureId;
|
||||
struct CachedTexture* data;
|
||||
GfxResourceID tex;
|
||||
bool _64x64;
|
||||
|
||||
tex = model->UsesHumanSkin ? entity->TextureId : entity->MobTextureId;
|
||||
if (tex) {
|
||||
Model_skinType = entity->SkinType;
|
||||
} else {
|
||||
@ -160,7 +167,8 @@ void Model_ApplyTexture(struct Entity* entity) {
|
||||
}
|
||||
|
||||
Gfx_BindTexture(tex);
|
||||
bool _64x64 = Model_skinType != SKIN_64x32;
|
||||
_64x64 = Model_skinType != SKIN_64x32;
|
||||
|
||||
Model_uScale = entity->uScale * 0.015625f;
|
||||
Model_vScale = entity->vScale * (_64x64 ? 0.015625f : 0.03125f);
|
||||
}
|
||||
|
@ -597,13 +597,10 @@ struct Screen* LoadingScreen_MakeInstance(const String* title, const String* mes
|
||||
s->VTABLE = &LoadingScreen_VTABLE;
|
||||
s->Progress = 0.0f;
|
||||
|
||||
String title_copy = String_FromArray(s->__TitleBuffer);
|
||||
String_AppendString(&title_copy, title);
|
||||
s->TitleStr = title_copy;
|
||||
|
||||
String message_copy = String_FromArray(s->__MessageBuffer);
|
||||
String_AppendString(&message_copy, message);
|
||||
s->MessageStr = message_copy;
|
||||
String_InitArray(s->TitleStr, s->__TitleBuffer);
|
||||
String_AppendString(&s->TitleStr, title);
|
||||
String_InitArray(s->MessageStr, s->__MessageBuffer);
|
||||
String_AppendString(&s->MessageStr, message);
|
||||
|
||||
s->HandlesAllInput = true;
|
||||
s->BlocksWorld = true;
|
||||
@ -1540,13 +1537,10 @@ struct Screen* DisconnectScreen_MakeInstance(const String* title, const String*
|
||||
s->BlocksWorld = true;
|
||||
s->HidesHUD = true;
|
||||
|
||||
String title_copy = String_FromArray(s->__TitleBuffer);
|
||||
String_AppendString(&title_copy, title);
|
||||
s->TitleStr = title_copy;
|
||||
|
||||
String message_copy = String_FromArray(s->__MessageBuffer);
|
||||
String_AppendString(&message_copy, message);
|
||||
s->MessageStr = message_copy;
|
||||
String_InitArray(s->TitleStr, s->__TitleBuffer);
|
||||
String_AppendString(&s->TitleStr, title);
|
||||
String_InitArray(s->MessageStr, s->__MessageBuffer);
|
||||
String_AppendString(&s->MessageStr, message);
|
||||
|
||||
char whyBuffer[STRING_SIZE];
|
||||
String why = String_FromArray(whyBuffer);
|
||||
|
@ -45,6 +45,8 @@ NOINLINE_ String String_FromReadonly(STRING_REF const char* buffer);
|
||||
#define String_FromRawArray(buffer) String_FromRaw(buffer, sizeof(buffer))
|
||||
/* Constructs a string from a compile time array (leaving 1 byte of room for null terminator) */
|
||||
#define String_NT_Array(buffer) { buffer, 0, (sizeof(buffer) - 1)}
|
||||
/* Initialises a string from a compile time array. */
|
||||
#define String_InitArray(str, buffr) str.buffer = buffr; str.length = 0; str.capacity = sizeof(buffr);
|
||||
|
||||
/* Removes all colour codes from the given string. */
|
||||
NOINLINE_ void String_StripCols(String* str);
|
||||
|
@ -204,7 +204,8 @@ static void EntryList_Load(struct EntryList* list) {
|
||||
char lineBuffer[FILENAME_SIZE];
|
||||
String line = String_FromArray(lineBuffer);
|
||||
|
||||
struct Stream stream;
|
||||
uint8_t buffer[2048];
|
||||
struct Stream stream, buffered;
|
||||
ReturnCode res;
|
||||
String_Format3(&path, "%c%r%c", list->Folder, &Directory_Separator, list->Filename);
|
||||
|
||||
@ -213,7 +214,6 @@ static void EntryList_Load(struct EntryList* list) {
|
||||
if (res) { Chat_LogError2(res, "opening", &path); return; }
|
||||
|
||||
/* ReadLine reads single byte at a time */
|
||||
uint8_t buffer[2048]; struct Stream buffered;
|
||||
Stream_ReadonlyBuffered(&buffered, &stream, buffer, sizeof(buffer));
|
||||
|
||||
for (;;) {
|
||||
|
@ -52,7 +52,7 @@ bool TextureCache_Has(const String* url);
|
||||
/* Attempts to get the cached data stream for the given url. */
|
||||
bool TextureCache_Get(const String* url, struct Stream* stream);
|
||||
/* Attempts to get the Last-Modified header cached for the given URL. */
|
||||
/* If header is not found, returns last time the cached datastream was modified. */
|
||||
/* If header is not found, returns last time the cached data was modified. */
|
||||
void TextureCache_GetLastModified(const String* url, TimeMS* time);
|
||||
/* Attempts to get the ETag header cached for the given URL. */
|
||||
void TextureCache_GetETag(const String* url, String* etag);
|
||||
|
279
src/Widgets.c
279
src/Widgets.c
@ -117,7 +117,10 @@ static void ButtonWidget_Reposition(void* widget) {
|
||||
|
||||
static void ButtonWidget_Render(void* widget, double delta) {
|
||||
struct ButtonWidget* w = widget;
|
||||
struct Texture back = w->Active ? Button_SelectedTex : Button_ShadowTex;
|
||||
struct Texture back;
|
||||
PackedCol col;
|
||||
|
||||
back = w->Active ? Button_SelectedTex : Button_ShadowTex;
|
||||
if (w->Disabled) back = Button_DisabledTex;
|
||||
|
||||
back.ID = Game_UseClassicGui ? Gui_GuiClassicTex : Gui_GuiTex;
|
||||
@ -147,7 +150,7 @@ static void ButtonWidget_Render(void* widget, double delta) {
|
||||
PackedCol disabledCol = PACKEDCOL_CONST(160, 160, 160, 255);
|
||||
|
||||
if (!w->Texture.ID) return;
|
||||
PackedCol col = w->Disabled ? disabledCol : (w->Active ? activeCol : normCol);
|
||||
col = w->Disabled ? disabledCol : (w->Active ? activeCol : normCol);
|
||||
Texture_RenderShaded(&w->Texture, col);
|
||||
}
|
||||
|
||||
@ -503,13 +506,13 @@ static int Table_Height(struct TableWidget* w) {
|
||||
|
||||
#define TABLE_MAX_VERTICES (8 * 10 * ISOMETRICDRAWER_MAXVERTICES)
|
||||
|
||||
static bool TableWidget_GetCoords(struct TableWidget* w, int i, int* winX, int* winY) {
|
||||
int x = i % w->ElementsPerRow, y = i / w->ElementsPerRow;
|
||||
*winX = w->X + w->BlockSize * x;
|
||||
*winY = w->Y + w->BlockSize * y + 3;
|
||||
static bool TableWidget_GetCoords(struct TableWidget* w, int i, int* cellX, int* cellY) {
|
||||
int x, y;
|
||||
x = i % w->ElementsPerRow;
|
||||
y = i / w->ElementsPerRow - w->Scroll.ScrollY;
|
||||
|
||||
*winY -= w->Scroll.ScrollY * w->BlockSize;
|
||||
y -= w->Scroll.ScrollY;
|
||||
*cellX = w->X + w->BlockSize * x;
|
||||
*cellY = w->Y + w->BlockSize * y + 3;
|
||||
return y >= 0 && y < TABLE_MAX_ROWS_DISPLAYED;
|
||||
}
|
||||
|
||||
@ -536,8 +539,10 @@ static void TableWidget_MoveCursorToSelected(struct TableWidget* w) {
|
||||
}
|
||||
|
||||
static void TableWidget_MakeBlockDesc(String* desc, BlockID block) {
|
||||
String name;
|
||||
if (Game_PureClassic) { String_AppendConst(desc, "Select block"); return; }
|
||||
String name = Block_UNSAFE_GetName(block);
|
||||
|
||||
name = Block_UNSAFE_GetName(block);
|
||||
String_AppendString(desc, &name);
|
||||
if (Game_ClassicMode) return;
|
||||
|
||||
@ -574,9 +579,9 @@ static void TableWidget_RecreateDescTex(struct TableWidget* w) {
|
||||
}
|
||||
|
||||
void TableWidget_MakeDescTex(struct TableWidget* w, BlockID block) {
|
||||
struct DrawTextArgs args;
|
||||
char descBuffer[STRING_SIZE * 2];
|
||||
String desc = String_FromArray(descBuffer);
|
||||
struct DrawTextArgs args;
|
||||
|
||||
Gfx_DeleteTexture(&w->DescTex.ID);
|
||||
if (block == BLOCK_AIR) return;
|
||||
@ -627,6 +632,9 @@ static void TableWidget_Init(void* widget) {
|
||||
|
||||
static void TableWidget_Render(void* widget, double delta) {
|
||||
struct TableWidget* w = widget;
|
||||
VertexP3fT2fC4b vertices[TABLE_MAX_VERTICES];
|
||||
int i, x, y;
|
||||
|
||||
/* These were sourced by taking a screenshot of vanilla
|
||||
Then using paint to extract the colour components
|
||||
Then using wolfram alpha to solve the glblendfunc equation */
|
||||
@ -644,8 +652,8 @@ static void TableWidget_Render(void* widget, double delta) {
|
||||
|
||||
int blockSize = w->BlockSize;
|
||||
if (w->SelectedIndex != -1 && Game_ClassicMode) {
|
||||
int x, y;
|
||||
TableWidget_GetCoords(w, w->SelectedIndex, &x, &y);
|
||||
|
||||
float off = blockSize * 0.1f;
|
||||
int size = (int)(blockSize + off * 2);
|
||||
GfxCommon_Draw2DGradient((int)(x - off), (int)(y - off),
|
||||
@ -654,11 +662,8 @@ static void TableWidget_Render(void* widget, double delta) {
|
||||
Gfx_SetTexturing(true);
|
||||
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B);
|
||||
|
||||
VertexP3fT2fC4b vertices[TABLE_MAX_VERTICES];
|
||||
IsometricDrawer_BeginBatch(vertices, w->VB);
|
||||
int i;
|
||||
for (i = 0; i < w->ElementsCount; i++) {
|
||||
int x, y;
|
||||
if (!TableWidget_GetCoords(w, i, &x, &y)) continue;
|
||||
|
||||
/* We want to always draw the selected block on top of others */
|
||||
@ -669,8 +674,8 @@ static void TableWidget_Render(void* widget, double delta) {
|
||||
|
||||
i = w->SelectedIndex;
|
||||
if (i != -1) {
|
||||
int x, y;
|
||||
TableWidget_GetCoords(w, i, &x, &y);
|
||||
|
||||
IsometricDrawer_DrawBatch(w->Elements[i],
|
||||
(blockSize + w->SelBlockExpand) * 0.7f / 2.0f,
|
||||
x + blockSize / 2, y + blockSize / 2);
|
||||
@ -872,13 +877,13 @@ static void InputWidget_FormatLine(struct InputWidget* w, int i, String* line) {
|
||||
}
|
||||
|
||||
static void InputWidget_CalculateLineSizes(struct InputWidget* w) {
|
||||
char lineBuffer[STRING_SIZE];
|
||||
String line = String_FromArray(lineBuffer);
|
||||
|
||||
struct DrawTextArgs args;
|
||||
Size2D size;
|
||||
int y;
|
||||
|
||||
char lineBuffer[STRING_SIZE];
|
||||
String line = String_FromArray(lineBuffer);
|
||||
|
||||
for (y = 0; y < INPUTWIDGET_MAX_LINES; y++) {
|
||||
w->LineSizes[y] = Size2D_Empty;
|
||||
}
|
||||
@ -1042,14 +1047,16 @@ static bool InputWidget_CheckCol(struct InputWidget* w, int index) {
|
||||
}
|
||||
|
||||
static void InputWidget_BackspaceKey(struct InputWidget* w) {
|
||||
int i, len;
|
||||
|
||||
if (InputWidget_ControlDown()) {
|
||||
if (w->CaretPos == -1) { w->CaretPos = w->Text.length - 1; }
|
||||
int len = WordWrap_GetBackLength(&w->Text, w->CaretPos);
|
||||
len = WordWrap_GetBackLength(&w->Text, w->CaretPos);
|
||||
if (!len) return;
|
||||
|
||||
w->CaretPos -= len;
|
||||
if (w->CaretPos < 0) { w->CaretPos = 0; }
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= len; i++) {
|
||||
String_DeleteAt(&w->Text, w->CaretPos);
|
||||
}
|
||||
@ -1214,10 +1221,12 @@ static bool InputWidget_KeyPress(void* widget, char keyChar) {
|
||||
|
||||
static bool InputWidget_MouseDown(void* widget, int x, int y, MouseButton button) {
|
||||
struct InputWidget* w = widget;
|
||||
struct DrawTextArgs args;
|
||||
|
||||
if (button != MouseButton_Left) return true;
|
||||
|
||||
x -= w->InputTex.X; y -= w->InputTex.Y;
|
||||
struct DrawTextArgs args; DrawTextArgs_MakeEmpty(&args, &w->Font, true);
|
||||
DrawTextArgs_MakeEmpty(&args, &w->Font, true);
|
||||
int offset = 0, charHeight = w->CaretTex.Height;
|
||||
|
||||
char lineBuffer[STRING_SIZE];
|
||||
@ -1399,7 +1408,7 @@ struct MenuInputValidator MenuInputValidator_Path(void) {
|
||||
|
||||
struct MenuInputValidator MenuInputValidator_Enum(const char** names, int namesCount) {
|
||||
struct MenuInputValidator v;
|
||||
v.VTABLE = NULL;
|
||||
v.VTABLE = NULL;
|
||||
v.Meta._Enum.Names = names;
|
||||
v.Meta._Enum.Count = namesCount;
|
||||
return v;
|
||||
@ -1444,14 +1453,18 @@ static void MenuInputWidget_Render(void* widget, double delta) {
|
||||
|
||||
static void MenuInputWidget_RemakeTexture(void* widget) {
|
||||
struct MenuInputWidget* w = widget;
|
||||
struct MenuInputValidator* v;
|
||||
struct DrawTextArgs args;
|
||||
Size2D size;
|
||||
Bitmap bmp;
|
||||
|
||||
DrawTextArgs_Make(&args, &w->Base.Lines[0], &w->Base.Font, false);
|
||||
Size2D size = Drawer2D_MeasureText(&args);
|
||||
size = Drawer2D_MeasureText(&args);
|
||||
w->Base.CaretAccumulator = 0.0;
|
||||
|
||||
char rangeBuffer[STRING_SIZE];
|
||||
String range = String_FromArray(rangeBuffer);
|
||||
struct MenuInputValidator* v = &w->Validator;
|
||||
v = &w->Validator;
|
||||
v->VTABLE->GetRange(v, &range);
|
||||
|
||||
/* Ensure we don't have 0 text height */
|
||||
@ -1465,7 +1478,7 @@ static void MenuInputWidget_RemakeTexture(void* widget) {
|
||||
w->Base.Height = max(size.Height, w->MinHeight);
|
||||
Size2D adjSize = size; adjSize.Width = w->Base.Width;
|
||||
|
||||
Bitmap bmp; Bitmap_AllocateClearedPow2(&bmp, adjSize.Width, adjSize.Height);
|
||||
Bitmap_AllocateClearedPow2(&bmp, adjSize.Width, adjSize.Height);
|
||||
{
|
||||
Drawer2D_DrawText(&bmp, &args, w->Base.Padding, 0);
|
||||
|
||||
@ -1491,13 +1504,14 @@ static void MenuInputWidget_RemakeTexture(void* widget) {
|
||||
static bool MenuInputWidget_AllowedChar(void* widget, char c) {
|
||||
struct InputWidget* w = widget;
|
||||
struct MenuInputValidator* v;
|
||||
int maxChars;
|
||||
bool valid;
|
||||
|
||||
if (c == '&') return false;
|
||||
v = &((struct MenuInputWidget*)w)->Validator;
|
||||
|
||||
if (!v->VTABLE->IsValidChar(v, c)) return false;
|
||||
int maxChars = w->GetMaxLines() * INPUTWIDGET_LEN;
|
||||
maxChars = w->GetMaxLines() * INPUTWIDGET_LEN;
|
||||
if (w->Text.length == maxChars) return false;
|
||||
|
||||
/* See if the new string is in valid format */
|
||||
@ -1524,8 +1538,7 @@ void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, co
|
||||
|
||||
w->Base.ConvertPercents = false;
|
||||
w->Base.Padding = 3;
|
||||
String inputStr = String_FromArray(w->__TextBuffer);
|
||||
w->Base.Text = inputStr;
|
||||
String_InitArray(w->Base.Text, w->__TextBuffer);
|
||||
|
||||
w->Base.GetMaxLines = MenuInputWidget_GetMaxLines;
|
||||
w->Base.RemakeTexture = MenuInputWidget_RemakeTexture;
|
||||
@ -1541,19 +1554,21 @@ void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, co
|
||||
*#########################################################################################################################*/
|
||||
static void ChatInputWidget_RemakeTexture(void* widget) {
|
||||
struct InputWidget* w = widget;
|
||||
int totalHeight = 0, maxWidth = 0, i;
|
||||
struct DrawTextArgs args;
|
||||
Size2D size = { 0, 0 };
|
||||
Bitmap bmp;
|
||||
int i;
|
||||
w->CaretAccumulator = 0;
|
||||
|
||||
for (i = 0; i < w->GetMaxLines(); i++) {
|
||||
totalHeight += w->LineSizes[i].Height;
|
||||
maxWidth = max(maxWidth, w->LineSizes[i].Width);
|
||||
size.Height += w->LineSizes[i].Height;
|
||||
size.Width = max(size.Width, w->LineSizes[i].Width);
|
||||
}
|
||||
Size2D size = { maxWidth, totalHeight };
|
||||
|
||||
int realHeight = 0;
|
||||
Bitmap bmp; Bitmap_AllocateClearedPow2(&bmp, size.Width, size.Height);
|
||||
Bitmap_AllocateClearedPow2(&bmp, size.Width, size.Height);
|
||||
|
||||
struct DrawTextArgs args; DrawTextArgs_MakeEmpty(&args, &w->Font, true);
|
||||
DrawTextArgs_MakeEmpty(&args, &w->Font, true);
|
||||
if (w->Prefix.length) {
|
||||
args.Text = w->Prefix;
|
||||
Drawer2D_DrawText(&bmp, &args, 0, 0);
|
||||
@ -1566,7 +1581,7 @@ static void ChatInputWidget_RemakeTexture(void* widget) {
|
||||
if (!w->Lines[i].length) break;
|
||||
line.length = 0;
|
||||
|
||||
/* Colour code goes to next line */
|
||||
/* Colour code continues in next line */
|
||||
char lastCol = InputWidget_GetLastCol(w, 0, i);
|
||||
if (!Drawer2D_IsWhiteCol(lastCol)) {
|
||||
String_Append(&line, '&'); String_Append(&line, lastCol);
|
||||
@ -1632,8 +1647,11 @@ static void ChatInputWidget_OnPressedEnter(void* widget) {
|
||||
|
||||
static void ChatInputWidget_UpKey(struct InputWidget* w) {
|
||||
struct ChatInputWidget* W = (struct ChatInputWidget*)w;
|
||||
String prevInput;
|
||||
int pos;
|
||||
|
||||
if (InputWidget_ControlDown()) {
|
||||
int pos = w->CaretPos == -1 ? w->Text.length : w->CaretPos;
|
||||
pos = w->CaretPos == -1 ? w->Text.length : w->CaretPos;
|
||||
if (pos < INPUTWIDGET_LEN) return;
|
||||
|
||||
w->CaretPos = pos - INPUTWIDGET_LEN;
|
||||
@ -1650,7 +1668,7 @@ static void ChatInputWidget_UpKey(struct InputWidget* w) {
|
||||
w->Text.length = 0;
|
||||
|
||||
if (W->TypingLogPos < 0) W->TypingLogPos = 0;
|
||||
String prevInput = StringsBuffer_UNSAFE_Get(&Chat_InputLog, W->TypingLogPos);
|
||||
prevInput = StringsBuffer_UNSAFE_Get(&Chat_InputLog, W->TypingLogPos);
|
||||
String_AppendString(&w->Text, &prevInput);
|
||||
|
||||
w->CaretPos = -1;
|
||||
@ -1659,8 +1677,11 @@ static void ChatInputWidget_UpKey(struct InputWidget* w) {
|
||||
|
||||
static void ChatInputWidget_DownKey(struct InputWidget* w) {
|
||||
struct ChatInputWidget* W = (struct ChatInputWidget*)w;
|
||||
String prevInput;
|
||||
int lines;
|
||||
|
||||
if (InputWidget_ControlDown()) {
|
||||
int lines = w->GetMaxLines();
|
||||
lines = w->GetMaxLines();
|
||||
if (w->CaretPos == -1 || w->CaretPos >= (lines - 1) * INPUTWIDGET_LEN) return;
|
||||
|
||||
w->CaretPos += INPUTWIDGET_LEN;
|
||||
@ -1676,7 +1697,7 @@ static void ChatInputWidget_DownKey(struct InputWidget* w) {
|
||||
W->TypingLogPos = Chat_InputLog.Count;
|
||||
String_AppendString(&w->Text, &W->OrigStr);
|
||||
} else {
|
||||
String prevInput = StringsBuffer_UNSAFE_Get(&Chat_InputLog, W->TypingLogPos);
|
||||
prevInput = StringsBuffer_UNSAFE_Get(&Chat_InputLog, W->TypingLogPos);
|
||||
String_AppendString(&w->Text, &prevInput);
|
||||
}
|
||||
|
||||
@ -1690,18 +1711,18 @@ static bool ChatInputWidget_IsNameChar(char c) {
|
||||
}
|
||||
|
||||
static void ChatInputWidget_TabKey(struct InputWidget* w) {
|
||||
EntityID matches[TABLIST_MAX_NAMES];
|
||||
String part, match;
|
||||
int end = w->CaretPos == -1 ? w->Text.length - 1 : w->CaretPos;
|
||||
int start = end;
|
||||
int beg = end;
|
||||
char* buffer = w->Text.buffer;
|
||||
|
||||
while (start >= 0 && ChatInputWidget_IsNameChar(buffer[start])) { start--; }
|
||||
start++;
|
||||
if (end < 0 || start > end) return;
|
||||
while (beg >= 0 && ChatInputWidget_IsNameChar(buffer[beg])) { beg--; }
|
||||
beg++;
|
||||
if (end < 0 || beg > end) return;
|
||||
|
||||
String part = String_UNSAFE_Substring(&w->Text, start, (end + 1) - start);
|
||||
part = String_UNSAFE_Substring(&w->Text, beg, (end + 1) - beg);
|
||||
Chat_AddOf(&String_Empty, MSG_TYPE_CLIENTSTATUS_3);
|
||||
|
||||
EntityID matches[TABLIST_MAX_NAMES];
|
||||
int i, matchesCount = 0;
|
||||
|
||||
for (i = 0; i < TABLIST_MAX_NAMES; i++) {
|
||||
@ -1715,13 +1736,13 @@ static void ChatInputWidget_TabKey(struct InputWidget* w) {
|
||||
|
||||
if (matchesCount == 1) {
|
||||
if (w->CaretPos == -1) end++;
|
||||
int len = end - start, j;
|
||||
int len = end - beg, j;
|
||||
for (j = 0; j < len; j++) {
|
||||
String_DeleteAt(&w->Text, start);
|
||||
String_DeleteAt(&w->Text, beg);
|
||||
}
|
||||
|
||||
if (w->CaretPos != -1) w->CaretPos -= len;
|
||||
String match = TabList_UNSAFE_GetPlayer(matches[0]);
|
||||
match = TabList_UNSAFE_GetPlayer(matches[0]);
|
||||
InputWidget_AppendString(w, &match);
|
||||
} else if (matchesCount > 1) {
|
||||
char strBuffer[STRING_SIZE];
|
||||
@ -1729,7 +1750,7 @@ static void ChatInputWidget_TabKey(struct InputWidget* w) {
|
||||
String_Format1(&str, "&e%i matching names: ", &matchesCount);
|
||||
|
||||
for (i = 0; i < matchesCount; i++) {
|
||||
String match = TabList_UNSAFE_GetPlayer(matches[i]);
|
||||
match = TabList_UNSAFE_GetPlayer(matches[i]);
|
||||
if ((str.length + match.length + 1) > STRING_SIZE) break;
|
||||
|
||||
String_AppendString(&str, &match);
|
||||
@ -1771,10 +1792,8 @@ void ChatInputWidget_Create(struct ChatInputWidget* w, const FontDesc* font) {
|
||||
w->Base.RemakeTexture = ChatInputWidget_RemakeTexture;
|
||||
w->Base.OnPressedEnter = ChatInputWidget_OnPressedEnter;
|
||||
|
||||
String inputStr = String_FromArray(w->__TextBuffer);
|
||||
w->Base.Text = inputStr;
|
||||
String origStr = String_FromArray(w->__OrigBuffer);
|
||||
w->OrigStr = origStr;
|
||||
String_InitArray(w->Base.Text, w->__TextBuffer);
|
||||
String_InitArray(w->OrigStr, w->__OrigBuffer);
|
||||
}
|
||||
|
||||
|
||||
@ -1827,40 +1846,41 @@ void PlayerListWidget_GetNameUnder(struct PlayerListWidget* w, int x, int y, Str
|
||||
|
||||
static void PlayerListWidget_UpdateTableDimensions(struct PlayerListWidget* w) {
|
||||
int width = w->XMax - w->XMin, height = w->YHeight;
|
||||
w->X = (w->XMin ) - LIST_BOUNDS_SIZE;
|
||||
w->X = (w->XMin ) - LIST_BOUNDS_SIZE;
|
||||
w->Y = (Game_Height / 2 - height / 2) - LIST_BOUNDS_SIZE;
|
||||
w->Width = width + LIST_BOUNDS_SIZE * 2;
|
||||
w->Height = height + LIST_BOUNDS_SIZE * 2;
|
||||
}
|
||||
|
||||
static int PlayerListWidget_GetColumnWidth(struct PlayerListWidget* w, int column) {
|
||||
int i = column * LIST_NAMES_PER_COLUMN;
|
||||
int i = column * LIST_NAMES_PER_COLUMN;
|
||||
int end = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
|
||||
int maxWidth = 0;
|
||||
int maxIndex = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
|
||||
|
||||
for (; i < maxIndex; i++) {
|
||||
for (; i < end; i++) {
|
||||
maxWidth = max(maxWidth, w->Textures[i].Width);
|
||||
}
|
||||
return maxWidth + LIST_COLUMN_PADDING + w->ElementOffset;
|
||||
}
|
||||
|
||||
static int PlayerListWidget_GetColumnHeight(struct PlayerListWidget* w, int column) {
|
||||
int i = column * LIST_NAMES_PER_COLUMN;
|
||||
int total = 0;
|
||||
int maxIndex = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
|
||||
int i = column * LIST_NAMES_PER_COLUMN;
|
||||
int end = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
|
||||
int height = 0;
|
||||
|
||||
for (; i < maxIndex; i++) {
|
||||
total += w->Textures[i].Height + 1;
|
||||
for (; i < end; i++) {
|
||||
height += w->Textures[i].Height + 1;
|
||||
}
|
||||
return total;
|
||||
return height;
|
||||
}
|
||||
|
||||
static void PlayerListWidget_SetColumnPos(struct PlayerListWidget* w, int column, int x, int y) {
|
||||
int i = column * LIST_NAMES_PER_COLUMN;
|
||||
int maxIndex = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
|
||||
struct Texture tex;
|
||||
int i = column * LIST_NAMES_PER_COLUMN;
|
||||
int end = min(w->NamesCount, i + LIST_NAMES_PER_COLUMN);
|
||||
|
||||
for (; i < maxIndex; i++) {
|
||||
struct Texture tex = w->Textures[i];
|
||||
for (; i < end; i++) {
|
||||
tex = w->Textures[i];
|
||||
tex.X = x; tex.Y = y - 10;
|
||||
|
||||
y += tex.Height + 1;
|
||||
@ -1909,11 +1929,12 @@ static void PlayerListWidget_Reposition(void* widget) {
|
||||
}
|
||||
|
||||
static void PlayerListWidget_AddName(struct PlayerListWidget* w, EntityID id, int index) {
|
||||
String name;
|
||||
/* insert at end of list */
|
||||
if (index == -1) { index = w->NamesCount; w->NamesCount++; }
|
||||
|
||||
String name = TabList_UNSAFE_GetList(id);
|
||||
w->IDs[index] = id;
|
||||
name = TabList_UNSAFE_GetList(id);
|
||||
w->IDs[index] = id;
|
||||
PlayerListWidget_DrawName(&w->Textures[index], w, &name);
|
||||
}
|
||||
|
||||
@ -1950,11 +1971,12 @@ static void PlayerListWidget_AddGroup(struct PlayerListWidget* w, int id, int* i
|
||||
|
||||
static int PlayerListWidget_GetGroupCount(struct PlayerListWidget* w, int id, int i) {
|
||||
String group = TabList_UNSAFE_GetGroup(id);
|
||||
String curGroup;
|
||||
int count = 0;
|
||||
|
||||
for (; i < w->NamesCount; i++, count++) {
|
||||
String curGroup = TabList_UNSAFE_GetGroup(w->IDs[i]);
|
||||
if (!String_CaselessEquals(&group, &curGroup)) return count;
|
||||
curGroup = TabList_UNSAFE_GetGroup(w->IDs[i]);
|
||||
if (!String_CaselessEquals(&group, &curGroup)) break;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@ -2089,8 +2111,8 @@ static void PlayerListWidget_Init(void* widget) {
|
||||
}
|
||||
|
||||
PlayerListWidget_SortAndReposition(w);
|
||||
TextWidget_Create(&w->Overview, &title, &w->Font);
|
||||
Widget_SetLocation(&w->Overview, ANCHOR_CENTRE, ANCHOR_MIN, 0, 0);
|
||||
TextWidget_Create(&w->Title, &title, &w->Font);
|
||||
Widget_SetLocation(&w->Title, ANCHOR_CENTRE, ANCHOR_MIN, 0, 0);
|
||||
|
||||
Event_RegisterInt(&TabListEvents_Added, w, PlayerListWidget_TabEntryAdded);
|
||||
Event_RegisterInt(&TabListEvents_Changed, w, PlayerListWidget_TabEntryChanged);
|
||||
@ -2099,26 +2121,29 @@ static void PlayerListWidget_Init(void* widget) {
|
||||
|
||||
static void PlayerListWidget_Render(void* widget, double delta) {
|
||||
struct PlayerListWidget* w = widget;
|
||||
struct TextWidget* overview = &w->Overview;
|
||||
PackedCol topCol = PACKEDCOL_CONST(0, 0, 0, 180);
|
||||
struct TextWidget* title = &w->Title;
|
||||
struct Texture tex;
|
||||
int offset, height;
|
||||
int i, selectedI;
|
||||
PackedCol topCol = PACKEDCOL_CONST( 0, 0, 0, 180);
|
||||
PackedCol bottomCol = PACKEDCOL_CONST(50, 50, 50, 205);
|
||||
|
||||
Gfx_SetTexturing(false);
|
||||
int offset = overview->Height + 10;
|
||||
int height = max(300, w->Height + overview->Height);
|
||||
offset = title->Height + 10;
|
||||
height = max(300, w->Height + title->Height);
|
||||
GfxCommon_Draw2DGradient(w->X, w->Y - offset, w->Width, height, topCol, bottomCol);
|
||||
|
||||
Gfx_SetTexturing(true);
|
||||
overview->YOffset = w->Y - offset + 5;
|
||||
Widget_Reposition(overview);
|
||||
Elem_Render(overview, delta);
|
||||
title->YOffset = w->Y - offset + 5;
|
||||
Widget_Reposition(title);
|
||||
Elem_Render(title, delta);
|
||||
|
||||
int i, highlightedI = PlayerListWidget_HighlightedName(w, Mouse_X, Mouse_Y);
|
||||
selectedI = PlayerListWidget_HighlightedName(w, Mouse_X, Mouse_Y);
|
||||
for (i = 0; i < w->NamesCount; i++) {
|
||||
if (!w->Textures[i].ID) continue;
|
||||
|
||||
struct Texture tex = w->Textures[i];
|
||||
if (i == highlightedI) tex.X += 4;
|
||||
tex = w->Textures[i];
|
||||
if (i == selectedI) tex.X += 4;
|
||||
Texture_Render(&tex);
|
||||
}
|
||||
}
|
||||
@ -2130,7 +2155,7 @@ static void PlayerListWidget_Free(void* widget) {
|
||||
Gfx_DeleteTexture(&w->Textures[i].ID);
|
||||
}
|
||||
|
||||
Elem_TryFree(&w->Overview);
|
||||
Elem_TryFree(&w->Title);
|
||||
Event_UnregisterInt(&TabListEvents_Added, w, PlayerListWidget_TabEntryAdded);
|
||||
Event_UnregisterInt(&TabListEvents_Changed, w, PlayerListWidget_TabEntryChanged);
|
||||
Event_UnregisterInt(&TabListEvents_Removed, w, PlayerListWidget_TabEntryRemoved);
|
||||
@ -2160,8 +2185,8 @@ void PlayerListWidget_Create(struct PlayerListWidget* w, const FontDesc* font, b
|
||||
*#########################################################################################################################*/
|
||||
#define TextGroupWidget_LineBuffer(w, i) ((w)->Buffer + (i) * TEXTGROUPWIDGET_LEN)
|
||||
String TextGroupWidget_UNSAFE_Get(struct TextGroupWidget* w, int i) {
|
||||
int length = w->LineLengths[i];
|
||||
return String_Init(TextGroupWidget_LineBuffer(w, i), length, length);
|
||||
int len = w->LineLengths[i];
|
||||
return String_Init(TextGroupWidget_LineBuffer(w, i), len, len);
|
||||
}
|
||||
|
||||
void TextGroupWidget_GetText(struct TextGroupWidget* w, int index, String* text) {
|
||||
@ -2170,9 +2195,11 @@ void TextGroupWidget_GetText(struct TextGroupWidget* w, int index, String* text)
|
||||
}
|
||||
|
||||
void TextGroupWidget_PushUpAndReplaceLast(struct TextGroupWidget* w, const String* text) {
|
||||
int y = w->Y;
|
||||
int max_index;
|
||||
int i, y = w->Y;
|
||||
|
||||
Gfx_DeleteTexture(&w->Textures[0].ID);
|
||||
int i, max_index = w->LinesCount - 1;
|
||||
max_index = w->LinesCount - 1;
|
||||
|
||||
/* Move contents of X line to X - 1 line */
|
||||
for (i = 0; i < max_index; i++) {
|
||||
@ -2276,13 +2303,15 @@ struct Portion { int16_t Beg, Len, LineBeg, LineLen; };
|
||||
#define TEXTGROUPWIDGET_PACKED_LEN 0x7FFF
|
||||
|
||||
static int TextGroupWidget_NextUrl(char* chars, int charsLen, int i) {
|
||||
int start, left;
|
||||
|
||||
for (; i < charsLen; i++) {
|
||||
if (!(chars[i] == 'h' || chars[i] == '&')) continue;
|
||||
int left = charsLen - i;
|
||||
left = charsLen - i;
|
||||
if (left < TEXTGROUPWIDGET_HTTP_LEN) return charsLen;
|
||||
|
||||
/* colour codes at start of URL */
|
||||
int start = i;
|
||||
start = i;
|
||||
while (left >= 2 && chars[i] == '&') { left -= 2; i += 2; }
|
||||
if (left < TEXTGROUPWIDGET_HTTP_LEN) continue;
|
||||
|
||||
@ -2299,9 +2328,12 @@ static int TextGroupWidget_NextUrl(char* chars, int charsLen, int i) {
|
||||
|
||||
static int TextGroupWidget_UrlEnd(char* chars, int charsLen, int32_t* begs, int begsLen, int i) {
|
||||
int start = i, j;
|
||||
int next, left;
|
||||
bool isBeg;
|
||||
|
||||
for (; i < charsLen && chars[i] != ' '; i++) {
|
||||
/* Is this character the start of a line */
|
||||
bool isBeg = false;
|
||||
isBeg = false;
|
||||
for (j = 0; j < begsLen; j++) {
|
||||
if (i == begs[j]) { isBeg = true; break; }
|
||||
}
|
||||
@ -2311,7 +2343,7 @@ static int TextGroupWidget_UrlEnd(char* chars, int charsLen, int32_t* begs, int
|
||||
if (chars[i] != '>') break;
|
||||
|
||||
/* Does this line start with "> ", making it a multiline */
|
||||
int next = i + 1, left = charsLen - next;
|
||||
next = i + 1; left = charsLen - next;
|
||||
while (left >= 2 && chars[next] == '&') { left -= 2; next += 2; }
|
||||
if (left == 0 || chars[next] != ' ') break;
|
||||
|
||||
@ -2321,7 +2353,10 @@ static int TextGroupWidget_UrlEnd(char* chars, int charsLen, int32_t* begs, int
|
||||
}
|
||||
|
||||
static void TextGroupWidget_Output(struct Portion bit, int lineBeg, int lineEnd, struct Portion** portions) {
|
||||
struct Portion* cur;
|
||||
int overBy, underBy;
|
||||
if (bit.Beg >= lineEnd || !bit.Len) return;
|
||||
|
||||
bit.LineBeg = bit.Beg;
|
||||
bit.LineLen = bit.Len & TEXTGROUPWIDGET_PACKED_LEN;
|
||||
|
||||
@ -2329,18 +2364,18 @@ static void TextGroupWidget_Output(struct Portion bit, int lineBeg, int lineEnd,
|
||||
if (bit.Beg >= lineBeg) {
|
||||
} else if (bit.Beg + bit.LineLen > lineBeg) {
|
||||
/* Adjust start of portion to be within this line */
|
||||
int underBy = lineBeg - bit.Beg;
|
||||
underBy = lineBeg - bit.Beg;
|
||||
bit.LineBeg += underBy; bit.LineLen -= underBy;
|
||||
} else { return; }
|
||||
|
||||
/* Limit length of portion to be within this line */
|
||||
int overBy = (bit.LineBeg + bit.LineLen) - lineEnd;
|
||||
overBy = (bit.LineBeg + bit.LineLen) - lineEnd;
|
||||
if (overBy > 0) bit.LineLen -= overBy;
|
||||
|
||||
bit.LineBeg -= lineBeg;
|
||||
if (!bit.LineLen) return;
|
||||
|
||||
struct Portion* cur = *portions; *cur++ = bit; *portions = cur;
|
||||
cur = *portions; *cur++ = bit; *portions = cur;
|
||||
}
|
||||
|
||||
static int TextGroupWidget_Reduce(struct TextGroupWidget* w, char* chars, int target, struct Portion* portions) {
|
||||
@ -2348,20 +2383,22 @@ static int TextGroupWidget_Reduce(struct TextGroupWidget* w, char* chars, int ta
|
||||
int32_t begs[TEXTGROUPWIDGET_MAX_LINES];
|
||||
int32_t ends[TEXTGROUPWIDGET_MAX_LINES];
|
||||
struct Portion bit;
|
||||
int i, total = 0, end = 0;
|
||||
int len, nextStart;
|
||||
int i, total = 0, end;
|
||||
|
||||
for (i = 0; i < w->LinesCount; i++) {
|
||||
int lineLen = w->LineLengths[i];
|
||||
len = w->LineLengths[i];
|
||||
begs[i] = -1; ends[i] = -1;
|
||||
if (!lineLen) continue;
|
||||
if (!len) continue;
|
||||
|
||||
begs[i] = total;
|
||||
Mem_Copy(&chars[total], TextGroupWidget_LineBuffer(w, i), lineLen);
|
||||
total += lineLen; ends[i] = total;
|
||||
Mem_Copy(&chars[total], TextGroupWidget_LineBuffer(w, i), len);
|
||||
total += len; ends[i] = total;
|
||||
}
|
||||
|
||||
end = 0;
|
||||
for (;;) {
|
||||
int nextStart = TextGroupWidget_NextUrl(chars, total, end);
|
||||
nextStart = TextGroupWidget_NextUrl(chars, total, end);
|
||||
|
||||
/* add normal portion between urls */
|
||||
bit.Beg = end;
|
||||
@ -2397,25 +2434,28 @@ static void TextGroupWidget_FormatUrl(String* text, const String* url) {
|
||||
static bool TextGroupWidget_GetUrl(struct TextGroupWidget* w, String* text, int index, int mouseX) {
|
||||
char chars[TEXTGROUPWIDGET_MAX_LINES * TEXTGROUPWIDGET_LEN];
|
||||
struct Portion portions[2 * (TEXTGROUPWIDGET_LEN / TEXTGROUPWIDGET_HTTP_LEN)];
|
||||
struct Portion bit;
|
||||
struct DrawTextArgs args = { 0 };
|
||||
String line;
|
||||
String line, url;
|
||||
int portionsCount;
|
||||
int i, x, width;
|
||||
|
||||
mouseX -= w->Textures[index].X;
|
||||
args.UseShadow = true;
|
||||
line = TextGroupWidget_UNSAFE_Get(w, index);
|
||||
|
||||
if (Game_ClassicMode) return false;
|
||||
int i, x, portionsCount = TextGroupWidget_Reduce(w, chars, index, portions);
|
||||
portionsCount = TextGroupWidget_Reduce(w, chars, index, portions);
|
||||
|
||||
for (i = 0, x = 0; i < portionsCount; i++) {
|
||||
struct Portion bit = portions[i];
|
||||
bit = portions[i];
|
||||
args.Text = String_UNSAFE_Substring(&line, bit.LineBeg, bit.LineLen);
|
||||
args.Font = (bit.Len & TEXTGROUPWIDGET_URL) ? w->UnderlineFont : w->Font;
|
||||
|
||||
int width = Drawer2D_MeasureText(&args).Width;
|
||||
width = Drawer2D_MeasureText(&args).Width;
|
||||
if ((bit.Len & TEXTGROUPWIDGET_URL) && mouseX >= x && mouseX < x + width) {
|
||||
bit.Len &= TEXTGROUPWIDGET_PACKED_LEN;
|
||||
String url = String_Init(&chars[bit.Beg], bit.Len, bit.Len);
|
||||
url = String_Init(&chars[bit.Beg], bit.Len, bit.Len);
|
||||
|
||||
TextGroupWidget_FormatUrl(text, &url);
|
||||
return true;
|
||||
@ -2460,33 +2500,38 @@ static bool TextGroupWidget_MightHaveUrls(struct TextGroupWidget* w) {
|
||||
static void TextGroupWidget_DrawAdvanced(struct TextGroupWidget* w, struct Texture* tex, struct DrawTextArgs* args, int index, const String* text) {
|
||||
char chars[TEXTGROUPWIDGET_MAX_LINES * TEXTGROUPWIDGET_LEN];
|
||||
struct Portion portions[2 * (TEXTGROUPWIDGET_LEN / TEXTGROUPWIDGET_HTTP_LEN)];
|
||||
int i, x, portionsCount = TextGroupWidget_Reduce(w, chars, index, portions);
|
||||
|
||||
Size2D total = { 0, 0 };
|
||||
struct Portion bit;
|
||||
Size2D size = { 0, 0 };
|
||||
Size2D partSizes[Array_Elems(portions)];
|
||||
Bitmap bmp;
|
||||
int portionsCount;
|
||||
int i, x;
|
||||
|
||||
portionsCount = TextGroupWidget_Reduce(w, chars, index, portions);
|
||||
for (i = 0; i < portionsCount; i++) {
|
||||
struct Portion bit = portions[i];
|
||||
bit = portions[i];
|
||||
|
||||
args->Text = String_UNSAFE_Substring(text, bit.LineBeg, bit.LineLen);
|
||||
args->Font = (bit.Len & TEXTGROUPWIDGET_URL) ? w->UnderlineFont : w->Font;
|
||||
|
||||
partSizes[i] = Drawer2D_MeasureText(args);
|
||||
total.Height = max(partSizes[i].Height, total.Height);
|
||||
total.Width += partSizes[i].Width;
|
||||
size.Height = max(partSizes[i].Height, size.Height);
|
||||
size.Width += partSizes[i].Width;
|
||||
}
|
||||
|
||||
Bitmap_AllocateClearedPow2(&bmp, total.Width, total.Height);
|
||||
Bitmap_AllocateClearedPow2(&bmp, size.Width, size.Height);
|
||||
{
|
||||
for (i = 0, x = 0; i < portionsCount; i++) {
|
||||
struct Portion bit = portions[i];
|
||||
x = 0;
|
||||
for (i = 0; i < portionsCount; i++) {
|
||||
bit = portions[i];
|
||||
|
||||
args->Text = String_UNSAFE_Substring(text, bit.LineBeg, bit.LineLen);
|
||||
args->Font = (bit.Len & TEXTGROUPWIDGET_URL) ? w->UnderlineFont : w->Font;
|
||||
|
||||
Drawer2D_DrawText(&bmp, args, x, 0);
|
||||
x += partSizes[i].Width;
|
||||
}
|
||||
Drawer2D_Make2DTexture(tex, &bmp, total, 0, 0);
|
||||
Drawer2D_Make2DTexture(tex, &bmp, size, 0, 0);
|
||||
}
|
||||
Mem_Free(bmp.Scan0);
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ struct PlayerListWidget {
|
||||
int NamesCount, ElementOffset;
|
||||
int XMin, XMax, YHeight;
|
||||
bool Classic;
|
||||
struct TextWidget Overview;
|
||||
struct TextWidget Title;
|
||||
uint16_t IDs[TABLIST_MAX_NAMES * 2];
|
||||
struct Texture Textures[TABLIST_MAX_NAMES * 2];
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user