diff --git a/src/Builder.c b/src/Builder.c index ccb9135dc..bd153ef93 100644 --- a/src/Builder.c +++ b/src/Builder.c @@ -37,8 +37,8 @@ static int (*Builder_StretchXLiquid)(int countIndex, int x, int y, int z, int ch static int (*Builder_StretchX)(int countIndex, int x, int y, int z, int chunkIndex, BlockID block, Face face); static int (*Builder_StretchZ)(int countIndex, int x, int y, int z, int chunkIndex, BlockID block, Face face); static void (*Builder_RenderBlock)(int countsIndex); -static void (*Builder_PreStretchTiles)(int x1, int y1, int z1); -static void (*Builder_PostStretchTiles)(int x1, int y1, int z1); +static void (*Builder_PreStretchTiles)(void); +static void (*Builder_PostStretchTiles)(void); /* Contains state for vertices for a portion of a chunk mesh (vertices that are in a 1D atlas) */ struct Builder1DPart { @@ -51,7 +51,6 @@ struct Builder1DPart { The first ATLAS1D_MAX_ATLASES parts are for normal parts, remainder are for translucent parts. */ static struct Builder1DPart Builder_Parts[ATLAS1D_MAX_ATLASES * 2]; static VertexP3fT2fC4b* Builder_Vertices; -static int Builder_VerticesElems; static int Builder1DPart_VerticesCount(struct Builder1DPart* part) { int i, count = part->sCount; @@ -84,13 +83,13 @@ static int Builder_TotalVerticesCount(void) { /*########################################################################################################################* *----------------------------------------------------Base mesh builder----------------------------------------------------* *#########################################################################################################################*/ -static void Builder_AddSpriteVertices(BlockID block) { +static void AddSpriteVertices(BlockID block) { int i = Atlas1D_Index(Block_Tex(block, FACE_XMAX)); struct Builder1DPart* part = &Builder_Parts[i]; part->sCount += 4 * 4; } -static void Builder_AddVertices(BlockID block, Face face) { +static void AddVertices(BlockID block, Face face) { int baseOffset = (Blocks.Draw[block] == DRAW_TRANSLUCENT) * ATLAS1D_MAX_ATLASES; int i = Atlas1D_Index(Block_Tex(block, face)); struct Builder1DPart* part = &Builder_Parts[baseOffset + i]; @@ -105,7 +104,7 @@ static void BuildPartVbs(struct ChunkPartInfo* info) { count = info->Counts[i]; if (count) { - info->Vbs[i] = Gfx_CreateVb(&Builder_Vertices[offset], VERTEX_FORMAT_P3FT2FC4B, count); + info->Vbs[i] = Gfx_CreateVb2(&Builder_Vertices[offset], VERTEX_FORMAT_P3FT2FC4B, count); offset += count; } else { info->Vbs[i] = 0; @@ -115,14 +114,14 @@ static void BuildPartVbs(struct ChunkPartInfo* info) { count = info->SpriteCount; offset = info->Offset; if (count) { - info->Vbs[i] = Gfx_CreateVb(&Builder_Vertices[offset], VERTEX_FORMAT_P3FT2FC4B, count); + info->Vbs[i] = Gfx_CreateVb2(&Builder_Vertices[offset], VERTEX_FORMAT_P3FT2FC4B, count); } else { info->Vbs[i] = 0; } } #endif -static void Builder_SetPartInfo(struct Builder1DPart* part, int* offset, struct ChunkPartInfo* info, cc_bool* hasParts) { +static void SetPartInfo(struct Builder1DPart* part, int* offset, struct ChunkPartInfo* info, cc_bool* hasParts) { int vCount = Builder1DPart_VerticesCount(part); info->Offset = -1; if (!vCount) return; @@ -180,7 +179,7 @@ static void Builder_Stretch(int x1, int y1, int z1) { /* Sprites can't be stretched, nor can then be they hidden by other blocks. */ /* Note sprites are drawn using DrawSprite and not with any of the DrawXFace. */ if (Blocks.Draw[b] == DRAW_SPRITE) { - Builder_AddSpriteVertices(b); + AddSpriteVertices(b); continue; } @@ -195,7 +194,7 @@ static void Builder_Stretch(int x1, int y1, int z1) { Builder_Counts[index] = 0; } else { count = Builder_StretchZ(index, x, y, z, cIndex, b, FACE_XMIN); - Builder_AddVertices(b, FACE_XMIN); + AddVertices(b, FACE_XMIN); Builder_Counts[index] = count; } @@ -206,7 +205,7 @@ static void Builder_Stretch(int x1, int y1, int z1) { Builder_Counts[index] = 0; } else { count = Builder_StretchZ(index, x, y, z, cIndex, b, FACE_XMAX); - Builder_AddVertices(b, FACE_XMAX); + AddVertices(b, FACE_XMAX); Builder_Counts[index] = count; } @@ -217,7 +216,7 @@ static void Builder_Stretch(int x1, int y1, int z1) { Builder_Counts[index] = 0; } else { count = Builder_StretchX(index, Builder_X, Builder_Y, Builder_Z, cIndex, b, FACE_ZMIN); - Builder_AddVertices(b, FACE_ZMIN); + AddVertices(b, FACE_ZMIN); Builder_Counts[index] = count; } @@ -228,7 +227,7 @@ static void Builder_Stretch(int x1, int y1, int z1) { Builder_Counts[index] = 0; } else { count = Builder_StretchX(index, x, y, z, cIndex, b, FACE_ZMAX); - Builder_AddVertices(b, FACE_ZMAX); + AddVertices(b, FACE_ZMAX); Builder_Counts[index] = count; } @@ -238,7 +237,7 @@ static void Builder_Stretch(int x1, int y1, int z1) { Builder_Counts[index] = 0; } else { count = Builder_StretchX(index, x, y, z, cIndex, b, FACE_YMIN); - Builder_AddVertices(b, FACE_YMIN); + AddVertices(b, FACE_YMIN); Builder_Counts[index] = count; } @@ -248,11 +247,11 @@ static void Builder_Stretch(int x1, int y1, int z1) { Builder_Counts[index] = 0; } else if (b < BLOCK_WATER || b > BLOCK_STILL_LAVA) { count = Builder_StretchX(index, x, y, z, cIndex, b, FACE_YMAX); - Builder_AddVertices(b, FACE_YMAX); + AddVertices(b, FACE_YMAX); Builder_Counts[index] = count; } else { count = Builder_StretchXLiquid(index, x, y, z, cIndex, b); - if (count > 0) Builder_AddVertices(b, FACE_YMAX); + if (count > 0) AddVertices(b, FACE_YMAX); Builder_Counts[index] = count; } } @@ -349,20 +348,20 @@ static cc_bool ReadBorderChunkData(int x1, int y1, int z1, cc_bool* outAllAir) { return false; } -static cc_bool Builder_BuildChunk(int x1, int y1, int z1, cc_bool* allAir) { +static cc_bool BuildChunk(int x1, int y1, int z1, struct ChunkInfo* info) { BlockID chunk[EXTCHUNK_SIZE_3]; cc_uint8 counts[CHUNK_SIZE_3 * FACE_COUNT]; int bitFlags[EXTCHUNK_SIZE_3]; - cc_bool allSolid, onBorder; - int xMax, yMax, zMax; + cc_bool allAir, allSolid, onBorder; + int xMax, yMax, zMax, totalVerts; int cIndex, index; int x, y, z, xx, yy, zz; Builder_Chunk = chunk; Builder_Counts = counts; Builder_BitFlags = bitFlags; - Builder_PreStretchTiles(x1, y1, z1); + Builder_PreStretchTiles(); onBorder = x1 == 0 || y1 == 0 || z1 == 0 || x1 + CHUNK_SIZE >= World.Width || @@ -371,12 +370,13 @@ static cc_bool Builder_BuildChunk(int x1, int y1, int z1, cc_bool* allAir) { if (onBorder) { /* less optimal case here */ Mem_Set(chunk, BLOCK_AIR, EXTCHUNK_SIZE_3 * sizeof(BlockID)); - allSolid = ReadBorderChunkData(x1, y1, z1, allAir); + allSolid = ReadBorderChunkData(x1, y1, z1, &allAir); } else { - allSolid = ReadChunkData(x1, y1, z1, allAir); + allSolid = ReadChunkData(x1, y1, z1, &allAir); } - if (*allAir || allSolid) return false; + info->AllAir = allAir; + if (allAir || allSolid) return false; Lighting_LightHint(x1 - 1, z1 - 1); Mem_Set(counts, 1, CHUNK_SIZE_3 * FACE_COUNT); @@ -386,7 +386,18 @@ static cc_bool Builder_BuildChunk(int x1, int y1, int z1, cc_bool* allAir) { Builder_ChunkEndX = xMax; Builder_ChunkEndZ = zMax; Builder_Stretch(x1, y1, z1); - Builder_PostStretchTiles(x1, y1, z1); + + totalVerts = Builder_TotalVerticesCount(); + if (!totalVerts) return false; + +#ifndef CC_BUILD_GL11 + /* add an extra element to fix crashing on some GPUs */ + Builder_Vertices = Gfx_CreateAndLockVb(VERTEX_FORMAT_P3FT2FC4B, totalVerts + 1, &info->Vb); +#else + /* NOTE: Relies on assumption vb is ignored by GL11 Gfx_LockVb implementation */ + Builder_Vertices = Gfx_LockVb(0, VERTEX_FORMAT_P3FT2FC4B, totalVerts + 1); +#endif + Builder_PostStretchTiles(); for (y = y1, yy = 0; y < yMax; y++, yy++) { for (z = z1, zz = 0; z < zMax; z++, zz++) { @@ -403,27 +414,22 @@ static cc_bool Builder_BuildChunk(int x1, int y1, int z1, cc_bool* allAir) { } } } + +#ifndef CC_BUILD_GL11 + Gfx_UnlockVb(info->Vb); +#endif return true; } void Builder_MakeChunk(struct ChunkInfo* info) { int x = info->CentreX - 8, y = info->CentreY - 8, z = info->CentreZ - 8; - cc_bool allAir, hasMesh, hasNorm, hasTran; - int totalVerts, partsIndex; + cc_bool hasMesh, hasNorm, hasTran; + int partsIndex; int i, j, curIdx, offset; - allAir = false; - hasMesh = Builder_BuildChunk(x, y, z, &allAir); - info->AllAir = allAir; + hasMesh = BuildChunk(x, y, z, info); if (!hasMesh) return; - totalVerts = Builder_TotalVerticesCount(); - if (!totalVerts) return; -#ifndef CC_BUILD_GL11 - /* add an extra element to fix crashing on some GPUs */ - info->Vb = Gfx_CreateVb(Builder_Vertices, VERTEX_FORMAT_P3FT2FC4B, totalVerts + 1); -#endif - partsIndex = MapRenderer_Pack(x >> CHUNK_SHIFT, y >> CHUNK_SHIFT, z >> CHUNK_SHIFT); offset = 0; hasNorm = false; @@ -433,8 +439,8 @@ void Builder_MakeChunk(struct ChunkInfo* info) { j = i + ATLAS1D_MAX_ATLASES; curIdx = partsIndex + i * MapRenderer_ChunksCount; - Builder_SetPartInfo(&Builder_Parts[i], &offset, &MapRenderer_PartsNormal[curIdx], &hasNorm); - Builder_SetPartInfo(&Builder_Parts[j], &offset, &MapRenderer_PartsTranslucent[curIdx], &hasTran); + SetPartInfo(&Builder_Parts[i], &offset, &MapRenderer_PartsNormal[curIdx], &hasNorm); + SetPartInfo(&Builder_Parts[j], &offset, &MapRenderer_PartsTranslucent[curIdx], &hasTran); } if (hasNorm) { @@ -460,21 +466,12 @@ static cc_bool Builder_OccludedLiquid(int chunkIndex) { && Blocks.Draw[Builder_Chunk[chunkIndex + EXTCHUNK_SIZE]] != DRAW_GAS; } -static void Builder_DefaultPreStretchTiles(int x1, int y1, int z1) { +static void DefaultPreStretchTiles(void) { Mem_Set(Builder_Parts, 0, sizeof(Builder_Parts)); } -static void Builder_DefaultPostStretchTiles(int x1, int y1, int z1) { - int i, j, offset, count; - - count = Builder_TotalVerticesCount(); - if (count > Builder_VerticesElems) { - Mem_Free(Builder_Vertices); - /* ensure buffer can be accessed with 64 bytes alignment by putting 2 extra vertices at end. */ - Builder_Vertices = (VertexP3fT2fC4b*)Mem_Alloc(count + 2, sizeof(VertexP3fT2fC4b), "chunk vertices"); - Builder_VerticesElems = count; - } - +static void DefaultPostStretchTiles(void) { + int i, j, offset; offset = 0; for (i = 0; i < ATLAS1D_MAX_ATLASES; i++) { j = i + ATLAS1D_MAX_ATLASES; @@ -756,8 +753,8 @@ static void Builder_SetDefault(void) { Builder_RenderBlock = NULL; Builder_UseBitFlags = false; - Builder_PreStretchTiles = Builder_DefaultPreStretchTiles; - Builder_PostStretchTiles = Builder_DefaultPostStretchTiles; + Builder_PreStretchTiles = DefaultPreStretchTiles; + Builder_PostStretchTiles = DefaultPostStretchTiles; } static void NormalBuilder_SetActive(void) { @@ -1238,9 +1235,9 @@ static void Adv_RenderBlock(int index) { if (count_YMax) Adv_DrawYMax(count_YMax); } -static void Adv_PreStretchTiles(int x1, int y1, int z1) { +static void Adv_PreStretchTiles(void) { int i; - Builder_DefaultPreStretchTiles(x1, y1, z1); + DefaultPreStretchTiles(); adv_bitFlags = Builder_BitFlags; for (i = 0; i <= 4; i++) { diff --git a/src/EnvRenderer.c b/src/EnvRenderer.c index fe6c6a797..ac740ccc8 100644 --- a/src/EnvRenderer.c +++ b/src/EnvRenderer.c @@ -180,8 +180,7 @@ static void DrawCloudsY(int x1, int z1, int x2, int z2, int y, VertexP3fT2fC4b* } static void UpdateClouds(void) { - VertexP3fT2fC4b v[ENV_SMALL_VERTICES]; - VertexP3fT2fC4b* ptr; + VertexP3fT2fC4b* data; int extent; int x1, z1, x2, z2; @@ -194,15 +193,9 @@ static void UpdateClouds(void) { z1 = -extent; z2 = World.Length + extent; clouds_vertices = CalcNumVertices(x2 - x1, z2 - z1); - ptr = v; - if (clouds_vertices > ENV_SMALL_VERTICES) { - ptr = (VertexP3fT2fC4b*)Mem_Alloc(clouds_vertices, sizeof(VertexP3fT2fC4b), "clouds vertices"); - } - - DrawCloudsY(x1, z1, x2, z2, Env.CloudsHeight, ptr); - clouds_vb = Gfx_CreateVb(ptr, VERTEX_FORMAT_P3FT2FC4B, clouds_vertices); - - if (clouds_vertices > ENV_SMALL_VERTICES) Mem_Free(ptr); + data = Gfx_CreateAndLockVb(VERTEX_FORMAT_P3FT2FC4B, clouds_vertices, &clouds_vb); + DrawCloudsY(x1, z1, x2, z2, Env.CloudsHeight, data); + Gfx_UnlockVb(clouds_vb); } @@ -258,8 +251,7 @@ static void DrawSkyY(int x1, int z1, int x2, int z2, int y, VertexP3fC4b* v) { } static void UpdateSky(void) { - VertexP3fC4b v[ENV_SMALL_VERTICES]; - VertexP3fC4b* ptr; + VertexP3fC4b* data; int extent, height; int x1, z1, x2, z2; @@ -272,16 +264,10 @@ static void UpdateSky(void) { z1 = -extent; z2 = World.Length + extent; sky_vertices = CalcNumVertices(x2 - x1, z2 - z1); - ptr = v; - if (sky_vertices > ENV_SMALL_VERTICES) { - ptr = (VertexP3fC4b*)Mem_Alloc(sky_vertices, sizeof(VertexP3fC4b), "sky vertices"); - } - + data = Gfx_CreateAndLockVb(VERTEX_FORMAT_P3FC4B, sky_vertices, &sky_vb); height = max((World.Height + 2), Env.CloudsHeight) + 6; - DrawSkyY(x1, z1, x2, z2, height, ptr); - sky_vb = Gfx_CreateVb(ptr, VERTEX_FORMAT_P3FC4B, sky_vertices); - - if (sky_vertices > ENV_SMALL_VERTICES) Mem_Free(ptr); + DrawSkyY(x1, z1, x2, z2, height, data); + Gfx_UnlockVb(sky_vb); } /*########################################################################################################################* @@ -324,7 +310,7 @@ void EnvRenderer_RenderSkybox(void) { } static void UpdateSkybox(void) { - static VertexP3fT2fC4b vertices[SKYBOX_COUNT] = { + static const VertexP3fT2fC4b 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 }, @@ -344,14 +330,17 @@ static void UpdateSkybox(void) { { 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 }, }; + VertexP3fT2fC4b* data; int i; Gfx_DeleteVb(&skybox_vb); - if (Gfx.LostContext) return; + if (Gfx.LostContext) return; if (EnvRenderer_Minimal) return; - for (i = 0; i < SKYBOX_COUNT; i++) { vertices[i].Col = Env.SkyboxCol; } - skybox_vb = Gfx_CreateVb(vertices, VERTEX_FORMAT_P3FT2FC4B, SKYBOX_COUNT); + data = Gfx_CreateAndLockVb(VERTEX_FORMAT_P3FT2FC4B, SKYBOX_COUNT, &skybox_vb); + Mem_Copy(data, vertices, sizeof(vertices)); + for (i = 0; i < SKYBOX_COUNT; i++) { data[i].Col = Env.SkyboxCol; } + Gfx_UnlockVb(skybox_vb); } @@ -489,8 +478,7 @@ void EnvRenderer_RenderWeather(double deltaTime) { if (height <= 0) continue; if (particles && (weather_accumulator >= 0.25 || moved)) { - Vec3 particlePos = Vec3_Create3((float)x, y, (float)z); - Particles_RainSnowEffect(particlePos); + Particles_RainSnowEffect((float)x, y, (float)z); } dist = dx * dx + dz * dz; @@ -680,10 +668,7 @@ static void UpdateMapSides(void) { PackedCol col, white = PACKEDCOL_WHITE; int y, y1, y2; int i; - - VertexP3fT2fC4b v[ENV_SMALL_VERTICES]; - VertexP3fT2fC4b* ptr; - VertexP3fT2fC4b* cur; + VertexP3fT2fC4b* data; Gfx_DeleteVb(&sides_vb); if (!World.Blocks || Gfx.LostContext) return; @@ -699,15 +684,10 @@ static void UpdateMapSides(void) { } y = Env_SidesHeight; - sides_vertices += CalcNumVertices(World.Width, World.Length); /* YQuads beneath map */ + sides_vertices += CalcNumVertices(World.Width, World.Length); /* YQuads beneath map */ sides_vertices += 2 * CalcNumVertices(World.Width, Math_AbsI(y)); /* ZQuads */ sides_vertices += 2 * CalcNumVertices(World.Length, Math_AbsI(y)); /* XQuads */ - - ptr = v; - if (sides_vertices > ENV_SMALL_VERTICES) { - ptr = (VertexP3fT2fC4b*)Mem_Alloc(sides_vertices, sizeof(VertexP3fT2fC4b), "sides vertices"); - } - cur = ptr; + data = Gfx_CreateAndLockVb(VERTEX_FORMAT_P3FT2FC4B, sides_vertices, &sides_vb); sides_fullBright = Blocks.FullBright[block]; col = sides_fullBright ? white : Env.ShadowCol; @@ -716,21 +696,20 @@ static void UpdateMapSides(void) { for (i = 0; i < 4; i++) { r = rects[i]; DrawBorderY(r.X, r.Y, r.X + r.Width, r.Y + r.Height, (float)y, col, - 0, Borders_YOffset(block), &cur); + 0, Borders_YOffset(block), &data); } /* Work properly for when ground level is below 0 */ y1 = 0; y2 = y; if (y < 0) { y1 = y; y2 = 0; } - DrawBorderY(0, 0, World.Width, World.Length, 0, col, 0, 0, &cur); - DrawBorderZ(0, 0, World.Width, y1, y2, col, &cur); - DrawBorderZ(World.Length, 0, World.Width, y1, y2, col, &cur); - DrawBorderX(0, 0, World.Length, y1, y2, col, &cur); - DrawBorderX(World.Width, 0, World.Length, y1, y2, col, &cur); + DrawBorderY(0, 0, World.Width, World.Length, 0, col, 0, 0, &data); + DrawBorderZ(0, 0, World.Width, y1, y2, col, &data); + DrawBorderZ(World.Length, 0, World.Width, y1, y2, col, &data); + DrawBorderX(0, 0, World.Length, y1, y2, col, &data); + DrawBorderX(World.Width, 0, World.Length, y1, y2, col, &data); - sides_vb = Gfx_CreateVb(ptr, VERTEX_FORMAT_P3FT2FC4B, sides_vertices); - if (sides_vertices > ENV_SMALL_VERTICES) Mem_Free(ptr); + Gfx_UnlockVb(sides_vb); } static void UpdateMapEdges(void) { @@ -739,10 +718,7 @@ static void UpdateMapEdges(void) { PackedCol col, white = PACKEDCOL_WHITE; float y; int i; - - VertexP3fT2fC4b v[ENV_SMALL_VERTICES]; - VertexP3fT2fC4b* ptr; - VertexP3fT2fC4b* cur; + VertexP3fT2fC4b* data; Gfx_DeleteVb(&edges_vb); if (!World.Blocks || Gfx.LostContext) return; @@ -756,12 +732,7 @@ static void UpdateMapEdges(void) { r = rects[i]; edges_vertices += CalcNumVertices(r.Width, r.Height); /* YPlanes outside */ } - - ptr = v; - if (edges_vertices > ENV_SMALL_VERTICES) { - ptr = (VertexP3fT2fC4b*)Mem_Alloc(edges_vertices, sizeof(VertexP3fT2fC4b), "edge vertices"); - } - cur = ptr; + data = Gfx_CreateAndLockVb(VERTEX_FORMAT_P3FT2FC4B, edges_vertices, &edges_vb); edges_fullBright = Blocks.FullBright[block]; col = edges_fullBright ? white : Env.SunCol; @@ -771,11 +742,9 @@ static void UpdateMapEdges(void) { for (i = 0; i < 4; i++) { r = rects[i]; DrawBorderY(r.X, r.Y, r.X + r.Width, r.Y + r.Height, y, col, - Borders_HorOffset(block), Borders_YOffset(block), &cur); + Borders_HorOffset(block), Borders_YOffset(block), &data); } - - edges_vb = Gfx_CreateVb(ptr, VERTEX_FORMAT_P3FT2FC4B, edges_vertices); - if (edges_vertices > ENV_SMALL_VERTICES) Mem_Free(ptr); + Gfx_UnlockVb(edges_vb); } diff --git a/src/Graphics.c b/src/Graphics.c index 6fea35094..dac720fc3 100644 --- a/src/Graphics.c +++ b/src/Graphics.c @@ -83,16 +83,16 @@ static void Gfx_RecreateContext(void) { } -void Gfx_UpdateDynamicVb_Lines(GfxResourceID vb, void* vertices, int vCount) { - Gfx_SetDynamicVbData(vb, vertices, vCount); - Gfx_DrawVb_Lines(vCount); -} - void Gfx_UpdateDynamicVb_IndexedTris(GfxResourceID vb, void* vertices, int vCount) { Gfx_SetDynamicVbData(vb, vertices, vCount); Gfx_DrawVb_IndexedTris(vCount); } +void* Gfx_CreateAndLockVb(VertexFormat fmt, int count, GfxResourceID* vb) { + *vb = Gfx_CreateVb(fmt, count); + return Gfx_LockVb(*vb, fmt, count); +} + void Gfx_Draw2DFlat(int x, int y, int width, int height, PackedCol col) { VertexP3fC4b verts[4]; VertexP3fC4b* v = verts; @@ -671,11 +671,44 @@ static void D3D9_RestoreRenderStates(void) { /*########################################################################################################################* -*---------------------------------------------------Vertex/Index buffers--------------------------------------------------* +*-------------------------------------------------------Index buffers-----------------------------------------------------* *#########################################################################################################################*/ -static IDirect3DVertexBuffer9* D3D9_AllocVertexBuffer(VertexFormat fmt, int size, DWORD usage) { +static void D3D9_SetIbData(IDirect3DIndexBuffer9* buffer, void* data, int size) { + void* dst = NULL; + cc_result res = IDirect3DIndexBuffer9_Lock(buffer, 0, size, &dst, 0); + if (res) Logger_Abort2(res, "D3D9_LockIb"); + + Mem_Copy(dst, data, size); + res = IDirect3DIndexBuffer9_Unlock(buffer); + if (res) Logger_Abort2(res, "D3D9_UnlockIb"); +} + +GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { + int size = indicesCount * 2; + IDirect3DIndexBuffer9* ibuffer; + cc_result res = IDirect3DDevice9_CreateIndexBuffer(device, size, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ibuffer, NULL); + if (res) Logger_Abort2(res, "D3D9_CreateIb"); + + D3D9_SetIbData(ibuffer, indices, size); + return ibuffer; +} + +void Gfx_BindIb(GfxResourceID ib) { + IDirect3DIndexBuffer9* ibuffer = (IDirect3DIndexBuffer9*)ib; + cc_result res = IDirect3DDevice9_SetIndices(device, ibuffer); + if (res) Logger_Abort2(res, "D3D9_BindIb"); +} + +void Gfx_DeleteIb(GfxResourceID* ib) { D3D9_FreeResource(ib); } + + +/*########################################################################################################################* +*------------------------------------------------------Vertex buffers-----------------------------------------------------* +*#########################################################################################################################*/ +static IDirect3DVertexBuffer9* D3D9_AllocVertexBuffer(VertexFormat fmt, int count, DWORD usage) { IDirect3DVertexBuffer9* vbuffer; cc_result res; + int size = count * gfx_strideSizes[fmt]; for (;;) { res = IDirect3DDevice9_CreateVertexBuffer(device, size, usage, @@ -698,39 +731,18 @@ static void D3D9_SetVbData(IDirect3DVertexBuffer9* buffer, void* data, int size, if (res) Logger_Abort2(res, "D3D9_UnlockVb"); } -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - int size = maxVertices * gfx_strideSizes[fmt]; - if (Gfx.LostContext) return 0; - return D3D9_AllocVertexBuffer(fmt, size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); -} - -GfxResourceID Gfx_CreateVb(void* vertices, VertexFormat fmt, int count) { - int size = count * gfx_strideSizes[fmt]; - IDirect3DVertexBuffer9* vbuffer; - - vbuffer = D3D9_AllocVertexBuffer(fmt, size, D3DUSAGE_WRITEONLY); - D3D9_SetVbData(vbuffer, vertices, size, 0); - return vbuffer; -} - -static void D3D9_SetIbData(IDirect3DIndexBuffer9* buffer, void* data, int size) { +static void* D3D9_LockVb(GfxResourceID vb, VertexFormat fmt, int count, int lockFlags) { + IDirect3DVertexBuffer9* buffer = (IDirect3DVertexBuffer9*)vb; void* dst = NULL; - cc_result res = IDirect3DIndexBuffer9_Lock(buffer, 0, size, &dst, 0); - if (res) Logger_Abort2(res, "D3D9_LockIb"); + int size = count * gfx_strideSizes[fmt]; - Mem_Copy(dst, data, size); - res = IDirect3DIndexBuffer9_Unlock(buffer); - if (res) Logger_Abort2(res, "D3D9_UnlockIb"); + cc_result res = IDirect3DVertexBuffer9_Lock(buffer, 0, size, &dst, lockFlags); + if (res) Logger_Abort2(res, "D3D9_LockVb"); + return dst; } -GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { - int size = indicesCount * 2; - IDirect3DIndexBuffer9* ibuffer; - cc_result res = IDirect3DDevice9_CreateIndexBuffer(device, size, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ibuffer, NULL); - if (res) Logger_Abort2(res, "D3D9_CreateIb"); - - D3D9_SetIbData(ibuffer, indices, size); - return ibuffer; +GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { + return D3D9_AllocVertexBuffer(fmt, count, D3DUSAGE_WRITEONLY); } void Gfx_BindVb(GfxResourceID vb) { @@ -739,14 +751,17 @@ void Gfx_BindVb(GfxResourceID vb) { if (res) Logger_Abort2(res, "D3D9_BindVb"); } -void Gfx_BindIb(GfxResourceID ib) { - IDirect3DIndexBuffer9* ibuffer = (IDirect3DIndexBuffer9*)ib; - cc_result res = IDirect3DDevice9_SetIndices(device, ibuffer); - if (res) Logger_Abort2(res, "D3D9_BindIb"); +void Gfx_DeleteVb(GfxResourceID* vb) { D3D9_FreeResource(vb); } +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + return D3D9_LockVb(vb, fmt, count, 0); +} + +void Gfx_UnlockVb(GfxResourceID vb) { + IDirect3DVertexBuffer9* buffer = (IDirect3DVertexBuffer9*)vb; + cc_result res = IDirect3DVertexBuffer9_Unlock(buffer); + if (res) Logger_Abort2(res, "Gfx_UnlockVb"); } -void Gfx_DeleteVb(GfxResourceID* vb) { D3D9_FreeResource(vb); } -void Gfx_DeleteIb(GfxResourceID* ib) { D3D9_FreeResource(ib); } void Gfx_SetVertexFormat(VertexFormat fmt) { if (fmt == gfx_batchFormat) return; @@ -757,15 +772,6 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { gfx_batchStride = gfx_strideSizes[fmt]; } -void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { - int size = vCount * gfx_batchStride; - IDirect3DVertexBuffer9* vbuffer = (IDirect3DVertexBuffer9*)vb; - D3D9_SetVbData(vbuffer, vertices, size, D3DLOCK_DISCARD); - - cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, vbuffer, 0, gfx_batchStride); - if (res) Logger_Abort2(res, "D3D9_SetDynamicVbData - Bind"); -} - void Gfx_DrawVb_Lines(int verticesCount) { /* NOTE: Skip checking return result for Gfx_DrawXYZ for performance */ IDirect3DDevice9_DrawPrimitive(device, D3DPT_LINELIST, 0, verticesCount >> 1); @@ -787,6 +793,33 @@ void Gfx_DrawIndexedVb_TrisT2fC4b(int verticesCount, int startVertex) { } +/*########################################################################################################################* +*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { + if (Gfx.LostContext) return 0; + return D3D9_AllocVertexBuffer(fmt, maxVertices, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY); +} + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return D3D9_LockVb(vb, fmt, count, D3DLOCK_DISCARD); +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + Gfx_UnlockVb(vb); + Gfx_BindVb(vb); /* TODO: Inline this? */ +} + +void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { + int size = vCount * gfx_batchStride; + IDirect3DVertexBuffer9* buffer = (IDirect3DVertexBuffer9*)vb; + D3D9_SetVbData(buffer, vertices, size, D3DLOCK_DISCARD); + + cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, gfx_batchStride); + if (res) Logger_Abort2(res, "D3D9_SetDynamicVbData - Bind"); +} + + /*########################################################################################################################* *---------------------------------------------------------Matrices--------------------------------------------------------* *#########################################################################################################################*/ @@ -953,9 +986,9 @@ void Gfx_OnWindowResize(void) { Gfx_LoseContext(" (resizing window)"); } #endif #if defined CC_BUILD_GL11 -static GLuint gfx_activeList; +static GLuint activeList; #define gl_DYNAMICLISTID 1234567891 -static void* gfx_dynamicListData; +static void* dynamicListData; static cc_uint16 gl_indices[GFX_MAX_INDICES]; #elif defined CC_BUILD_GLMODERN #define _glBindBuffer(t,b) glBindBuffer(t,b) @@ -1035,6 +1068,18 @@ void Gfx_Free(void) { } #define gl_Toggle(cap) if (enabled) { glEnable(cap); } else { glDisable(cap); } +static void* tmpData; +static int tmpSize; + +static void* FastAllocTempMem(int size) { + if (size > tmpSize) { + Mem_Free(tmpData); + tmpData = Mem_Alloc(size, 1, "Gfx_AllocTempMemory"); + } + + tmpSize = size; + return tmpData; +} /*########################################################################################################################* @@ -1149,7 +1194,7 @@ void Gfx_CalcPerspectiveMatrix(float fov, float aspect, float zNear, float zFar, /*########################################################################################################################* -*---------------------------------------------------Vertex/Index buffers--------------------------------------------------* +*-------------------------------------------------------Index buffers-----------------------------------------------------* *#########################################################################################################################*/ #ifndef CC_BUILD_GL11 static GLuint GL_GenAndBind(GLenum target) { @@ -1159,24 +1204,6 @@ static GLuint GL_GenAndBind(GLenum target) { return id; } -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - GLuint id; - cc_uint32 size; - if (Gfx.LostContext) return 0; - - id = GL_GenAndBind(GL_ARRAY_BUFFER); - size = maxVertices * gfx_strideSizes[fmt]; - _glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); - return id; -} - -GfxResourceID Gfx_CreateVb(void* vertices, VertexFormat fmt, int count) { - GLuint id = GL_GenAndBind(GL_ARRAY_BUFFER); - cc_uint32 size = count * gfx_strideSizes[fmt]; - _glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_STATIC_DRAW); - return id; -} - GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { GLuint id = GL_GenAndBind(GL_ELEMENT_ARRAY_BUFFER); cc_uint32 size = indicesCount * 2; @@ -1184,9 +1211,31 @@ GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { return id; } -void Gfx_BindVb(GfxResourceID vb) { _glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); } void Gfx_BindIb(GfxResourceID ib) { _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)ib); } +void Gfx_DeleteIb(GfxResourceID* ib) { + GLuint id = (GLuint)(*ib); + if (!id) return; + _glDeleteBuffers(1, &id); + *ib = 0; +} +#else +GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { return 0; } +void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_DeleteIb(GfxResourceID* ib) { } +#endif + + +/*########################################################################################################################* +*------------------------------------------------------Vertex buffers-----------------------------------------------------* +*#########################################################################################################################*/ +#ifndef CC_BUILD_GL11 +GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { + return GL_GenAndBind(GL_ARRAY_BUFFER); +} + +void Gfx_BindVb(GfxResourceID vb) { _glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); } + void Gfx_DeleteVb(GfxResourceID* vb) { GLuint id = (GLuint)(*vb); if (!id) return; @@ -1194,11 +1243,83 @@ void Gfx_DeleteVb(GfxResourceID* vb) { *vb = 0; } -void Gfx_DeleteIb(GfxResourceID* ib) { - GLuint id = (GLuint)(*ib); - if (!id) return; - _glDeleteBuffers(1, &id); - *ib = 0; +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + return FastAllocTempMem(count * gfx_strideSizes[fmt]); +} + +void Gfx_UnlockVb(GfxResourceID vb) { + _glBufferData(GL_ARRAY_BUFFER, tmpSize, tmpData, GL_STATIC_DRAW); +} +#else +static void UpdateDisplayList(GLuint list, void* vertices, VertexFormat fmt, int count) { + /* We need to restore client state afer building the list */ + int curFormat = gfx_batchFormat; + void* dyn_data = dynamicListData; + Gfx_SetVertexFormat(fmt); + dynamicListData = vertices; + + glNewList(list, GL_COMPILE); + gfx_setupVBFunc(); + glDrawElements(GL_TRIANGLES, ICOUNT(count), GL_UNSIGNED_SHORT, gl_indices); + glEndList(); + + Gfx_SetVertexFormat(curFormat); + dynamicListData = dyn_data; +} + +GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { return glGenLists(1); } +void Gfx_BindVb(GfxResourceID vb) { activeList = (GLuint)vb; } + +void Gfx_DeleteVb(GfxResourceID* vb) { + GLuint id = (GLuint)(*vb); + if (id) glDeleteLists(id, 1); + *vb = 0; +} + +/* NOTE! Building chunk in Builder.c relies on vb being ignored */ +/* If that changes, you must fix Builder.c to properly call Gfx_LockVb */ +static VertexFormat tmpFormat; +static int tmpCount; +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + tmpFormat = fmt; + tmpCount = count; + return FastAllocTempMem(count * gfx_strideSizes[fmt]); +} + +void Gfx_UnlockVb(GfxResourceID vb) { + UpdateDisplayList((GLuint)vb, tmpData, tmpFormat, tmpCount); +} + +GfxResourceID Gfx_CreateVb2(void* vertices, VertexFormat fmt, int count) { + GLuint list = glGenLists(1); + UpdateDisplayList(list, vertices, fmt, count); + return list; +} +#endif + + +/*########################################################################################################################* +*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------* +*#########################################################################################################################*/ +#ifndef CC_BUILD_GL11 +GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { + GLuint id; + cc_uint32 size; + if (Gfx.LostContext) return 0; + + id = GL_GenAndBind(GL_ARRAY_BUFFER); + size = maxVertices * gfx_strideSizes[fmt]; + _glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); + return id; +} + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return FastAllocTempMem(count * gfx_strideSizes[fmt]); +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + _glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); + _glBufferSubData(GL_ARRAY_BUFFER, 0, tmpSize, tmpData); } void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { @@ -1206,6 +1327,29 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { _glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); _glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices); } +#else +GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { + return (GfxResourceID)Mem_Alloc(maxVertices, gfx_strideSizes[fmt], "creating dynamic vb"); +} + +void Gfx_BindDynamicVb(GfxResourceID vb) { + activeList = gl_DYNAMICLISTID; + dynamicListData = (void*)vb; +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { + cc_uintptr id = (cc_uintptr)(*vb); + if (id) Mem_Free((void*)id); + *vb = 0; +} + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return (void*)vb; } +void Gfx_UnlockDynamicVb(GfxResourceID vb) { Gfx_BindDynamicVb(vb); } + +void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { + Gfx_BindDynamicVb(vb); + Mem_Copy((void*)vb, vertices, vCount * gfx_batchStride); +} #endif @@ -1776,7 +1920,7 @@ cc_bool Gfx_WarnIfNecessary(void) { *#########################################################################################################################*/ #ifdef CC_BUILD_GL11 /* point to client side dynamic array */ -#define VB_PTR ((cc_uint8*)gfx_dynamicListData) +#define VB_PTR ((cc_uint8*)dynamicListData) #define IB_PTR gl_indices #else /* no client side array, use vertex buffer object */ @@ -1831,7 +1975,7 @@ void Gfx_DrawVb_Lines(int verticesCount) { void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { #ifdef CC_BUILD_GL11 - if (gfx_activeList != gl_DYNAMICLISTID) { glCallList(gfx_activeList); return; } + if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; } #endif gfx_setupVBRangeFunc(startVertex); glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); @@ -1839,7 +1983,7 @@ void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { void Gfx_DrawVb_IndexedTris(int verticesCount) { #ifdef CC_BUILD_GL11 - if (gfx_activeList != gl_DYNAMICLISTID) { glCallList(gfx_activeList); return; } + if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; } #endif gfx_setupVBFunc(); glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR); @@ -1882,56 +2026,6 @@ static void GL_CheckSupport(void) { Gfx.CustomMipmapsLevels = true; } #else -GfxResourceID Gfx_CreateVb(void* vertices, VertexFormat fmt, int count) { - GLuint list = glGenLists(1); - - /* We need to restore client state afer building the list */ - int curFormat = gfx_batchFormat; - void* dyn_data = gfx_dynamicListData; - Gfx_SetVertexFormat(fmt); - gfx_dynamicListData = vertices; - - glNewList(list, GL_COMPILE); - gfx_setupVBFunc(); - glDrawElements(GL_TRIANGLES, ICOUNT(count), GL_UNSIGNED_SHORT, gl_indices); - glEndList(); - - Gfx_SetVertexFormat(curFormat); - gfx_dynamicListData = dyn_data; - return list; -} - -GfxResourceID Gfx_CreateIb(void* indices, int indicesCount) { return 0; } -void Gfx_BindVb(GfxResourceID vb) { gfx_activeList = (GLuint)vb; } -void Gfx_BindIb(GfxResourceID ib) { } -void Gfx_DeleteIb(GfxResourceID* ib) { } - -void Gfx_DeleteVb(GfxResourceID* vb) { - GLuint id = (GLuint)(*vb); - if (id) glDeleteLists(id, 1); - *vb = 0; -} - -GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { - return (GfxResourceID)Mem_Alloc(maxVertices, gfx_strideSizes[fmt], "creating dynamic vb"); -} - -void Gfx_BindDynamicVb(GfxResourceID vb) { - gfx_activeList = gl_DYNAMICLISTID; - gfx_dynamicListData = (void*)vb; -} - -void Gfx_DeleteDynamicVb(GfxResourceID* vb) { - cc_uintptr id = (cc_uintptr)(*vb); - if (id) Mem_Free((void*)id); - *vb = 0; -} - -void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { - Gfx_BindDynamicVb(vb); - Mem_Copy((void*)vb, vertices, vCount * gfx_batchStride); -} - void Gfx_DrawIndexedVb_TrisT2fC4b(int list, int ignored) { glCallList(list); } static void GL_CheckSupport(void) { diff --git a/src/Graphics.h b/src/Graphics.h index d4d90ce73..03e80976a 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -62,7 +62,7 @@ CC_API void Gfx_SetTexturing(cc_bool enabled); /* Turns on mipmapping. (if Gfx_Mipmaps is enabled) */ /* NOTE: You must have created textures with mipmaps true for this to work. */ CC_API void Gfx_EnableMipmaps(void); -/* Turns off mipmapping. (if GfX_Mipmaps is enabled) */ +/* Turns off mipmapping. (if Gfx_Mipmaps is enabled) */ /* NOTE: You must have created textures with mipmaps true for this to work. */ CC_API void Gfx_DisableMipmaps(void); @@ -99,21 +99,32 @@ CC_API void Gfx_SetColWriteMask(cc_bool r, cc_bool g, cc_bool b, cc_bool a); /* Sets whether z/depth of pixels is actually written to the depth buffer. */ CC_API void Gfx_SetDepthWrite(cc_bool enabled); -/* Creates a new dynamic vertex buffer, whose contents can be updated later. */ -CC_API GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices); -/* Creates a new vertex buffer and fills out its contents. */ -CC_API GfxResourceID Gfx_CreateVb(void* vertices, VertexFormat fmt, int count); /* Creates a new index buffer and fills out its contents. */ CC_API GfxResourceID Gfx_CreateIb(void* indices, int indicesCount); -/* Sets the currently active vertex buffer. */ -CC_API void Gfx_BindVb(GfxResourceID vb); /* Sets the currently active index buffer. */ CC_API void Gfx_BindIb(GfxResourceID ib); -/* Deletes the given vertex buffer, then sets it to 0. */ -CC_API void Gfx_DeleteVb(GfxResourceID* vb); /* Deletes the given index buffer, then sets it to 0. */ CC_API void Gfx_DeleteIb(GfxResourceID* ib); +/* Creates a new vertex buffer. */ +CC_API GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count); +/* Sets the currently active vertex buffer. */ +CC_API void Gfx_BindVb(GfxResourceID vb); +/* Deletes the given vertex buffer, then sets it to 0. */ +CC_API void Gfx_DeleteVb(GfxResourceID* vb); +/* Acquires temp memory for changing the contents of a vertex buffer. */ +CC_API void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count); +/* Submits the changed contents of a vertex buffer. */ +CC_API void Gfx_UnlockVb(GfxResourceID vb); +/* TODO: How to make LockDynamicVb work with OpenGL 1.1 Builder stupidity.. */ +/* TODO: Cleanup the D3D9 Init and remove the if (i == count) stuff. */ +#ifdef CC_BUILD_GL11 +/* Special case of Gfx_Create/LockVb for building chunks in Builder.c */ +GfxResourceID Gfx_CreateVb2(void* vertices, VertexFormat fmt, int count); +#endif + +/* Creates a new dynamic vertex buffer, whose contents can be updated later. */ +CC_API GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices); #ifndef CC_BUILD_GL11 /* Static and dynamic vertex buffers are drawn in the same way */ #define Gfx_BindDynamicVb Gfx_BindVb @@ -123,6 +134,10 @@ CC_API void Gfx_DeleteIb(GfxResourceID* ib); void Gfx_BindDynamicVb(GfxResourceID vb); void Gfx_DeleteDynamicVb(GfxResourceID* vb); #endif +/* Acquires temp memory for changing the contents of a dynamic vertex buffer. */ +CC_API void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count); +/* Binds then submits the changed contents of a dynamic vertex buffer. */ +CC_API void Gfx_UnlockDynamicVb(GfxResourceID vb); /* Sets the format of the rendered vertices. */ CC_API void Gfx_SetVertexFormat(VertexFormat fmt); @@ -172,12 +187,11 @@ void Gfx_LoseContext(const char* reason); /* Attempts to restore a lost context. Raises ContextRecreated event on success. */ cc_bool Gfx_TryRestoreContext(void); -/* Binds and draws the specified subset of the vertices in the current dynamic vertex buffer. */ -/* NOTE: This replaces the dynamic vertex buffer's data first with the given vertices before drawing. */ -void Gfx_UpdateDynamicVb_Lines(GfxResourceID vb, void* vertices, int vCount); /* Binds and draws the specified subset of the vertices in the current dynamic vertex buffer. */ /* NOTE: This replaces the dynamic vertex buffer's data first with the given vertices before drawing. */ void Gfx_UpdateDynamicVb_IndexedTris(GfxResourceID vb, void* vertices, int vCount); +/* Shorthand for Gfx_CreateVb followed by Gfx_LockVb */ +void* Gfx_CreateAndLockVb(VertexFormat fmt, int count, GfxResourceID* vb); /* Renders a 2D flat coloured rectangle. */ void Gfx_Draw2DFlat(int x, int y, int width, int height, PackedCol col); diff --git a/src/Gui.h b/src/Gui.h index ba370db0c..5fd8eee37 100644 --- a/src/Gui.h +++ b/src/Gui.h @@ -74,7 +74,7 @@ struct ScreenVTABLE { cc_bool blocksWorld; /* Whether this screen completely and opaquely covers the game world behind it. */ \ cc_bool closable; /* Whether this screen is automatically closed when pressing Escape */ \ cc_bool dirty; /* Whether this screens needs to have its mesh rebuilt. */ \ - GfxResourceID vb; struct Widget** widgets; int numWidgets; + int maxVertices; GfxResourceID vb; struct Widget** widgets; int numWidgets; /* Represents a container of widgets and other 2D elements. May cover entire window. */ struct Screen { Screen_Body }; diff --git a/src/Menus.c b/src/Menus.c index 1c58015da..89c7e712e 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -74,6 +74,12 @@ static void Menu_Input(void* s, int i, struct MenuInputWidget* input, int width, ((struct Screen*)s)->widgets[i] = (struct Widget*)input; } +static void Menu_MakeInput(struct MenuInputWidget* input, int width, const String* text, struct MenuInputDesc* desc, int horAnchor, int verAnchor, int x, int y) { + MenuInputWidget_Create(input, width, 30, text, desc); + Widget_SetLocation(input, horAnchor, verAnchor, x, y); + input->base.showCaret = true; +} + static void Menu_Back(void* s, int i, struct ButtonWidget* btn, Widget_LeftClick onClick) { int width = Gui_ClassicMenu ? 400 : 200; Menu_Button(s, i, btn, width, onClick, ANCHOR_CENTRE, ANCHOR_MAX, 0, 25); @@ -240,10 +246,10 @@ static struct Widget* list_widgets[10] = { (struct Widget*)&ListScreen.page, (struct Widget*)&ListScreen.done }; #define LIST_MAX_VERTICES (8 * BUTTONWIDGET_MAX + 2 * TEXTWIDGET_MAX) -#define LIST_SCREEN_EMPTY "-----" +#define LISTSCREEN_EMPTY "-----" static STRING_REF String ListScreen_UNSAFE_Get(struct ListScreen* s, int index) { - static const String str = String_FromConst(LIST_SCREEN_EMPTY); + static const String str = String_FromConst(LISTSCREEN_EMPTY); if (index >= 0 && index < s->entries.count) { return StringsBuffer_UNSAFE_Get(&s->entries, index); @@ -376,6 +382,7 @@ static void ListScreen_Init(void* screen) { s->numWidgets = Array_Elems(list_widgets); s->wheelAcc = 0.0f; s->currentIndex = 0; + s->maxVertices = LIST_MAX_VERTICES; for (i = 0; i < LIST_SCREEN_ITEMS; i++) { ButtonWidget_Make(&s->btns[i], 300, s->EntryClick, @@ -414,7 +421,7 @@ static void ListScreen_ContextLost(void* screen) { static void ListScreen_ContextRecreated(void* screen) { struct ListScreen* s = (struct ListScreen*)screen; - s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, LIST_MAX_VERTICES); + Screen_CreateVb(screen); Menu_MakeTitleFont(&s->font); ListScreen_RedrawEntries(s); @@ -425,26 +432,18 @@ static void ListScreen_ContextRecreated(void* screen) { ListScreen_UpdatePage(s); } -static void ListScreen_BuildMesh(void* screen) { - struct Screen* s = (struct Screen*)screen; - VertexP3fT2fC4b vertices[LIST_MAX_VERTICES]; - - Screen_BuildMesh(screen, vertices); - Gfx_SetDynamicVbData(s->vb, vertices, LIST_MAX_VERTICES); -} - static const struct ScreenVTABLE ListScreen_VTABLE = { ListScreen_Init, Screen_NullUpdate, ListScreen_Free, - ListScreen_Render, ListScreen_BuildMesh, + ListScreen_Render, Screen_BuildMesh, ListScreen_KeyDown, Screen_TInput, Screen_TKeyPress, Screen_TText, Menu_PointerDown, Screen_TPointer, Menu_PointerMove, ListScreen_MouseScroll, Screen_Layout, ListScreen_ContextLost, ListScreen_ContextRecreated }; void ListScreen_Show(void) { struct ListScreen* s = &ListScreen; - s->grabsInput = true; - s->closable = true; - s->VTABLE = &ListScreen_VTABLE; + s->grabsInput = true; + s->closable = true; + s->VTABLE = &ListScreen_VTABLE; Gui_Replace((struct Screen*)s, GUI_PRIORITY_MENU); } @@ -627,7 +626,7 @@ static void OptionsGroupScreen_ContextLost(void* screen) { static void OptionsGroupScreen_ContextRecreated(void* screen) { struct OptionsGroupScreen* s = (struct OptionsGroupScreen*)screen; struct FontDesc titleFont; - s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, OPTGROUPS_MAX_VERTICES); + Screen_CreateVb(screen); Menu_MakeTitleFont(&titleFont); Menu_MakeBodyFont(&s->textFont); @@ -640,21 +639,14 @@ static void OptionsGroupScreen_ContextRecreated(void* screen) { Font_Free(&titleFont); } -static void OptionsGroupScreen_BuildMesh(void* screen) { - struct Screen* s = (struct Screen*)screen; - VertexP3fT2fC4b vertices[OPTGROUPS_MAX_VERTICES]; - - Screen_BuildMesh(screen, vertices); - Gfx_SetDynamicVbData(s->vb, vertices, OPTGROUPS_MAX_VERTICES); -} - static void OptionsGroupScreen_Init(void* screen) { struct OptionsGroupScreen* s = (struct OptionsGroupScreen*)screen; Event_RegisterVoid(&UserEvents.HackPermissionsChanged, s, OptionsGroupScreen_CheckHacksAllowed); - s->widgets = optGroups_widgets; - s->numWidgets = Array_Elems(optGroups_widgets); - s->selectedI = -1; + s->widgets = optGroups_widgets; + s->numWidgets = Array_Elems(optGroups_widgets); + s->selectedI = -1; + s->maxVertices = OPTGROUPS_MAX_VERTICES; Menu_Buttons(s, s->btns, 300, optsGroup_btns, 7); TextWidget_Make(&s->desc, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 100); @@ -679,7 +671,7 @@ static int OptionsGroupScreen_PointerMove(void* screen, int id, int x, int y) { static const struct ScreenVTABLE OptionsGroupScreen_VTABLE = { OptionsGroupScreen_Init, Screen_NullUpdate, OptionsGroupScreen_Free, - MenuScreen_Render2, OptionsGroupScreen_BuildMesh, + MenuScreen_Render2, Screen_BuildMesh, Screen_InputDown, Screen_TInput, Screen_TKeyPress, Screen_TText, Menu_PointerDown, Screen_TPointer, OptionsGroupScreen_PointerMove, Screen_TMouseScroll, Screen_Layout, OptionsGroupScreen_ContextLost, OptionsGroupScreen_ContextRecreated @@ -704,10 +696,18 @@ static struct EditHotkeyScreen { struct FontDesc titleFont, textFont; struct MenuInputWidget input; struct ButtonWidget btns[5], cancel; -} EditHotkeyScreen_Instance; +} EditHotkeyScreen; + +static struct Widget* edithotkey_widgets[7] = { + (struct Widget*)&EditHotkeyScreen.btns[0], (struct Widget*)&EditHotkeyScreen.btns[1], + (struct Widget*)&EditHotkeyScreen.btns[2], (struct Widget*)&EditHotkeyScreen.btns[3], + (struct Widget*)&EditHotkeyScreen.btns[4], (struct Widget*)&EditHotkeyScreen.input, + (struct Widget*)&EditHotkeyScreen.cancel +}; +#define EDITHOTKEY_MAX_VERTICES (MENUINPUTWIDGET_MAX + 6 * BUTTONWIDGET_MAX) -static void EditHotkeyScreen_Make(struct EditHotkeyScreen* s, int i, int x, int y, Widget_LeftClick onClick) { - Menu_Button(s, i, &s->btns[i], 300, onClick, ANCHOR_CENTRE, ANCHOR_CENTRE, x, y); +static void EditHotkeyScreen_Make(struct ButtonWidget* btn, int x, int y, Widget_LeftClick onClick) { + ButtonWidget_Make(btn, 300, onClick, ANCHOR_CENTRE, ANCHOR_CENTRE, x, y); } static void HotkeyListScreen_MakeFlags(int flags, String* str); @@ -811,7 +811,7 @@ static void EditHotkeyScreen_RemoveHotkey(void* screen, void* b) { static void EditHotkeyScreen_Render(void* screen, double delta) { PackedCol grey = PackedCol_Make(150, 150, 150, 255); int x, y; - MenuScreen_Render(screen, delta); + MenuScreen_Render2(screen, delta); x = Window_Width / 2; y = Window_Height / 2; Gfx_Draw2DFlat(x - 250, y - 65, 500, 2, grey); @@ -871,6 +871,8 @@ static void EditHotkeyScreen_ContextRecreated(void* screen) { Menu_MakeTitleFont(&s->titleFont); Menu_MakeBodyFont(&s->textFont); + Screen_CreateVb(screen); + EditHotkeyScreen_UpdateBaseKey(s); EditHotkeyScreen_UpdateModifiers(s); EditHotkeyScreen_UpdateLeaveOpen(s); @@ -881,45 +883,48 @@ static void EditHotkeyScreen_ContextRecreated(void* screen) { ButtonWidget_SetConst(&s->cancel, "Cancel", &s->titleFont); } -static void EditHotkeyScreen_BuildMesh(void* screen) { } +static void EditHotkeyScreen_Update(void* screen, double delta) { + struct EditHotkeyScreen* s = (struct EditHotkeyScreen*)screen; + s->input.base.caretAccumulator += delta; +} static void EditHotkeyScreen_Init(void* screen) { - static struct Widget* widgets[7]; struct EditHotkeyScreen* s = (struct EditHotkeyScreen*)screen; struct MenuInputDesc desc; String text; - s->widgets = widgets; - s->numWidgets = Array_Elems(widgets); - s->selectedI = -1; + s->widgets = edithotkey_widgets; + s->numWidgets = Array_Elems(edithotkey_widgets); + s->selectedI = -1; + s->maxVertices = EDITHOTKEY_MAX_VERTICES; MenuInput_String(desc); - EditHotkeyScreen_Make(s, 0, 0, -150, EditHotkeyScreen_BaseKey); - EditHotkeyScreen_Make(s, 1, 0, -100, EditHotkeyScreen_Modifiers); - EditHotkeyScreen_Make(s, 2, -100, 10, EditHotkeyScreen_LeaveOpen); - EditHotkeyScreen_Make(s, 3, 0, 80, EditHotkeyScreen_SaveChanges); - EditHotkeyScreen_Make(s, 4, 0, 130, EditHotkeyScreen_RemoveHotkey); + EditHotkeyScreen_Make(&s->btns[0], 0, -150, EditHotkeyScreen_BaseKey); + EditHotkeyScreen_Make(&s->btns[1], 0, -100, EditHotkeyScreen_Modifiers); + EditHotkeyScreen_Make(&s->btns[2], -100, 10, EditHotkeyScreen_LeaveOpen); + EditHotkeyScreen_Make(&s->btns[3], 0, 80, EditHotkeyScreen_SaveChanges); + EditHotkeyScreen_Make(&s->btns[4], 0, 130, EditHotkeyScreen_RemoveHotkey); if (s->origHotkey.Trigger) { text = StringsBuffer_UNSAFE_Get(&HotkeysText, s->origHotkey.TextIndex); } else { text = String_Empty; } - Menu_Input(s, 6, &s->input, 500, &text, &desc, + Menu_MakeInput(&s->input, 500, &text, &desc, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -35); - Menu_Back(s, 5, &s->cancel, Menu_SwitchHotkeys); + Menu_MakeBack( &s->cancel, Menu_SwitchHotkeys); Window_OpenKeyboard(); Window_SetKeyboardText(&text); } static const struct ScreenVTABLE EditHotkeyScreen_VTABLE = { - EditHotkeyScreen_Init, Screen_NullUpdate, Menu_CloseKeyboard, - EditHotkeyScreen_Render, EditHotkeyScreen_BuildMesh, + EditHotkeyScreen_Init, EditHotkeyScreen_Update, Menu_CloseKeyboard, + EditHotkeyScreen_Render, Screen_BuildMesh, EditHotkeyScreen_KeyDown, Screen_TInput, EditHotkeyScreen_KeyPress, EditHotkeyScreen_TextChanged, Menu_PointerDown, Screen_TPointer, Menu_PointerMove, Screen_TMouseScroll, Screen_Layout, EditHotkeyScreen_ContextLost, EditHotkeyScreen_ContextRecreated }; void EditHotkeyScreen_Show(struct HotkeyData original) { - struct EditHotkeyScreen* s = &EditHotkeyScreen_Instance; + struct EditHotkeyScreen* s = &EditHotkeyScreen; s->grabsInput = true; s->closable = true; s->VTABLE = &EditHotkeyScreen_VTABLE; @@ -939,7 +944,17 @@ static struct GenLevelScreen { struct MenuInputWidget* selected; struct MenuInputWidget inputs[4]; struct TextWidget labels[4], title; -} GenLevelScreen_Instance; +} GenLevelScreen; + +static struct Widget* gen_widgets[12] = { + (struct Widget*)&GenLevelScreen.inputs[0], (struct Widget*)&GenLevelScreen.inputs[1], + (struct Widget*)&GenLevelScreen.inputs[2], (struct Widget*)&GenLevelScreen.inputs[3], + (struct Widget*)&GenLevelScreen.labels[0], (struct Widget*)&GenLevelScreen.labels[1], + (struct Widget*)&GenLevelScreen.labels[2], (struct Widget*)&GenLevelScreen.labels[3], + (struct Widget*)&GenLevelScreen.title, (struct Widget*)&GenLevelScreen.flatgrass, + (struct Widget*)&GenLevelScreen.vanilla, (struct Widget*)&GenLevelScreen.cancel +}; +#define GEN_MAX_VERTICES (3 * BUTTONWIDGET_MAX + 4 * MENUINPUTWIDGET_MAX + 5 * TEXTWIDGET_MAX) CC_NOINLINE static int GenLevelScreen_GetInt(struct GenLevelScreen* s, int index) { struct MenuInputWidget* input = &s->inputs[index]; @@ -988,7 +1003,6 @@ static void GenLevelScreen_Notchy(void* a, void* b) { GenLevelScreen_Gen(a, t static void GenLevelScreen_Make(struct GenLevelScreen* s, int i, int y, int def) { String tmp; char tmpBuffer[STRING_SIZE]; struct MenuInputDesc desc; - PackedCol col = PackedCol_Make(224, 224, 224, 255); if (i == 3) { MenuInput_Seed(desc); @@ -999,13 +1013,13 @@ static void GenLevelScreen_Make(struct GenLevelScreen* s, int i, int y, int def) String_InitArray(tmp, tmpBuffer); desc.VTABLE->GetDefault(&desc, &tmp); - Menu_Input(s, i, &s->inputs[i], 200, &tmp, &desc, + Menu_MakeInput(&s->inputs[i], 200, &tmp, &desc, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, y); s->inputs[i].base.showCaret = false; - Menu_Label(s, i + 4, &s->labels[i], + TextWidget_Make(&s->labels[i], ANCHOR_CENTRE_MAX, ANCHOR_CENTRE, 110, y); - s->labels[i].col = col; + s->labels[i].col = PackedCol_Make(224, 224, 224, 255); } static int GenLevelScreen_KeyDown(void* screen, int key) { @@ -1051,6 +1065,7 @@ static void GenLevelScreen_ContextRecreated(void* screen) { struct FontDesc titleFont; Menu_MakeTitleFont(&titleFont); Menu_MakeBodyFont(&s->textFont); + Screen_CreateVb(screen); MenuInputWidget_SetFont(&s->inputs[0], &s->textFont); MenuInputWidget_SetFont(&s->inputs[1], &s->textFont); @@ -1069,39 +1084,42 @@ static void GenLevelScreen_ContextRecreated(void* screen) { Font_Free(&titleFont); } -static void GenLevelScreen_BuildMesh(void* screen) { } +static void GenLevelScreen_Update(void* screen, double delta) { + struct GenLevelScreen* s = (struct GenLevelScreen*)screen; + if (s->selected) s->selected->base.caretAccumulator += delta; +} static void GenLevelScreen_Init(void* screen) { - static struct Widget* widgets[12]; struct GenLevelScreen* s = (struct GenLevelScreen*)screen; - s->widgets = widgets; - s->numWidgets = Array_Elems(widgets); - s->selected = NULL; + s->widgets = gen_widgets; + s->numWidgets = Array_Elems(gen_widgets); + s->selected = NULL; + s->maxVertices = GEN_MAX_VERTICES; GenLevelScreen_Make(s, 0, -80, World.Width); GenLevelScreen_Make(s, 1, -40, World.Height); GenLevelScreen_Make(s, 2, 0, World.Length); GenLevelScreen_Make(s, 3, 40, 0); - Menu_Label(s, 8, &s->title, + TextWidget_Make( &s->title, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -130); - Menu_Button(s, 9, &s->flatgrass, 200, GenLevelScreen_Flatgrass, + ButtonWidget_Make(&s->flatgrass, 200, GenLevelScreen_Flatgrass, ANCHOR_CENTRE, ANCHOR_CENTRE, -120, 100); - Menu_Button(s, 10, &s->vanilla, 200, GenLevelScreen_Notchy, + ButtonWidget_Make(&s->vanilla, 200, GenLevelScreen_Notchy, ANCHOR_CENTRE, ANCHOR_CENTRE, 120, 100); - Menu_Back(s, 11, &s->cancel, Menu_SwitchPause); + Menu_MakeBack( &s->cancel, Menu_SwitchPause); Window_OpenKeyboard(); } static const struct ScreenVTABLE GenLevelScreen_VTABLE = { - GenLevelScreen_Init, Screen_NullUpdate, Menu_CloseKeyboard, - MenuScreen_Render, GenLevelScreen_BuildMesh, + GenLevelScreen_Init, GenLevelScreen_Update, Menu_CloseKeyboard, + MenuScreen_Render2, Screen_BuildMesh, GenLevelScreen_KeyDown, Screen_TInput, GenLevelScreen_KeyPress, GenLevelScreen_TextChanged, GenLevelScreen_PointerDown, Screen_TPointer, Menu_PointerMove, Screen_TMouseScroll, Screen_Layout, GenLevelScreen_ContextLost, GenLevelScreen_ContextRecreated }; void GenLevelScreen_Show(void) { - struct GenLevelScreen* s = &GenLevelScreen_Instance; + struct GenLevelScreen* s = &GenLevelScreen; s->grabsInput = true; s->closable = true; s->VTABLE = &GenLevelScreen_VTABLE; @@ -1139,7 +1157,7 @@ static void ClassicGenScreen_Huge(void* a, void* b) { ClassicGenScreen_Gen(512 static void ClassicGenScreen_ContextRecreated(void* screen) { struct ClassicGenScreen* s = (struct ClassicGenScreen*)screen; struct FontDesc titleFont; - s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, CLASSICGEN_MAX_VERTICES); + Screen_CreateVb(screen); Menu_MakeTitleFont(&titleFont); ButtonWidget_SetConst(&s->btns[0], "Small", &titleFont); @@ -1149,22 +1167,15 @@ static void ClassicGenScreen_ContextRecreated(void* screen) { Font_Free(&titleFont); } -static void ClassicGenScreen_BuildMesh(void* screen) { - struct Screen* s = (struct Screen*)screen; - VertexP3fT2fC4b vertices[CLASSICGEN_MAX_VERTICES]; - - Screen_BuildMesh(screen, vertices); - Gfx_SetDynamicVbData(s->vb, vertices, CLASSICGEN_MAX_VERTICES); -} - static void ClassicGenScreen_Make(struct ClassicGenScreen* s, int i, int y, Widget_LeftClick onClick) { ButtonWidget_Make(&s->btns[i], 400, onClick, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, y); } static void ClassicGenScreen_Init(void* screen) { struct ClassicGenScreen* s = (struct ClassicGenScreen*)screen; - s->widgets = classicgen_widgets; - s->numWidgets = Array_Elems(classicgen_widgets); + s->widgets = classicgen_widgets; + s->numWidgets = Array_Elems(classicgen_widgets); + s->maxVertices = CLASSICGEN_MAX_VERTICES; ClassicGenScreen_Make(s, 0, -100, ClassicGenScreen_Small); ClassicGenScreen_Make(s, 1, -50, ClassicGenScreen_Medium); @@ -1175,7 +1186,7 @@ static void ClassicGenScreen_Init(void* screen) { static const struct ScreenVTABLE ClassicGenScreen_VTABLE = { ClassicGenScreen_Init, Screen_NullUpdate, Screen_NullFunc, - MenuScreen_Render2, ClassicGenScreen_BuildMesh, + MenuScreen_Render2, Screen_BuildMesh, Screen_InputDown, Screen_TInput, Screen_TKeyPress, Screen_TText, Menu_PointerDown, Screen_TPointer, Menu_PointerMove, Screen_TMouseScroll, Screen_Layout, Screen_ContextLost, ClassicGenScreen_ContextRecreated @@ -1198,7 +1209,14 @@ static struct SaveLevelScreen { struct ButtonWidget save, alt, cancel; struct MenuInputWidget input; struct TextWidget mcEdit, desc; -} SaveLevelScreen_Instance; +} SaveLevelScreen; + +static struct Widget* save_widgets[6] = { + (struct Widget*)&SaveLevelScreen.save, (struct Widget*)&SaveLevelScreen.alt, + (struct Widget*)&SaveLevelScreen.mcEdit, (struct Widget*)&SaveLevelScreen.cancel, + (struct Widget*)&SaveLevelScreen.input, (struct Widget*)&SaveLevelScreen.desc, +}; +#define SAVE_MAX_VERTICES (3 * BUTTONWIDGET_MAX + MENUINPUTWIDGET_MAX + 2 * TEXTWIDGET_MAX) static void SaveLevelScreen_UpdateSave(struct SaveLevelScreen* s) { ButtonWidget_SetConst(&s->save, @@ -1358,7 +1376,7 @@ static void SaveLevelScreen_Alt(void* a, void* b) { SaveLevelScreen_Save(a, b, static void SaveLevelScreen_Render(void* screen, double delta) { PackedCol grey = PackedCol_Make(150, 150, 150, 255); int x, y; - MenuScreen_Render(screen, delta); + MenuScreen_Render2(screen, delta); #ifndef CC_BUILD_WEB x = Window_Width / 2; y = Window_Height / 2; @@ -1402,6 +1420,8 @@ static void SaveLevelScreen_ContextRecreated(void* screen) { struct SaveLevelScreen* s = (struct SaveLevelScreen*)screen; Menu_MakeTitleFont(&s->titleFont); Menu_MakeBodyFont(&s->textFont); + + Screen_CreateVb(screen); SaveLevelScreen_UpdateSave(s); SaveLevelScreen_UpdateAlt(s); @@ -1412,51 +1432,55 @@ static void SaveLevelScreen_ContextRecreated(void* screen) { ButtonWidget_SetConst(&s->cancel, "Cancel", &s->titleFont); } -static void SaveLevelScreen_BuildMesh(void* screen) { } +static void SaveLevelScreen_Update(void* screen, double delta) { + struct SaveLevelScreen* s = (struct SaveLevelScreen*)screen; + s->input.base.caretAccumulator += delta; +} static void SaveLevelScreen_Init(void* screen) { - static struct Widget* widgets[6]; struct SaveLevelScreen* s = (struct SaveLevelScreen*)screen; struct MenuInputDesc desc; - s->widgets = widgets; - s->numWidgets = Array_Elems(widgets); + s->widgets = save_widgets; + s->numWidgets = Array_Elems(save_widgets); + s->maxVertices = SAVE_MAX_VERTICES; MenuInput_Path(desc); - Menu_Button(s, 0, &s->save, 300, SaveLevelScreen_Main, + ButtonWidget_Make(&s->save, 300, SaveLevelScreen_Main, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 20); #ifdef CC_BUILD_WEB - Menu_Button(s, 1, &s->alt, 300, SaveLevelScreen_Alt, + ButtonWidget_Make(&s->alt, 300, SaveLevelScreen_Alt, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 70); + s->widgets[2] = NULL; /* null mcEdit widget */ #else - Menu_Button(s, 1, &s->alt, 200, SaveLevelScreen_Alt, + ButtonWidget_Make(&s->alt, 200, SaveLevelScreen_Alt, ANCHOR_CENTRE, ANCHOR_CENTRE, -150, 120); - Menu_Label(s, 2, &s->mcEdit, + TextWidget_Make( &s->mcEdit, ANCHOR_CENTRE, ANCHOR_CENTRE, 110, 120); #endif - Menu_Back(s, 3, &s->cancel, Menu_SwitchPause); - Menu_Input(s, 4, &s->input, 500, &String_Empty, &desc, + Menu_MakeBack( &s->cancel, Menu_SwitchPause); + Menu_MakeInput( &s->input, 500, &String_Empty, &desc, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, -30); #ifdef CC_BUILD_WEB - Menu_Label(s, 5, &s->desc, + TextWidget_Make( &s->desc, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 115); #else - Menu_Label(s, 5, &s->desc, + TextWidget_Make( &s->desc, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 65); #endif Window_OpenKeyboard(); } static const struct ScreenVTABLE SaveLevelScreen_VTABLE = { - SaveLevelScreen_Init, Screen_NullUpdate, Menu_CloseKeyboard, - SaveLevelScreen_Render, SaveLevelScreen_BuildMesh, - SaveLevelScreen_KeyDown, Screen_TInput, SaveLevelScreen_KeyPress, SaveLevelScreen_TextChanged, - Menu_PointerDown, Screen_TPointer, Menu_PointerMove, Screen_TMouseScroll, + SaveLevelScreen_Init, SaveLevelScreen_Update, Menu_CloseKeyboard, + SaveLevelScreen_Render, Screen_BuildMesh, + SaveLevelScreen_KeyDown, Screen_TInput, SaveLevelScreen_KeyPress, SaveLevelScreen_TextChanged, + Menu_PointerDown, Screen_TPointer, Menu_PointerMove, Screen_TMouseScroll, Screen_Layout, SaveLevelScreen_ContextLost, SaveLevelScreen_ContextRecreated }; void SaveLevelScreen_Show(void) { - struct SaveLevelScreen* s = &SaveLevelScreen_Instance; + struct SaveLevelScreen* s = &SaveLevelScreen; s->grabsInput = true; s->closable = true; s->VTABLE = &SaveLevelScreen_VTABLE; @@ -1515,7 +1539,7 @@ static void FontListScreen_EntryClick(void* screen, void* widget) { struct ListScreen* s = (struct ListScreen*)screen; String fontName = ListScreen_UNSAFE_GetCur(s, widget); - if (String_CaselessEqualsConst(&fontName, LIST_SCREEN_EMPTY)) return; + if (String_CaselessEqualsConst(&fontName, LISTSCREEN_EMPTY)) return; String_Copy(&Drawer2D_FontName, &fontName); Options_Set(OPT_FONT_NAME, &fontName); Event_RaiseVoid(&ChatEvents.FontChanged); @@ -1525,7 +1549,7 @@ static void FontListScreen_UpdateEntry(struct ListScreen* s, struct ButtonWidget struct FontDesc font; cc_result res; - if (String_CaselessEqualsConst(text, LIST_SCREEN_EMPTY)) { + if (String_CaselessEqualsConst(text, LISTSCREEN_EMPTY)) { ButtonWidget_Set(button, text, &s->font); return; } @@ -1572,7 +1596,7 @@ static void HotkeyListScreen_EntryClick(void* screen, void* widget) { int i, flags = 0; text = ListScreen_UNSAFE_GetCur(s, widget); - if (String_CaselessEqualsConst(&text, LIST_SCREEN_EMPTY)) { + if (String_CaselessEqualsConst(&text, LISTSCREEN_EMPTY)) { EditHotkeyScreen_Show(original); return; } @@ -1598,7 +1622,7 @@ static void HotkeyListScreen_MakeFlags(int flags, String* str) { } static void HotkeyListScreen_LoadEntries(struct ListScreen* s) { - static const String empty = String_FromConst(LIST_SCREEN_EMPTY); + static const String empty = String_FromConst(LISTSCREEN_EMPTY); String text; char textBuffer[STRING_SIZE]; struct HotkeyData hKey; int i; @@ -1641,7 +1665,7 @@ static void LoadLevelScreen_EntryClick(void* screen, void* widget) { String relPath; relPath = ListScreen_UNSAFE_GetCur(s, widget); - if (String_CaselessEqualsConst(&relPath, LIST_SCREEN_EMPTY)) return; + if (String_CaselessEqualsConst(&relPath, LISTSCREEN_EMPTY)) return; String_InitArray(path, pathBuffer); String_Format1(&path, "maps/%s", &relPath); @@ -3139,7 +3163,7 @@ static void UrlWarningOverlay_AppendUrl(void* screen, void* b) { static void UrlWarningOverlay_ContextRecreated(void* screen) { struct UrlWarningOverlay* s = (struct UrlWarningOverlay*)screen; struct FontDesc titleFont, textFont; - s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, URLWARNING_MAX_VERTICES); + Screen_CreateVb(screen); Menu_MakeTitleFont(&titleFont); Menu_MakeBodyFont(&textFont); @@ -3155,18 +3179,11 @@ static void UrlWarningOverlay_ContextRecreated(void* screen) { Font_Free(&textFont); } -static void UrlWarningOverlay_BuildMesh(void* screen) { - struct Screen* s = (struct Screen*)screen; - VertexP3fT2fC4b vertices[URLWARNING_MAX_VERTICES]; - - Screen_BuildMesh(screen, vertices); - Gfx_SetDynamicVbData(s->vb, vertices, URLWARNING_MAX_VERTICES); -} - static void UrlWarningOverlay_Init(void* screen) { struct UrlWarningOverlay* s = (struct UrlWarningOverlay*)screen; - s->widgets = urlwarning_widgets; - s->numWidgets = Array_Elems(urlwarning_widgets); + s->widgets = urlwarning_widgets; + s->numWidgets = Array_Elems(urlwarning_widgets); + s->maxVertices = URLWARNING_MAX_VERTICES; Overlay_MakeLabels(s->lbls); Overlay_MakeMainButtons(s->btns); @@ -3176,7 +3193,7 @@ static void UrlWarningOverlay_Init(void* screen) { static const struct ScreenVTABLE UrlWarningOverlay_VTABLE = { UrlWarningOverlay_Init, Screen_NullUpdate, Screen_NullFunc, - MenuScreen_Render2, UrlWarningOverlay_BuildMesh, + MenuScreen_Render2, Screen_BuildMesh, Screen_InputDown, Screen_TInput, Screen_TKeyPress, Screen_TText, Menu_PointerDown, Screen_TPointer, Menu_PointerMove, Screen_TMouseScroll, Screen_Layout, Screen_ContextLost, UrlWarningOverlay_ContextRecreated @@ -3295,7 +3312,7 @@ static void TexPackOverlay_ContextLost(void* screen) { static void TexPackOverlay_ContextRecreated(void* screen) { struct TexPackOverlay* s = (struct TexPackOverlay*)screen; struct FontDesc titleFont; - s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, TEXPACK_MAX_VERTICES); + Screen_CreateVb(screen); Menu_MakeTitleFont(&titleFont); Menu_MakeBodyFont(&s->textFont); @@ -3323,18 +3340,11 @@ static void TexPackOverlay_ContextRecreated(void* screen) { Font_Free(&titleFont); } -static void TexPackOverlay_BuildMesh(void* screen) { - struct Screen* s = (struct Screen*)screen; - VertexP3fT2fC4b vertices[TEXPACK_MAX_VERTICES]; - - Screen_BuildMesh(screen, vertices); - Gfx_SetDynamicVbData(s->vb, vertices, TEXPACK_MAX_VERTICES); -} - static void TexPackOverlay_Init(void* screen) { struct TexPackOverlay* s = (struct TexPackOverlay*)screen; - s->widgets = texpack_widgets; - s->numWidgets = Array_Elems(texpack_widgets); + s->widgets = texpack_widgets; + s->numWidgets = Array_Elems(texpack_widgets); + s->maxVertices = TEXPACK_MAX_VERTICES; s->contentLength = 0; s->deny = false; @@ -3349,7 +3359,7 @@ static void TexPackOverlay_Init(void* screen) { static const struct ScreenVTABLE TexPackOverlay_VTABLE = { TexPackOverlay_Init, TexPackOverlay_Update, Screen_NullFunc, - MenuScreen_Render2, TexPackOverlay_BuildMesh, + MenuScreen_Render2, Screen_BuildMesh, Screen_InputDown, Screen_TInput, Screen_TKeyPress, Screen_TText, Menu_PointerDown, Screen_TPointer, Menu_PointerMove, Screen_TMouseScroll, Screen_Layout, TexPackOverlay_ContextLost, TexPackOverlay_ContextRecreated @@ -3371,16 +3381,24 @@ void TexPackOverlay_Show(const String* url) { #ifdef CC_BUILD_TOUCH /*########################################################################################################################* -*----------------------------------------------------UrlWarningOverlay----------------------------------------------------* +*-----------------------------------------------------TouchMoreScreen-----------------------------------------------------* *#########################################################################################################################*/ -static struct TouchMoreOverlay { +static struct TouchMoreScreen { Screen_Body - struct ButtonWidget buttons[8]; -} TouchMoreOverlay_Instance; + struct ButtonWidget btns[8]; +} TouchMoreScreen; + +static struct Widget* touchMore_widgets[8] = { + (struct Widget*)&TouchMoreScreen.btns[0], (struct Widget*)&TouchMoreScreen.btns[1], + (struct Widget*)&TouchMoreScreen.btns[2], (struct Widget*)&TouchMoreScreen.btns[3], + (struct Widget*)&TouchMoreScreen.btns[4], (struct Widget*)&TouchMoreScreen.btns[5], + (struct Widget*)&TouchMoreScreen.btns[6], (struct Widget*)&TouchMoreScreen.btns[7] +}; +#define TOUCHMORE_MAX_VERTICES (8 * BUTTONWIDGET_MAX) static void TouchMore_Toggle(KeyBind bind) { int key = KeyBinds[bind]; - Gui_Remove((struct Screen*)&TouchMoreOverlay_Instance); + Gui_Remove((struct Screen*)&TouchMoreScreen); Input_SetPressed(key, !Input_Pressed[key]); } @@ -3392,7 +3410,7 @@ static void TouchMore_Screen(void* s, void* w) { TouchMore_Toggle(KEYBIND_FULLSC static void TouchMore_Noclip(void* s, void* w) { TouchMore_Toggle(KEYBIND_NOCLIP); } static void TouchMore_Menu(void* s, void* w) { - Gui_Remove((struct Screen*)&TouchMoreOverlay_Instance); + Gui_Remove((struct Screen*)&TouchMoreScreen); PauseScreen_Show(); } @@ -3401,7 +3419,7 @@ static void TouchMore_Fog(void* s, void* w) { Input_SetPressed(KeyBinds[KEYBIND_FOG], false); } -static const struct SimpleButtonDesc touchOverlay_btns[8] = { +static const struct SimpleButtonDesc touchMore_btns[8] = { { -160, -50, "Chat", TouchMore_Chat }, { -160, 0, "Speed", TouchMore_Speed }, { -160, 50, "Fly", TouchMore_Fly }, @@ -3412,39 +3430,38 @@ static const struct SimpleButtonDesc touchOverlay_btns[8] = { { 160, 100, "Fog", TouchMore_Fog } }; -static void TouchMoreOverlay_ContextRecreated(void* screen) { - struct TouchMoreOverlay* s = (struct TouchMoreOverlay*)screen; +static void TouchMoreScreen_ContextRecreated(void* screen) { + struct TouchMoreScreen* s = (struct TouchMoreScreen*)screen; struct FontDesc titleFont; Menu_MakeTitleFont(&titleFont); + Screen_CreateVb(screen); - Menu_SetButtons(s->buttons, &titleFont, touchOverlay_btns, 8); + Menu_SetButtons(s->btns, &titleFont, touchMore_btns, 8); Font_Free(&titleFont); } -static void TouchMoreOverlay_Init(void* screen) { - static struct Widget* widgets[8]; - struct TouchMoreOverlay* s = (struct TouchMoreOverlay*)screen; - s->widgets = widgets; - s->numWidgets = Array_Elems(widgets); +static void TouchMoreScreen_Init(void* screen) { + struct TouchMoreScreen* s = (struct TouchMoreScreen*)screen; + s->widgets = touchMore_widgets; + s->numWidgets = Array_Elems(touchMore_widgets); + s->maxVertices = TOUCHMORE_MAX_VERTICES; - Menu_Buttons(s, s->buttons, 300, touchOverlay_btns, 8); + Menu_Buttons(s, s->btns, 300, touchMore_btns, 8); /* TODO: Close button */ } -static void TouchMoreOverlay_BuildMesh(void* screen) { } - -static const struct ScreenVTABLE TouchMoreOverlay_VTABLE = { - TouchMoreOverlay_Init, Screen_NullUpdate, Screen_NullFunc, - MenuScreen_Render, TouchMoreOverlay_BuildMesh, +static const struct ScreenVTABLE TouchMoreScreen_VTABLE = { + TouchMoreScreen_Init, Screen_NullUpdate, Screen_NullFunc, + MenuScreen_Render, Screen_BuildMesh, Screen_InputDown, Screen_TInput, Screen_TKeyPress, Screen_TText, Menu_PointerDown, Screen_TPointer, Menu_PointerMove, Screen_TMouseScroll, - Screen_Layout, Screen_ContextLost, TouchMoreOverlay_ContextRecreated + Screen_Layout, Screen_ContextLost, TouchMoreScreen_ContextRecreated }; -void TouchMoreOverlay_Show(void) { - struct TouchMoreOverlay* s = &TouchMoreOverlay_Instance; +void TouchMoreScreen_Show(void) { + struct TouchMoreScreen* s = &TouchMoreScreen; s->grabsInput = true; s->closable = true; - s->VTABLE = &TouchMoreOverlay_VTABLE; + s->VTABLE = &TouchMoreScreen_VTABLE; Gui_Replace((struct Screen*)s, GUI_PRIORITY_TOUCHMORE); } diff --git a/src/Menus.h b/src/Menus.h index 43f0ca58b..e73bcdac9 100644 --- a/src/Menus.h +++ b/src/Menus.h @@ -37,6 +37,6 @@ void UrlWarningOverlay_Show(const String* url); void TexIdsOverlay_Show(void); void TexPackOverlay_Show(const String* url); #ifdef CC_BUILD_TOUCH -void TouchMoreOverlay_Show(void); +void TouchMoreScreen_Show(void); #endif #endif diff --git a/src/Model.c b/src/Model.c index 31798cf72..48b918f0b 100644 --- a/src/Model.c +++ b/src/Model.c @@ -379,7 +379,7 @@ static void Models_ContextRecreated(void* obj) { Models.Vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, Models.MaxVertices); } -static void Model_Make(struct Model* model) { +static void MakeModel(struct Model* model) { struct Model* active = Models.Active; Models.Active = model; model->MakeParts(); @@ -395,7 +395,7 @@ struct Model* Model_Get(const String* name) { for (model = models_head; model; model = model->next) { if (!String_CaselessEqualsConst(name, model->name)) continue; - if (!model->initalised) Model_Make(model); + if (!model->initalised) MakeModel(model); return model; } return NULL; @@ -1663,7 +1663,7 @@ static void Model_RegisterDefaultModels(void) { Model_RegisterTexture(&zombie_tex); Model_Register(HumanoidModel_GetInstance()); - Model_Make(&human_model); + MakeModel(&human_model); Models.Human = &human_model; Model_Register(ChickenModel_GetInstance()); diff --git a/src/Particle.c b/src/Particle.c index 5befc7cdc..e567828ef 100644 --- a/src/Particle.c +++ b/src/Particle.c @@ -20,7 +20,7 @@ static GfxResourceID Particles_TexId, Particles_VB; static RNGState rnd; static cc_bool particle_hitTerrain; -void Particle_DoRender(Vec2* size, Vec3* pos, TextureRec* rec, PackedCol col, VertexP3fT2fC4b* v) { +void Particle_DoRender(const Vec2* size, const Vec3* pos, const TextureRec* rec, PackedCol col, VertexP3fT2fC4b* v) { struct Matrix* view; float sX, sY; Vec3 centre; @@ -138,25 +138,23 @@ static cc_bool Particle_PhysicsTick(struct Particle* p, float gravity, cc_bool t /*########################################################################################################################* *-------------------------------------------------------Rain particle-----------------------------------------------------* *#########################################################################################################################*/ -struct RainParticle { struct Particle base; }; - -static struct RainParticle rain_Particles[PARTICLES_MAX]; +static struct Particle rain_Particles[PARTICLES_MAX]; static int rain_count; static TextureRec rain_rec = { 2.0f/128.0f, 14.0f/128.0f, 5.0f/128.0f, 16.0f/128.0f }; -static cc_bool RainParticle_Tick(struct RainParticle* p, double delta) { +static cc_bool RainParticle_Tick(struct Particle* p, double delta) { particle_hitTerrain = false; - return Particle_PhysicsTick(&p->base, 3.5f, false, delta) || particle_hitTerrain; + return Particle_PhysicsTick(p, 3.5f, false, delta) || particle_hitTerrain; } -static void RainParticle_Render(struct RainParticle* p, float t, VertexP3fT2fC4b* vertices) { +static void RainParticle_Render(struct Particle* p, float t, VertexP3fT2fC4b* vertices) { Vec3 pos; Vec2 size; PackedCol col; int x, y, z; - Vec3_Lerp(&pos, &p->base.lastPos, &p->base.nextPos, t); - size.X = (float)p->base.size * 0.015625f; size.Y = size.X; + Vec3_Lerp(&pos, &p->lastPos, &p->nextPos, t); + size.X = (float)p->size * 0.015625f; size.Y = size.X; x = Math_Floor(pos.X); y = Math_Floor(pos.Y); z = Math_Floor(pos.Z); col = World_Contains(x, y, z) ? Lighting_Col(x, y, z) : Env.SunCol; @@ -164,23 +162,23 @@ static void RainParticle_Render(struct RainParticle* p, float t, VertexP3fT2fC4b } static void Rain_Render(float t) { - VertexP3fT2fC4b vertices[PARTICLES_MAX * 4]; - VertexP3fT2fC4b* ptr; + VertexP3fT2fC4b* data; int i; if (!rain_count) return; - ptr = vertices; + data = (VertexP3fT2fC4b*)Gfx_LockDynamicVb(Particles_VB, VERTEX_FORMAT_P3FT2FC4B, rain_count * 4); for (i = 0; i < rain_count; i++) { - RainParticle_Render(&rain_Particles[i], t, ptr); - ptr += 4; + RainParticle_Render(&rain_Particles[i], t, data); + data += 4; } Gfx_BindTexture(Particles_TexId); - Gfx_UpdateDynamicVb_IndexedTris(Particles_VB, vertices, rain_count * 4); + Gfx_UnlockDynamicVb(Particles_VB); + Gfx_DrawVb_IndexedTris(rain_count * 4); } static void Rain_RemoveAt(int index) { - struct RainParticle removed = rain_Particles[index]; + struct Particle removed = rain_Particles[index]; int i; for (i = index; i < rain_count - 1; i++) { @@ -254,22 +252,23 @@ static void Terrain_Update1DCounts(void) { } static void Terrain_Render(float t) { - VertexP3fT2fC4b vertices[PARTICLES_MAX * 4]; + VertexP3fT2fC4b* data; VertexP3fT2fC4b* ptr; int offset = 0; int i, index; if (!terrain_count) return; + data = (VertexP3fT2fC4b*)Gfx_LockDynamicVb(Particles_VB, VERTEX_FORMAT_P3FT2FC4B, terrain_count * 4); Terrain_Update1DCounts(); for (i = 0; i < terrain_count; i++) { index = Atlas1D_Index(terrain_particles[i].texLoc); - ptr = &vertices[terrain_1DIndices[index]]; + ptr = data + terrain_1DIndices[index]; TerrainParticle_Render(&terrain_particles[i], t, ptr); terrain_1DIndices[index] += 4; } - Gfx_SetDynamicVbData(Particles_VB, vertices, terrain_count * 4); + Gfx_UnlockDynamicVb(Particles_VB); for (i = 0; i < Atlas1D.Count; i++) { int partCount = terrain_1DCount[i]; if (!partCount) continue; @@ -409,29 +408,28 @@ void Particles_BreakBlockEffect(IVec3 coords, BlockID old, BlockID now) { } } -void Particles_RainSnowEffect(Vec3 pos) { - struct RainParticle* p; - Vec3 origin = pos; +void Particles_RainSnowEffect(float x, float y, float z) { + struct Particle* p; Vec3 offset, velocity; int i, type; for (i = 0; i < 2; i++) { - velocity.X = Random_Float(&rnd) * 0.8f - 0.4f; /* [-0.4, 0.4] */ - velocity.Z = Random_Float(&rnd) * 0.8f - 0.4f; - velocity.Y = Random_Float(&rnd) + 0.4f; - - offset.X = Random_Float(&rnd); /* [0.0, 1.0] */ - offset.Y = Random_Float(&rnd) * 0.1f + 0.01f; - offset.Z = Random_Float(&rnd); - if (rain_count == PARTICLES_MAX) Rain_RemoveAt(0); p = &rain_Particles[rain_count++]; - Vec3_Add(&pos, &origin, &offset); - Particle_Reset(&p->base, pos, velocity, 40.0f); + p->velocity.X = Random_Float(&rnd) * 0.8f - 0.4f; /* [-0.4, 0.4] */ + p->velocity.Z = Random_Float(&rnd) * 0.8f - 0.4f; + p->velocity.Y = Random_Float(&rnd) + 0.4f; + + p->lastPos.X = x + Random_Float(&rnd); /* [0.0, 1.0] */ + p->lastPos.Y = y + Random_Float(&rnd) * 0.1f + 0.01f; + p->lastPos.Z = z + Random_Float(&rnd); + + p->nextPos = p->lastPos; + p->lifetime = 40.0f; type = Random_Next(&rnd, 30); - p->base.size = (cc_uint8)(type >= 28 ? 2 : (type >= 25 ? 4 : 3)); + p->size = (cc_uint8)(type >= 28 ? 2 : (type >= 25 ? 4 : 3)); } } diff --git a/src/Particle.h b/src/Particle.h index c83304199..318569db4 100644 --- a/src/Particle.h +++ b/src/Particle.h @@ -18,9 +18,9 @@ struct Particle { }; /* http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/ */ -void Particle_DoRender(Vec2* size, Vec3* pos, TextureRec* rec, PackedCol col, VertexP3fT2fC4b* vertices); +void Particle_DoRender(const Vec2* size, const Vec3* pos, const TextureRec* rec, PackedCol col, VertexP3fT2fC4b* vertices); void Particles_Render(float t); void Particles_Tick(struct ScheduledTask* task); void Particles_BreakBlockEffect(IVec3 coords, BlockID oldBlock, BlockID block); -void Particles_RainSnowEffect(Vec3 pos); +void Particles_RainSnowEffect(float x, float y, float z); #endif diff --git a/src/Screens.c b/src/Screens.c index 59a91ed3b..0fc1fb24f 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -99,16 +99,26 @@ void Screen_ContextLost(void* screen) { } } -void Screen_BuildMesh(void* screen, VertexP3fT2fC4b* vertices) { +void Screen_CreateVb(void* screen) { + struct Screen* s = (struct Screen*)screen; + s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, s->maxVertices); +} + +void Screen_BuildMesh(void* screen) { struct Screen* s = (struct Screen*)screen; struct Widget** widgets = s->widgets; - VertexP3fT2fC4b** ptr = &vertices; + VertexP3fT2fC4b* data; + VertexP3fT2fC4b** ptr; int i; + data = (VertexP3fT2fC4b*)Gfx_LockDynamicVb(s->vb, VERTEX_FORMAT_P3FT2FC4B, s->maxVertices); + ptr = &data; + for (i = 0; i < s->numWidgets; i++) { if (!widgets[i]) continue; Widget_BuildMesh(widgets[i], ptr); } + Gfx_UnlockDynamicVb(s->vb); } @@ -1469,7 +1479,7 @@ static void DisconnectScreen_ContextLost(void* screen) { static void DisconnectScreen_ContextRecreated(void* screen) { String msg; char msgBuffer[STRING_SIZE]; struct DisconnectScreen* s = (struct DisconnectScreen*)screen; - s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, DISCONNECT_MAX_VERTICES); + Screen_CreateVb(screen); Drawer2D_MakeFont(&s->titleFont, 16, FONT_STYLE_BOLD); Drawer2D_MakeFont(&s->messageFont, 16, FONT_STYLE_NORMAL); @@ -1481,14 +1491,6 @@ static void DisconnectScreen_ContextRecreated(void* screen) { ButtonWidget_Set(&s->reconnect, &msg, &s->titleFont); } -static void DisconnectScreen_BuildMesh(void* screen) { - struct Screen* s = (struct Screen*)screen; - VertexP3fT2fC4b vertices[DISCONNECT_MAX_VERTICES]; - - Screen_BuildMesh(screen, vertices); - Gfx_SetDynamicVbData(s->vb, vertices, DISCONNECT_MAX_VERTICES); -} - static void DisconnectScreen_Init(void* screen) { struct DisconnectScreen* s = (struct DisconnectScreen*)screen; @@ -1498,6 +1500,7 @@ static void DisconnectScreen_Init(void* screen) { ButtonWidget_Make(&s->reconnect, 300, NULL, ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 80); s->reconnect.disabled = !s->canReconnect; + s->maxVertices = DISCONNECT_MAX_VERTICES; /* NOTE: changing VSync can't be done within frame, causes crash on some GPUs */ Gfx_SetFpsLimit(Game_FpsLimit == FPS_LIMIT_VSYNC, 1000 / 5.0f); @@ -1547,7 +1550,7 @@ static int DisconnectScreen_PointerMove(void* screen, int idx, int x, int y) { static const struct ScreenVTABLE DisconnectScreen_VTABLE = { DisconnectScreen_Init, DisconnectScreen_Update, DisconnectScreen_Free, - DisconnectScreen_Render, DisconnectScreen_BuildMesh, + DisconnectScreen_Render, Screen_BuildMesh, Screen_InputDown, Screen_TInput, Screen_TKeyPress, Screen_TText, DisconnectScreen_PointerDown, Screen_TPointer, DisconnectScreen_PointerMove, Screen_TMouseScroll, Screen_Layout, DisconnectScreen_ContextLost, DisconnectScreen_ContextRecreated @@ -1626,15 +1629,14 @@ static void TouchScreen_ModeClick(void* s, void* w) { Input_Placing = !Input_Placing; TouchScreen_UpdateModeText(s); } -static void TouchScreen_MoreClick(void* s, void* w) { TouchMoreOverlay_Show(); } +static void TouchScreen_MoreClick(void* s, void* w) { TouchMoreScreen_Show(); } static void TouchScreen_ContextRecreated(void* screen) { struct TouchScreen* s = (struct TouchScreen*)screen; const struct TouchBindDesc* desc; int i; - + Screen_CreateVb(screen); Drawer2D_MakeFont(&s->font, 16, FONT_STYLE_BOLD); - s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FT2FC4B, TOUCH_MAX_VERTICES); for (i = 0; i < s->numWidgets; i++) { desc = &touchDescs[i]; @@ -1690,21 +1692,14 @@ static int TouchScreen_PointerUp(void* screen, int id, int x, int y) { return false; } -static void TouchScreen_BuildMesh(void* screen) { - struct Screen* s = (struct Screen*)screen; - VertexP3fT2fC4b vertices[TOUCH_MAX_VERTICES]; - - Screen_BuildMesh(screen, vertices); - Gfx_SetDynamicVbData(s->vb, vertices, TOUCH_MAX_VERTICES); -} - static void TouchScreen_Init(void* screen) { struct TouchScreen* s = (struct TouchScreen*)screen; const struct TouchBindDesc* desc; int i; - s->widgets = touch_widgets; - s->numWidgets = Array_Elems(touch_widgets); + s->widgets = touch_widgets; + s->numWidgets = Array_Elems(touch_widgets); + s->maxVertices = TOUCH_MAX_VERTICES; for (i = 0; i < s->numWidgets; i++) { desc = &touchDescs[i]; @@ -1719,7 +1714,7 @@ static void TouchScreen_Init(void* screen) { static const struct ScreenVTABLE TouchScreen_VTABLE = { TouchScreen_Init, Screen_NullUpdate, Screen_NullFunc, - TouchScreen_Render, TouchScreen_BuildMesh, + TouchScreen_Render, Screen_BuildMesh, Screen_FInput, Screen_FInput, Screen_FKeyPress, Screen_FText, TouchScreen_PointerDown, TouchScreen_PointerUp, Screen_FPointer, Screen_FMouseScroll, Screen_Layout, TouchScreen_ContextLost, TouchScreen_ContextRecreated diff --git a/src/Screens.h b/src/Screens.h index 7f5939b77..9ffad6890 100644 --- a/src/Screens.h +++ b/src/Screens.h @@ -34,8 +34,8 @@ void Screen_Layout(void* screen); /* Calls Widget_Free on each widget in the screen. */ /* Also deletes the screen's vb. */ void Screen_ContextLost(void* screen); -/* Calls Widget_BuildMesh on each widget in the screen. */ -void Screen_BuildMesh(void* screen, VertexP3fT2fC4b* vertices); +void Screen_CreateVb(void* screen); +void Screen_BuildMesh(void* screen); void InventoryScreen_Show(void); void HUDScreen_Show(void); diff --git a/src/SelectionBox.c b/src/SelectionBox.c index fefb62fa6..c7e38b0a5 100644 --- a/src/SelectionBox.c +++ b/src/SelectionBox.c @@ -13,25 +13,25 @@ struct SelectionBox { float MinDist, MaxDist; }; -#define SelectionBox_Y(y) 0,y,0, 0,y,1, 1,y,1, 1,y,0, -#define SelectionBox_Z(z) 0,0,z, 0,1,z, 1,1,z, 1,0,z, -#define SelectionBox_X(x) x,0,0, x,1,0, x,1,1, x,0,1, - -static void SelectionBox_Render(struct SelectionBox* box, VertexP3fC4b** faceVertices, VertexP3fC4b** edgeVertices) { - static const cc_uint8 faceIndices[72] = { - SelectionBox_Y(0) SelectionBox_Y(1) /* YMin, YMax */ - SelectionBox_Z(0) SelectionBox_Z(1) /* ZMin, ZMax */ - SelectionBox_X(0) SelectionBox_X(1) /* XMin, XMax */ +#define X0 0 +#define X1 1 +#define Y0 0 +#define Y1 2 +#define Z0 0 +#define Z1 4 + +#define SelectionBox_Y(y) X0|y |Z0, X0|y |Z1, X1|y |Z1, X1|y |Z0, +#define SelectionBox_Z(z) X0|Y0|z , X0|Y1|z , X1|Y1|z , X1|Y0|z , +#define SelectionBox_X(x) x |Y0|Z0, x |Y1|Z0, x |Y1|Z1, x |Y0|Z1, + +static void SelectionBox_RenderFaces(struct SelectionBox* box, VertexP3fC4b* v) { + static const cc_uint8 faceIndices[24] = { + SelectionBox_Y(Y0) SelectionBox_Y(Y1) /* YMin, YMax */ + SelectionBox_Z(Z0) SelectionBox_Z(Z1) /* ZMin, ZMax */ + SelectionBox_X(X0) SelectionBox_X(X1) /* XMin, XMax */ }; - static const cc_uint8 edgeIndices[72] = { - 0,0,0, 1,0,0, 1,0,0, 1,0,1, 1,0,1, 0,0,1, 0,0,1, 0,0,0, /* YMin */ - 0,1,0, 1,1,0, 1,1,0, 1,1,1, 1,1,1, 0,1,1, 0,1,1, 0,1,0, /* YMax */ - 0,0,0, 0,1,0, 1,0,0, 1,1,0, 1,0,1, 1,1,1, 0,0,1, 0,1,1, /* X/Z */ - }; - - VertexP3fC4b* v; PackedCol col; - int i; + int i, flags; float offset = box->MinDist < 32.0f * 32.0f ? (1/32.0f) : (1/16.0f); Vec3 coords[2]; @@ -39,25 +39,40 @@ static void SelectionBox_Render(struct SelectionBox* box, VertexP3fC4b** faceVer Vec3_Add1(&coords[1], &box->Max, offset); col = box->Col; - v = *faceVertices; - for (i = 0; i < Array_Elems(faceIndices); i += 3, v++) { - v->X = coords[faceIndices[i + 0]].X; - v->Y = coords[faceIndices[i + 1]].Y; - v->Z = coords[faceIndices[i + 2]].Z; + for (i = 0; i < Array_Elems(faceIndices); i++, v++) { + flags = faceIndices[i]; + v->X = coords[(flags ) & 1].X; + v->Y = coords[(flags >> 1) & 1].Y; + v->Z = coords[(flags >> 2) ].Z; v->Col = col; } - *faceVertices = v; +} + +static void SelectionBox_RenderEdges(struct SelectionBox* box, VertexP3fC4b* v) { + static const cc_uint8 edgeIndices[24] = { + X0|Y0|Z0, X1|Y0|Z0, X1|Y0|Z0, X1|Y0|Z1, X1|Y0|Z1, X0|Y0|Z1, X0|Y0|Z1, X0|Y0|Z0, /* YMin */ + X0|Y1|Z0, X1|Y1|Z0, X1|Y1|Z0, X1|Y1|Z1, X1|Y1|Z1, X0|Y1|Z1, X0|Y1|Z1, X0|Y1|Z0, /* YMax */ + X0|Y0|Z0, X0|Y1|Z0, X1|Y0|Z0, X1|Y1|Z0, X1|Y0|Z1, X1|Y1|Z1, X0|Y0|Z1, X0|Y1|Z1, /* X/Z */ + }; + PackedCol col; + int i, flags; + + float offset = box->MinDist < 32.0f * 32.0f ? (1/32.0f) : (1/16.0f); + Vec3 coords[2]; + Vec3_Add1(&coords[0], &box->Min, -offset); + Vec3_Add1(&coords[1], &box->Max, offset); + col = box->Col; /* invert R/G/B for surrounding line */ col = (col & PACKEDCOL_A_MASK) | (~col & PACKEDCOL_RGB_MASK); - v = *edgeVertices; - for (i = 0; i < Array_Elems(edgeIndices); i += 3, v++) { - v->X = coords[edgeIndices[i + 0]].X; - v->Y = coords[edgeIndices[i + 1]].Y; - v->Z = coords[edgeIndices[i + 2]].Z; + + for (i = 0; i < Array_Elems(edgeIndices); i++, v++) { + flags = edgeIndices[i]; + v->X = coords[(flags ) & 1].X; + v->Y = coords[(flags >> 1) & 1].Y; + v->Z = coords[(flags >> 2) ].Z; v->Col = col; } - *edgeVertices = v; } static int SelectionBox_Compare(struct SelectionBox* a, struct SelectionBox* b) { @@ -70,7 +85,7 @@ static int SelectionBox_Compare(struct SelectionBox* a, struct SelectionBox* b) /* Reversed comparison order result, because we need to render back to front for alpha blending */ if (aDist < bDist) return 1; - if (aDist > bDist) return -1; + if (aDist > bDist) return -1; return 0; } @@ -154,10 +169,9 @@ static void Selections_QuickSort(int left, int right) { } void Selections_Render(void) { - VertexP3fC4b faceVertices[SELECTIONS_MAX_VERTICES]; VertexP3fC4b* facesPtr; - VertexP3fC4b edgeVertices[SELECTIONS_MAX_VERTICES]; VertexP3fC4b* edgesPtr; + VertexP3fC4b* data; Vec3 cameraPos; - int i; + int i, count; if (!selections_count || Gfx.LostContext) return; /* TODO: Proper selection box sorting. But this is very difficult because @@ -172,20 +186,25 @@ void Selections_Render(void) { selections_used = true; Selections_ContextRecreated(NULL); } + count = selections_count * SELECTIONS_VERTICES; + Gfx_SetVertexFormat(VERTEX_FORMAT_P3FC4B); - facesPtr = faceVertices; edgesPtr = edgeVertices; - for (i = 0; i < selections_count; i++) { - SelectionBox_Render(&selections_list[i], &facesPtr, &edgesPtr); + data = (VertexP3fC4b*)Gfx_LockDynamicVb(selections_LineVB, VERTEX_FORMAT_P3FC4B, count); + for (i = 0; i < selections_count; i++, data += SELECTIONS_VERTICES) { + SelectionBox_RenderEdges(&selections_list[i], data); } + Gfx_UnlockDynamicVb(selections_LineVB); + Gfx_DrawVb_Lines(count); - Gfx_SetVertexFormat(VERTEX_FORMAT_P3FC4B); - Gfx_UpdateDynamicVb_Lines(selections_LineVB, edgeVertices, - selections_count * SELECTIONS_VERTICES); + data = (VertexP3fC4b*)Gfx_LockDynamicVb(selections_VB, VERTEX_FORMAT_P3FC4B, count); + for (i = 0; i < selections_count; i++, data += SELECTIONS_VERTICES) { + SelectionBox_RenderFaces(&selections_list[i], data); + } + Gfx_UnlockDynamicVb(selections_VB); Gfx_SetDepthWrite(false); Gfx_SetAlphaBlending(true); - Gfx_UpdateDynamicVb_IndexedTris(selections_VB, faceVertices, - selections_count * SELECTIONS_VERTICES); + Gfx_DrawVb_IndexedTris(count); Gfx_SetDepthWrite(true); Gfx_SetAlphaBlending(false); } diff --git a/src/Widgets.c b/src/Widgets.c index be4c70db0..cf4d825d7 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -1403,6 +1403,25 @@ static void MenuInputWidget_Render(void* widget, double delta) { InputWidget_RenderCaret(w, delta); } +static void MenuInputWidget_BuildMesh(void* widget, VertexP3fT2fC4b** vertices) { + struct InputWidget* w = (struct InputWidget*)widget; + Gfx_Make2DQuad(&w->inputTex, PACKEDCOL_WHITE, vertices); + Gfx_Make2DQuad(&w->caretTex, w->caretCol, vertices); +} + +static int MenuInputWidget_Render2(void* widget, int offset) { + struct InputWidget* w = (struct InputWidget*)widget; + Gfx_BindTexture(w->inputTex.ID); + Gfx_DrawVb_IndexedTris_Range(4, offset); + offset += 4; + + if (w->showCaret && Math_Mod1((float)w->caretAccumulator) < 0.5f) { + Gfx_BindTexture(w->caretTex.ID); + Gfx_DrawVb_IndexedTris_Range(4, offset); + } + return offset + 4; +} + static void MenuInputWidget_RemakeTexture(void* widget) { String range; char rangeBuffer[STRING_SIZE]; struct MenuInputWidget* w = (struct MenuInputWidget*)widget; @@ -1476,7 +1495,8 @@ static int MenuInputWidget_GetMaxLines(void) { return 1; } static const struct WidgetVTABLE MenuInputWidget_VTABLE = { MenuInputWidget_Render, InputWidget_Free, InputWidget_Reposition, InputWidget_KeyDown, InputWidget_KeyUp, Widget_MouseScroll, - InputWidget_PointerDown, Widget_Pointer, Widget_PointerMove + InputWidget_PointerDown, Widget_Pointer, Widget_PointerMove, + MenuInputWidget_BuildMesh, MenuInputWidget_Render2 }; void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, const String* text, struct MenuInputDesc* desc) { InputWidget_Reset(&w->base); diff --git a/src/Widgets.h b/src/Widgets.h index 99c992f32..e2c4f1ed6 100644 --- a/src/Widgets.h +++ b/src/Widgets.h @@ -191,6 +191,8 @@ struct MenuInputWidget { struct MenuInputDesc desc; char _textBuffer[INPUTWIDGET_LEN]; }; +#define MENUINPUTWIDGET_MAX 8 + CC_NOINLINE void MenuInputWidget_Create(struct MenuInputWidget* w, int width, int height, const String* text, struct MenuInputDesc* d); /* Sets the font used, then redraws the input widget. */ CC_NOINLINE void MenuInputWidget_SetFont(struct MenuInputWidget* w, struct FontDesc* font);