From 776906ebce890c459aef16ccc8f1c1fe08efec52 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 3 Nov 2023 18:34:05 +1100 Subject: [PATCH] Move entity name rendering into more general EntityRenderers module --- src/AxisLinesRenderer.c | 2 +- src/Entity.c | 204 ++++--------------------------------- src/Entity.h | 6 +- src/EntityRenderers.c | 213 ++++++++++++++++++++++++++++++++++++--- src/EntityRenderers.h | 10 +- src/EnvRenderer.c | 73 +++++++------- src/Game.c | 5 +- src/Graphics.h | 1 - src/Graphics_3DS.c | 2 + src/Graphics_Dreamcast.c | 2 + src/Graphics_GCWii.c | 2 + src/Graphics_PS3.c | 2 + src/Graphics_PSP.c | 2 + src/Graphics_PSVita.c | 2 + src/Graphics_Xbox.c | 2 + src/Program.c | 4 +- src/_GraphicsBase.h | 2 +- 17 files changed, 285 insertions(+), 249 deletions(-) diff --git a/src/AxisLinesRenderer.c b/src/AxisLinesRenderer.c index 7798f0f26..44bb75895 100644 --- a/src/AxisLinesRenderer.c +++ b/src/AxisLinesRenderer.c @@ -34,7 +34,7 @@ void AxisLinesRenderer_Render(void) { if (!AxisLinesRenderer_Enabled) return; /* Don't do it in a ContextRecreated handler, because we only want VB recreated if ShowAxisLines in on. */ if (!axisLines_vb) { - Gfx_RecreateDynamicVb(&axisLines_vb, VERTEX_FORMAT_COLOURED, AXISLINES_NUM_VERTICES); + axisLines_vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_COLOURED, AXISLINES_NUM_VERTICES); } if (Camera.Active->isThirdPerson) { diff --git a/src/Entity.c b/src/Entity.c index 136576601..dfe7bbede 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -9,8 +9,6 @@ #include "Funcs.h" #include "Graphics.h" #include "Lighting.h" -#include "Drawer2D.h" -#include "Particle.h" #include "Http.h" #include "Chat.h" #include "Model.h" @@ -22,6 +20,7 @@ #include "Options.h" #include "Errors.h" #include "Utils.h" +#include "EntityRenderers.h" const char* const NameMode_Names[NAME_MODE_COUNT] = { "None", "Hovered", "All", "AllHovered", "AllUnscaled" }; const char* const ShadowMode_Names[SHADOW_MODE_COUNT] = { "None", "SnapToBlock", "Circle", "CircleAll" }; @@ -47,6 +46,11 @@ void Entity_Init(struct Entity* e) { Entity_SetModel(e, &model); } +void Entity_SetName(struct Entity* e, const cc_string* name) { + EntityNames_Delete(e); + String_CopyToRawArray(e->NameRaw, name); +} + Vec3 Entity_GetEyePosition(struct Entity* e) { Vec3 pos = e->Position; pos.Y += Entity_GetEyeHeight(e); return pos; } @@ -191,107 +195,6 @@ cc_bool Entity_TouchesAnyWater(struct Entity* e) { } - -/*########################################################################################################################* -*-----------------------------------------------------Entity nametag------------------------------------------------------* -*#########################################################################################################################*/ -#define NAME_IS_EMPTY -30000 -#define NAME_OFFSET 3 /* offset of back layer of name above an entity */ - -static void MakeNameTexture(struct Entity* e) { - cc_string colorlessName; char colorlessBuffer[STRING_SIZE]; - BitmapCol shadowColor = BitmapCol_Make(80, 80, 80, 255); - BitmapCol origWhiteColor; - - struct DrawTextArgs args; - struct FontDesc font; - struct Context2D ctx; - int width, height; - cc_string name; - - /* Names are always drawn using default.png font */ - Font_MakeBitmapped(&font, 24, FONT_FLAGS_NONE); - /* Don't want DPI scaling or padding */ - font.size = 24; font.height = 24; - - name = String_FromRawArray(e->NameRaw); - DrawTextArgs_Make(&args, &name, &font, false); - width = Drawer2D_TextWidth(&args); - - if (!width) { - e->NameTex.ID = 0; - e->NameTex.X = NAME_IS_EMPTY; - } else { - String_InitArray(colorlessName, colorlessBuffer); - width += NAME_OFFSET; - height = Drawer2D_TextHeight(&args) + NAME_OFFSET; - - Context2D_Alloc(&ctx, width, height); - { - origWhiteColor = Drawer2D.Colors['f']; - - Drawer2D.Colors['f'] = shadowColor; - Drawer2D_WithoutColors(&colorlessName, &name); - args.text = colorlessName; - Context2D_DrawText(&ctx, &args, NAME_OFFSET, NAME_OFFSET); - - Drawer2D.Colors['f'] = origWhiteColor; - args.text = name; - Context2D_DrawText(&ctx, &args, 0, 0); - } - Context2D_MakeTexture(&e->NameTex, &ctx); - Context2D_Free(&ctx); - } -} - -static void DrawName(struct Entity* e) { - struct VertexTextured* vertices; - struct Model* model; - struct Matrix mat; - Vec3 pos; - float scale; - Vec2 size; - - if (e->NameTex.X == NAME_IS_EMPTY) return; - if (!e->NameTex.ID) MakeNameTexture(e); - Gfx_BindTexture(e->NameTex.ID); - - model = e->Model; - Vec3_TransformY(&pos, model->GetNameY(e), &e->Transform); - - scale = model->nameScale * e->ModelScale.Y; - scale = scale > 1.0f ? (1.0f/70.0f) : (scale/70.0f); - size.X = e->NameTex.Width * scale; size.Y = e->NameTex.Height * scale; - - if (Entities.NamesMode == NAME_MODE_ALL_UNSCALED && LocalPlayer_Instance.Hacks.CanSeeAllNames) { - Matrix_Mul(&mat, &Gfx.View, &Gfx.Projection); /* TODO: This mul is slow, avoid it */ - /* Get W component of transformed position */ - scale = pos.X * mat.row1.W + pos.Y * mat.row2.W + pos.Z * mat.row3.W + mat.row4.W; - size.X *= scale * 0.2f; size.Y *= scale * 0.2f; - } - - Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); - - vertices = (struct VertexTextured*)Gfx_LockDynamicVb(Gfx_texVb, VERTEX_FORMAT_TEXTURED, 4); - Particle_DoRender(&size, &pos, &e->NameTex.uv, PACKEDCOL_WHITE, vertices); - Gfx_UnlockDynamicVb(Gfx_texVb); - - Gfx_DrawVb_IndexedTris(4); -} - -/* Deletes the texture containing the entity's nametag */ -CC_NOINLINE static void DeleteNameTex(struct Entity* e) { - Gfx_DeleteTexture(&e->NameTex.ID); - e->NameTex.X = 0; /* X is used as an 'empty name' flag */ -} - -void Entity_SetName(struct Entity* e, const cc_string* name) { - DeleteNameTex(e); - String_CopyToRawArray(e->NameRaw, name); - /* name texture redraw deferred until necessary */ -} - - /*########################################################################################################################* *------------------------------------------------------Entity skins-------------------------------------------------------* *#########################################################################################################################*/ @@ -531,7 +434,6 @@ void Entity_LerpAngles(struct Entity* e, float t) { *--------------------------------------------------------Entities---------------------------------------------------------* *#########################################################################################################################*/ struct _EntitiesData Entities; -static EntityID entities_closestId; void Entities_Tick(struct ScheduledTask* task) { int i; @@ -551,83 +453,17 @@ void Entities_RenderModels(double delta, float t) { } Gfx_SetAlphaTest(false); } - - -void Entities_RenderNames(void) { - struct LocalPlayer* p = &LocalPlayer_Instance; - cc_bool hadFog; - int i; - - if (Entities.NamesMode == NAME_MODE_NONE) return; - entities_closestId = Entities_GetClosest(&p->Base); - if (!p->Hacks.CanSeeAllNames || Entities.NamesMode != NAME_MODE_ALL) return; - - Gfx_SetAlphaTest(true); - hadFog = Gfx_GetFog(); - if (hadFog) Gfx_SetFog(false); - - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i]) continue; - if (i != entities_closestId || i == ENTITIES_SELF_ID) { - Entities.List[i]->VTABLE->RenderName(Entities.List[i]); - } - } - - Gfx_SetAlphaTest(false); - if (hadFog) Gfx_SetFog(true); -} - -void Entities_RenderHoveredNames(void) { - struct LocalPlayer* p = &LocalPlayer_Instance; - cc_bool allNames, hadFog; - int i; - - if (Entities.NamesMode == NAME_MODE_NONE) return; - allNames = !(Entities.NamesMode == NAME_MODE_HOVERED || Entities.NamesMode == NAME_MODE_ALL) - && p->Hacks.CanSeeAllNames; - - Gfx_SetAlphaTest(true); - Gfx_SetDepthTest(false); - hadFog = Gfx_GetFog(); - if (hadFog) Gfx_SetFog(false); - - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i]) continue; - if ((i == entities_closestId || allNames) && i != ENTITIES_SELF_ID) { - Entities.List[i]->VTABLE->RenderName(Entities.List[i]); - } - } - - Gfx_SetAlphaTest(false); - Gfx_SetDepthTest(true); - if (hadFog) Gfx_SetFog(true); -} - -static void Entity_ContextLost(struct Entity* e) { DeleteNameTex(e); } static void Entities_ContextLost(void* obj) { int i; - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i]) continue; - Entity_ContextLost(Entities.List[i]); - } - if (Gfx.ManagedTextures) return; + for (i = 0; i < ENTITIES_MAX_COUNT; i++) { if (!Entities.List[i]) continue; DeleteSkin(Entities.List[i]); } } -/* No OnContextCreated, names/skin textures remade when needed */ - -static void Entities_ChatFontChanged(void* obj) { - int i; - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i]) continue; - DeleteNameTex(Entities.List[i]); - /* name redraw is deferred until rendered */ - } -} +/* No OnContextCreated, skin textures remade when needed */ void Entities_Remove(EntityID id) { struct Entity* e = Entities.List[id]; @@ -749,7 +585,7 @@ struct IGameComponent TabList_Component = { static void Player_Despawn(struct Entity* e) { DeleteSkin(e); - Entity_ContextLost(e); + EntityNames_Delete(e); } @@ -870,9 +706,8 @@ static void LocalPlayer_RenderModel(struct Entity* e, double deltaTime, float t) Model_Render(e->Model, e); } -static void LocalPlayer_RenderName(struct Entity* e) { - if (!Camera.Active->isThirdPerson) return; - DrawName(e); +static cc_bool LocalPlayer_ShouldRenderName(struct Entity* e) { + return Camera.Active->isThirdPerson; } static void LocalPlayer_CheckJumpVelocity(void* obj) { @@ -896,7 +731,7 @@ static void LocalPlayer_GetMovement(float* xMoving, float* zMoving) { static const struct EntityVTABLE localPlayer_VTABLE = { LocalPlayer_Tick, Player_Despawn, LocalPlayer_SetLocation, Entity_GetColor, - LocalPlayer_RenderModel, LocalPlayer_RenderName + LocalPlayer_RenderModel, LocalPlayer_ShouldRenderName }; static void LocalPlayer_Init(void) { struct LocalPlayer* p = &LocalPlayer_Instance; @@ -1152,19 +987,19 @@ static void NetPlayer_RenderModel(struct Entity* e, double deltaTime, float t) { if (e->ShouldRender) Model_Render(e->Model, e); } -static void NetPlayer_RenderName(struct Entity* e) { +static cc_bool NetPlayer_ShouldRenderName(struct Entity* e) { float distance; int threshold; - if (!e->ShouldRender) return; + if (!e->ShouldRender) return false; distance = Model_RenderDistance(e); threshold = Entities.NamesMode == NAME_MODE_ALL_UNSCALED ? 8192 * 8192 : 32 * 32; - if (distance <= (float)threshold) DrawName(e); + return distance <= (float)threshold; } static const struct EntityVTABLE netPlayer_VTABLE = { NetPlayer_Tick, Player_Despawn, NetPlayer_SetLocation, Entity_GetColor, - NetPlayer_RenderModel, NetPlayer_RenderName + NetPlayer_RenderModel, NetPlayer_ShouldRenderName }; void NetPlayer_Init(struct NetPlayer* p) { Mem_Set(p, 0, sizeof(struct NetPlayer)); @@ -1177,10 +1012,9 @@ void NetPlayer_Init(struct NetPlayer* p) { *---------------------------------------------------Entities component----------------------------------------------------* *#########################################################################################################################*/ static void Entities_Init(void) { - Event_Register_(&GfxEvents.ContextLost, NULL, Entities_ContextLost); - Event_Register_(&ChatEvents.FontChanged, NULL, Entities_ChatFontChanged); - Event_Register_(&InputEvents.Down, NULL, LocalPlayer_InputDown); - Event_Register_(&InputEvents.Up, NULL, LocalPlayer_InputUp); + Event_Register_(&GfxEvents.ContextLost, NULL, Entities_ContextLost); + Event_Register_(&InputEvents.Down, NULL, LocalPlayer_InputDown); + Event_Register_(&InputEvents.Up, NULL, LocalPlayer_InputUp); Entities.NamesMode = Options_GetEnum(OPT_NAMES_MODE, NAME_MODE_HOVERED, NameMode_Names, Array_Elems(NameMode_Names)); diff --git a/src/Entity.h b/src/Entity.h index b3e8e9202..22c6b1e45 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -71,7 +71,7 @@ struct EntityVTABLE { void (*SetLocation)(struct Entity* e, struct LocationUpdate* update); PackedCol (*GetCol)(struct Entity* e); void (*RenderModel)(struct Entity* e, double deltaTime, float t); - void (*RenderName)(struct Entity* e); + cc_bool (*ShouldRenderName)(struct Entity* e); }; /* Skin is still being downloaded asynchronously */ @@ -155,10 +155,6 @@ CC_VAR extern struct _EntitiesData { void Entities_Tick(struct ScheduledTask* task); /* Renders all entities */ void Entities_RenderModels(double delta, float t); -/* Renders the name tags of entities, depending on Entities.NamesMode */ -void Entities_RenderNames(void); -/* Renders hovered entity name tags (these appears through blocks) */ -void Entities_RenderHoveredNames(void); /* Removes the given entity, raising EntityEvents.Removed event */ void Entities_Remove(EntityID id); /* Gets the ID of the closest entity to the given entity */ diff --git a/src/EntityRenderers.c b/src/EntityRenderers.c index 8f027b4a6..d33f3dd21 100644 --- a/src/EntityRenderers.c +++ b/src/EntityRenderers.c @@ -9,15 +9,29 @@ #include "Graphics.h" #include "Model.h" #include "World.h" +#include "Particle.h" +#include "Drawer2D.h" /*########################################################################################################################* *------------------------------------------------------Entity Shadow------------------------------------------------------* *#########################################################################################################################*/ static cc_bool shadows_boundTex; +static GfxResourceID shadows_VB; static GfxResourceID shadows_tex; static float shadow_radius, shadow_uvScale; struct ShadowData { float Y; BlockID Block; cc_uint8 A; }; +/* Circle shadows extend at most 4 blocks vertically */ +#define SHADOW_MAX_RANGE 4 +/* Circle shadows on blocks underneath the top block can be chopped up into at most 4 pieces */ +#define SHADOW_MAX_PER_SUB_BLOCK (4 * 4) +/* Circle shadows use at most: + - 4 vertices for top most block + - MAX_PER_SUB_BLOCK for everyblock underneath the top block */ +#define SHADOW_MAX_PER_COLUMN (4 + SHADOW_MAX_PER_SUB_BLOCK * (SHADOW_MAX_RANGE - 1)) +/* Circle shadows may be split across (x,z), (x,z+1), (x+1,z), (x+1,z+1) */ +#define SHADOW_MAX_VERTS 4 * SHADOW_MAX_PER_COLUMN + static cc_bool lequal(float a, float b) { return a < b || Math_AbsF(a - b) < 0.001f; } static void EntityShadow_DrawCoords(struct VertexTextured** vertices, struct Entity* e, struct ShadowData* data, float x1, float z1, float x2, float z2) { PackedCol col; @@ -72,7 +86,8 @@ static void EntityShadow_DrawCircle(struct VertexTextured** vertices, struct Ent min = Blocks.MinBB[data[0].Block]; max = Blocks.MaxBB[data[0].Block]; EntityShadow_DrawCoords(vertices, e, &data[0], x + min.X, z + min.Z, x + max.X, z + max.Z); - for (i = 1; i < 4; i++) { + for (i = 1; i < 4; i++) + { if (data[i].Block == BLOCK_AIR) return; nMin = Blocks.MinBB[data[i].Block]; nMax = Blocks.MaxBB[data[i].Block]; @@ -112,7 +127,8 @@ static cc_bool EntityShadow_GetBlocks(struct Entity* e, int x, int y, int z, str posY = e->Position.Y; outside = !World_ContainsXZ(x, z); - for (i = 0; y >= 0 && i < 4; y--) { + for (i = 0; y >= 0 && i < 4; y--) + { if (!outside) { block = World_GetBlock(x, y, z); } else if (y == Env.EdgeHeight - 1) { @@ -146,10 +162,9 @@ static cc_bool EntityShadow_GetBlocks(struct Entity* e, int x, int y, int z, str } static void EntityShadow_Draw(struct Entity* e) { - struct VertexTextured vertices[128]; + struct VertexTextured vertices[128]; /* TODO this is less than maxVertes */ struct VertexTextured* ptr; struct ShadowData data[4]; - GfxResourceID vb; Vec3 pos; float radius; int y, count; @@ -163,16 +178,13 @@ static void EntityShadow_Draw(struct Entity* e) { shadow_radius = radius / 16.0f; shadow_uvScale = 16.0f / (radius * 2.0f); - /* TODO: Should shadow component use its own VB? */ ptr = vertices; if (Entities.ShadowsMode == SHADOW_MODE_SNAP_TO_BLOCK) { - vb = Gfx_texVb; x1 = Math_Floor(pos.X); z1 = Math_Floor(pos.Z); if (!EntityShadow_GetBlocks(e, x1, y, z1, data)) return; EntityShadow_DrawSquareShadow(&ptr, data[0].Y, x1, z1); } else { - vb = Models.Vb; x1 = Math_Floor(pos.X - shadow_radius); z1 = Math_Floor(pos.Z - shadow_radius); x2 = Math_Floor(pos.X + shadow_radius); z2 = Math_Floor(pos.Z + shadow_radius); @@ -198,7 +210,7 @@ static void EntityShadow_Draw(struct Entity* e) { } count = (int)(ptr - vertices); - Gfx_SetDynamicVbData(vb, vertices, count); + Gfx_SetDynamicVbData(shadows_VB, vertices, count); Gfx_DrawVb_IndexedTris(count); } @@ -226,7 +238,7 @@ static void EntityShadows_MakeTexture(void) { row[x] = dist < sh_half * sh_half ? color : 0; } } - Gfx_RecreateTexture(&shadows_tex, &bmp, 0, false); + shadows_tex = Gfx_CreateTexture(&bmp, 0, false); } void EntityShadows_Render(void) { @@ -234,7 +246,10 @@ void EntityShadows_Render(void) { if (Entities.ShadowsMode == SHADOW_MODE_NONE) return; shadows_boundTex = false; - if (!shadows_tex) EntityShadows_MakeTexture(); + if (!shadows_tex) + EntityShadows_MakeTexture(); + if (!shadows_VB) + shadows_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, SHADOW_MAX_VERTS); Gfx_SetAlphaArgBlend(true); Gfx_SetDepthWrite(false); @@ -257,19 +272,193 @@ void EntityShadows_Render(void) { } +/*########################################################################################################################* +*-----------------------------------------------------Entity nametag------------------------------------------------------* +*#########################################################################################################################*/ +static GfxResourceID names_VB; +#define NAME_IS_EMPTY -30000 +#define NAME_OFFSET 3 /* offset of back layer of name above an entity */ + +static void MakeNameTexture(struct Entity* e) { + cc_string colorlessName; char colorlessBuffer[STRING_SIZE]; + BitmapCol shadowColor = BitmapCol_Make(80, 80, 80, 255); + BitmapCol origWhiteColor; + + struct DrawTextArgs args; + struct FontDesc font; + struct Context2D ctx; + int width, height; + cc_string name; + + /* Names are always drawn using default.png font */ + Font_MakeBitmapped(&font, 24, FONT_FLAGS_NONE); + /* Don't want DPI scaling or padding */ + font.size = 24; font.height = 24; + + name = String_FromRawArray(e->NameRaw); + DrawTextArgs_Make(&args, &name, &font, false); + width = Drawer2D_TextWidth(&args); + + if (!width) { + e->NameTex.ID = 0; + e->NameTex.X = NAME_IS_EMPTY; + } else { + String_InitArray(colorlessName, colorlessBuffer); + width += NAME_OFFSET; + height = Drawer2D_TextHeight(&args) + NAME_OFFSET; + + Context2D_Alloc(&ctx, width, height); + { + origWhiteColor = Drawer2D.Colors['f']; + + Drawer2D.Colors['f'] = shadowColor; + Drawer2D_WithoutColors(&colorlessName, &name); + args.text = colorlessName; + Context2D_DrawText(&ctx, &args, NAME_OFFSET, NAME_OFFSET); + + Drawer2D.Colors['f'] = origWhiteColor; + args.text = name; + Context2D_DrawText(&ctx, &args, 0, 0); + } + Context2D_MakeTexture(&e->NameTex, &ctx); + Context2D_Free(&ctx); + } +} + +static void DrawName(struct Entity* e) { + struct VertexTextured* vertices; + struct Model* model; + struct Matrix mat; + Vec3 pos; + float scale; + Vec2 size; + + if (!e->VTABLE->ShouldRenderName(e)) return; + if (e->NameTex.X == NAME_IS_EMPTY) return; + if (!e->NameTex.ID) MakeNameTexture(e); + Gfx_BindTexture(e->NameTex.ID); + + if (!names_VB) + names_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, 4); + + model = e->Model; + Vec3_TransformY(&pos, model->GetNameY(e), &e->Transform); + + scale = model->nameScale * e->ModelScale.Y; + scale = scale > 1.0f ? (1.0f/70.0f) : (scale/70.0f); + size.X = e->NameTex.Width * scale; size.Y = e->NameTex.Height * scale; + + if (Entities.NamesMode == NAME_MODE_ALL_UNSCALED && LocalPlayer_Instance.Hacks.CanSeeAllNames) { + Matrix_Mul(&mat, &Gfx.View, &Gfx.Projection); /* TODO: This mul is slow, avoid it */ + /* Get W component of transformed position */ + scale = pos.X * mat.row1.W + pos.Y * mat.row2.W + pos.Z * mat.row3.W + mat.row4.W; + size.X *= scale * 0.2f; size.Y *= scale * 0.2f; + } + + Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED); + + vertices = (struct VertexTextured*)Gfx_LockDynamicVb(names_VB, VERTEX_FORMAT_TEXTURED, 4); + Particle_DoRender(&size, &pos, &e->NameTex.uv, PACKEDCOL_WHITE, vertices); + Gfx_UnlockDynamicVb(names_VB); + + Gfx_DrawVb_IndexedTris(4); +} + +void EntityNames_Delete(struct Entity* e) { + Gfx_DeleteTexture(&e->NameTex.ID); + e->NameTex.X = 0; /* X is used as an 'empty name' flag */ +} + + +/*########################################################################################################################* +*-----------------------------------------------------Names rendering-----------------------------------------------------* +*#########################################################################################################################*/ +static EntityID closestEntityId; + +void EntityNames_Render(void) { + struct LocalPlayer* p = &LocalPlayer_Instance; + cc_bool hadFog; + int i; + + if (Entities.NamesMode == NAME_MODE_NONE) return; + closestEntityId = Entities_GetClosest(&p->Base); + if (!p->Hacks.CanSeeAllNames || Entities.NamesMode != NAME_MODE_ALL) return; + + Gfx_SetAlphaTest(true); + hadFog = Gfx_GetFog(); + if (hadFog) Gfx_SetFog(false); + + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + if (!Entities.List[i]) continue; + if (i != closestEntityId || i == ENTITIES_SELF_ID) { + DrawName(Entities.List[i]); + } + } + + Gfx_SetAlphaTest(false); + if (hadFog) Gfx_SetFog(true); +} + +void EntityNames_RenderHovered(void) { + struct LocalPlayer* p = &LocalPlayer_Instance; + cc_bool allNames, hadFog; + int i; + + if (Entities.NamesMode == NAME_MODE_NONE) return; + allNames = !(Entities.NamesMode == NAME_MODE_HOVERED || Entities.NamesMode == NAME_MODE_ALL) + && p->Hacks.CanSeeAllNames; + + Gfx_SetAlphaTest(true); + Gfx_SetDepthTest(false); + hadFog = Gfx_GetFog(); + if (hadFog) Gfx_SetFog(false); + + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + if (!Entities.List[i]) continue; + if ((i == closestEntityId || allNames) && i != ENTITIES_SELF_ID) { + DrawName(Entities.List[i]); + } + } + + Gfx_SetAlphaTest(false); + Gfx_SetDepthTest(true); + if (hadFog) Gfx_SetFog(true); +} + +static void DeleteAllNameTextures(void) { + int i; + for (i = 0; i < ENTITIES_MAX_COUNT; i++) + { + if (!Entities.List[i]) continue; + EntityNames_Delete(Entities.List[i]); + } +} + +static void EntityNames_ChatFontChanged(void* obj) { + DeleteAllNameTextures(); +} + + /*########################################################################################################################* *-----------------------------------------------Entity renderers component------------------------------------------------* *#########################################################################################################################*/ static void EntityRenderers_ContextLost(void* obj) { Gfx_DeleteTexture(&shadows_tex); + Gfx_DeleteDynamicVb(&shadows_VB); + + Gfx_DeleteDynamicVb(&names_VB); + DeleteAllNameTextures(); } static void EntityRenderers_Init(void) { - Event_Register_(&GfxEvents.ContextLost, NULL, EntityRenderers_ContextLost); + Event_Register_(&GfxEvents.ContextLost, NULL, EntityRenderers_ContextLost); + Event_Register_(&ChatEvents.FontChanged, NULL, EntityNames_ChatFontChanged); } static void EntityRenderers_Free(void) { - Gfx_DeleteTexture(&shadows_tex); + EntityRenderers_ContextLost(NULL); } struct IGameComponent EntityRenderers_Component = { diff --git a/src/EntityRenderers.h b/src/EntityRenderers.h index a2f03131a..ab46eee46 100644 --- a/src/EntityRenderers.h +++ b/src/EntityRenderers.h @@ -1,13 +1,21 @@ #ifndef CC_ENTITYRENDERERS_H #define CC_ENTITYRENDERERS_H #include "Core.h" -/* Renders supporting objects for entities (shadows) +/* Renders supporting objects for entities (shadows and names) Copyright 2014-2023 ClassiCube | Licensed under BSD-3 */ struct IGameComponent; extern struct IGameComponent EntityRenderers_Component; +struct Entity; /* Draws shadows under entities, depending on Entities.ShadowsMode */ void EntityShadows_Render(void); +/* Deletes the texture containing the entity's nametag */ +void EntityNames_Delete(struct Entity* e); +/* Renders the name tags of entities, depending on Entities.NamesMode */ +void EntityNames_Render(void); +/* Renders hovered entity name tags (these appears through blocks) */ +void EntityNames_RenderHovered(void); + #endif diff --git a/src/EnvRenderer.c b/src/EnvRenderer.c index 5fbad21af..ce63c8378 100644 --- a/src/EnvRenderer.c +++ b/src/EnvRenderer.c @@ -272,11 +272,42 @@ static GfxResourceID skybox_tex, skybox_vb; #define SKYBOX_COUNT (6 * 4) cc_bool EnvRenderer_ShouldRenderSkybox(void) { return skybox_tex && !EnvRenderer_Minimal; } +static void AllocateSkyboxVB(void) { + static const struct VertexTextured vertices[SKYBOX_COUNT] = { + /* Front quad */ + { -1, -1, -1, 0, 0.25f, 1.00f }, { 1, -1, -1, 0, 0.50f, 1.00f }, + { 1, 1, -1, 0, 0.50f, 0.50f }, { -1, 1, -1, 0, 0.25f, 0.50f }, + /* Left quad */ + { -1, -1, 1, 0, 0.00f, 1.00f }, { -1, -1, -1, 0, 0.25f, 1.00f }, + { -1, 1, -1, 0, 0.25f, 0.50f }, { -1, 1, 1, 0, 0.00f, 0.50f }, + /* Back quad */ + { 1, -1, 1, 0, 0.75f, 1.00f }, { -1, -1, 1, 0, 1.00f, 1.00f }, + { -1, 1, 1, 0, 1.00f, 0.50f }, { 1, 1, 1, 0, 0.75f, 0.50f }, + /* Right quad */ + { 1, -1, -1, 0, 0.50f, 1.00f }, { 1, -1, 1, 0, 0.75f, 1.00f }, + { 1, 1, 1, 0, 0.75f, 0.50f }, { 1, 1, -1, 0, 0.50f, 0.50f }, + /* Top quad */ + { 1, 1, -1, 0, 0.50f, 0.50f }, { 1, 1, 1, 0, 0.50f, 0.00f }, + { -1, 1, 1, 0, 0.25f, 0.00f }, { -1, 1, -1, 0, 0.25f, 0.50f }, + /* Bottom quad */ + { 1, -1, -1, 0, 0.75f, 0.50f }, { 1, -1, 1, 0, 0.75f, 0.00f }, + { -1, -1, 1, 0, 0.50f, 0.00f }, { -1, -1, -1, 0, 0.50f, 0.50f }, + }; + struct VertexTextured* data; + int i; + + data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&skybox_vb, + VERTEX_FORMAT_TEXTURED, SKYBOX_COUNT); + Mem_Copy(data, vertices, sizeof(vertices)); + for (i = 0; i < SKYBOX_COUNT; i++) { data[i].Col = Env.SkyboxCol; } + Gfx_UnlockVb(skybox_vb); +} + void EnvRenderer_RenderSkybox(void) { struct Matrix m, rotX, rotY, view; float rotTime; Vec3 pos; - if (!skybox_vb) return; + if (!skybox_vb) AllocateSkyboxVB(); Gfx_SetDepthWrite(false); Gfx_BindTexture(skybox_tex); @@ -302,42 +333,6 @@ void EnvRenderer_RenderSkybox(void) { Gfx_SetDepthWrite(true); } -static void UpdateSkybox(void) { - static const struct VertexTextured vertices[SKYBOX_COUNT] = { - /* Front quad */ - { -1, -1, -1, 0, 0.25f, 1.00f }, { 1, -1, -1, 0, 0.50f, 1.00f }, - { 1, 1, -1, 0, 0.50f, 0.50f }, { -1, 1, -1, 0, 0.25f, 0.50f }, - /* Left quad */ - { -1, -1, 1, 0, 0.00f, 1.00f }, { -1, -1, -1, 0, 0.25f, 1.00f }, - { -1, 1, -1, 0, 0.25f, 0.50f }, { -1, 1, 1, 0, 0.00f, 0.50f }, - /* Back quad */ - { 1, -1, 1, 0, 0.75f, 1.00f }, { -1, -1, 1, 0, 1.00f, 1.00f }, - { -1, 1, 1, 0, 1.00f, 0.50f }, { 1, 1, 1, 0, 0.75f, 0.50f }, - /* Right quad */ - { 1, -1, -1, 0, 0.50f, 1.00f }, { 1, -1, 1, 0, 0.75f, 1.00f }, - { 1, 1, 1, 0, 0.75f, 0.50f }, { 1, 1, -1, 0, 0.50f, 0.50f }, - /* Top quad */ - { 1, 1, -1, 0, 0.50f, 0.50f }, { 1, 1, 1, 0, 0.50f, 0.00f }, - { -1, 1, 1, 0, 0.25f, 0.00f }, { -1, 1, -1, 0, 0.25f, 0.50f }, - /* Bottom quad */ - { 1, -1, -1, 0, 0.75f, 0.50f }, { 1, -1, 1, 0, 0.75f, 0.00f }, - { -1, -1, 1, 0, 0.50f, 0.00f }, { -1, -1, -1, 0, 0.50f, 0.50f }, - }; - struct VertexTextured* data; - int i; - - Gfx_DeleteVb(&skybox_vb); - if (Gfx.LostContext) return; - if (EnvRenderer_Minimal) return; - - data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&skybox_vb, - VERTEX_FORMAT_TEXTURED, SKYBOX_COUNT); - Mem_Copy(data, vertices, sizeof(vertices)); - for (i = 0; i < SKYBOX_COUNT; i++) { data[i].Col = Env.SkyboxCol; } - Gfx_UnlockVb(skybox_vb); -} - - /*########################################################################################################################* *----------------------------------------------------------Weather--------------------------------------------------------* *#########################################################################################################################*/ @@ -834,7 +829,7 @@ static void UpdateAll(void) { UpdateMapEdges(); UpdateClouds(); UpdateSky(); - UpdateSkybox(); + Gfx_DeleteVb(&skybox_vb); EnvRenderer_UpdateFog(); Gfx_DeleteDynamicVb(&weather_vb); @@ -898,7 +893,7 @@ static void OnEnvVariableChanged(void* obj, int envVar) { UpdateSky(); UpdateClouds(); } else if (envVar == ENV_VAR_SKYBOX_COLOR) { - UpdateSkybox(); + Gfx_DeleteVb(&skybox_vb); } } diff --git a/src/Game.c b/src/Game.c index aedc766ce..a197fdb0b 100644 --- a/src/Game.c +++ b/src/Game.c @@ -463,7 +463,7 @@ static void Game_Render3D(double delta, float t) { AxisLinesRenderer_Render(); Entities_RenderModels(delta, t); - Entities_RenderNames(); + EntityNames_Render(); Particles_Render(t); Camera.Active->GetPickedBlock(&Game_SelectedPos); /* TODO: only pick when necessary */ @@ -496,7 +496,7 @@ static void Game_Render3D(double delta, float t) { } Selections_Render(); - Entities_RenderHoveredNames(); + EntityNames_RenderHovered(); Camera_KeyLookUpdate(); InputHandler_Tick(); if (!Game_HideGui) HeldBlockRenderer_Render(delta); @@ -573,6 +573,7 @@ static void Game_RenderFrame(double delta) { Gfx_RecreateContext(); /* all good, context is back */ } else { + Game.Time += delta; /* TODO: Not set in two places? */ Server.Tick(NULL); Thread_Sleep(16); return; diff --git a/src/Graphics.h b/src/Graphics.h index 277a3ffb6..fa97eef5e 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -56,7 +56,6 @@ CC_VAR extern struct _GfxData { } Gfx; extern GfxResourceID Gfx_defaultIb; -extern GfxResourceID Gfx_quadVb, Gfx_texVb; extern const cc_string Gfx_LowPerfMessage; #define ICOUNT(verticesCount) (((verticesCount) >> 2) * 6) diff --git a/src/Graphics_3DS.c b/src/Graphics_3DS.c index 794c7a688..f12287ea9 100644 --- a/src/Graphics_3DS.c +++ b/src/Graphics_3DS.c @@ -434,6 +434,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { return AllocBuffer(maxVertices, strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } diff --git a/src/Graphics_Dreamcast.c b/src/Graphics_Dreamcast.c index 9bd4023fa..6cdec6f0f 100644 --- a/src/Graphics_Dreamcast.c +++ b/src/Graphics_Dreamcast.c @@ -190,6 +190,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { return memalign(16, maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { vb_size = count * strideSizes[fmt]; return vb; diff --git a/src/Graphics_GCWii.c b/src/Graphics_GCWii.c index b7fbccb69..b211e5357 100644 --- a/src/Graphics_GCWii.c +++ b/src/Graphics_GCWii.c @@ -320,6 +320,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { return memalign(16, maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { vb_size = count * strideSizes[fmt]; return vb; diff --git a/src/Graphics_PS3.c b/src/Graphics_PS3.c index ee1d1b888..408ca52fe 100644 --- a/src/Graphics_PS3.c +++ b/src/Graphics_PS3.c @@ -538,6 +538,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) return rsxMemalign(128, maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { vb_size = count * strideSizes[fmt]; return vb; diff --git a/src/Graphics_PSP.c b/src/Graphics_PSP.c index acfb217f2..30461db8c 100644 --- a/src/Graphics_PSP.c +++ b/src/Graphics_PSP.c @@ -311,6 +311,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { return memalign(16, maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { vb_size = count * strideSizes[fmt]; return vb; diff --git a/src/Graphics_PSVita.c b/src/Graphics_PSVita.c index d1134203d..88dbe685e 100644 --- a/src/Graphics_PSVita.c +++ b/src/Graphics_PSVita.c @@ -915,6 +915,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { return GPUBuffer_Alloc(maxVertices * strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { struct GPUBuffer* buffer = (struct GPUBuffer*)vb; return buffer->data; diff --git a/src/Graphics_Xbox.c b/src/Graphics_Xbox.c index 7fe032d9a..25ffa4074 100644 --- a/src/Graphics_Xbox.c +++ b/src/Graphics_Xbox.c @@ -453,6 +453,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { return AllocBuffer(maxVertices, strideSizes[fmt]); } +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } diff --git a/src/Program.c b/src/Program.c index addcea54f..988e33007 100644 --- a/src/Program.c +++ b/src/Program.c @@ -77,8 +77,8 @@ static int RunProgram(int argc, char** argv) { #ifdef _MSC_VER /* NOTE: Make sure to comment this out before pushing a commit */ //cc_string rawArgs = String_FromConst("UnknownShadow200 fffff 127.0.0.1 25565"); - cc_string rawArgs = String_FromConst("UnknownShadow200"); - argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4); + //cc_string rawArgs = String_FromConst("UnknownShadow200"); + //argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4); #endif if (argsCount == 0) { diff --git a/src/_GraphicsBase.h b/src/_GraphicsBase.h index 9b08e7407..6e5c5a453 100644 --- a/src/_GraphicsBase.h +++ b/src/_GraphicsBase.h @@ -13,7 +13,7 @@ struct _GfxData Gfx; GfxResourceID Gfx_defaultIb; -GfxResourceID Gfx_quadVb, Gfx_texVb; +static GfxResourceID Gfx_quadVb, Gfx_texVb; const cc_string Gfx_LowPerfMessage = String_FromConst("&eRunning in reduced performance mode (game minimised or hidden)"); static const int strideSizes[] = { SIZEOF_VERTEX_COLOURED, SIZEOF_VERTEX_TEXTURED };