diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj
index aa1a0a4e9..cdc427c56 100644
--- a/ClassicalSharp/ClassicalSharp.csproj
+++ b/ClassicalSharp/ClassicalSharp.csproj
@@ -276,7 +276,6 @@
-
diff --git a/ClassicalSharp/Selections/SelectionBox.cs b/ClassicalSharp/Selections/SelectionBox.cs
index a614f547a..fa0a54cd6 100644
--- a/ClassicalSharp/Selections/SelectionBox.cs
+++ b/ClassicalSharp/Selections/SelectionBox.cs
@@ -1,11 +1,12 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
+using System.Collections.Generic;
using ClassicalSharp.GraphicsAPI;
using OpenTK;
namespace ClassicalSharp.Selections {
- public class SelectionBox {
+ internal class SelectionBox {
public byte ID;
public Vector3I Min, Max;
@@ -75,4 +76,40 @@ namespace ClassicalSharp.Selections {
v.X = x2; v.Y = y2; v.Z = z2; vertices[index++] = v;
}
}
+
+ internal class SelectionBoxComparer : IComparer {
+
+ public int Compare(SelectionBox a, SelectionBox b) {
+ // Reversed comparison order because we need to render back to front for alpha blending.
+ return a.MinDist == b.MinDist
+ ? b.MaxDist.CompareTo(a.MaxDist)
+ : b.MinDist.CompareTo(a.MinDist);
+ }
+
+ internal void Intersect(SelectionBox box, Vector3 origin) {
+ Vector3I min = box.Min, max = box.Max;
+ float closest = float.PositiveInfinity, furthest = float.NegativeInfinity;
+ // Bottom corners
+ UpdateDist(origin, min.X, min.Y, min.Z, ref closest, ref furthest);
+ UpdateDist(origin, max.X, min.Y, min.Z, ref closest, ref furthest);
+ UpdateDist(origin, max.X, min.Y, max.Z, ref closest, ref furthest);
+ UpdateDist(origin, min.X, min.Y, max.Z, ref closest, ref furthest);
+ // Top corners
+ UpdateDist(origin, min.X, max.Y, min.Z, ref closest, ref furthest);
+ UpdateDist(origin, max.X, max.Y, min.Z, ref closest, ref furthest);
+ UpdateDist(origin, max.X, max.Y, max.Z, ref closest, ref furthest);
+ UpdateDist(origin, min.X, max.Y, max.Z, ref closest, ref furthest);
+ box.MinDist = closest; box.MaxDist = furthest;
+ }
+
+
+ static void UpdateDist(Vector3 p, float x2, float y2, float z2,
+ ref float closest, ref float furthest) {
+ float dx = x2 - p.X, dy = y2 - p.Y, dz = z2 - p.Z;
+ float dist = dx * dx + dy * dy + dz * dz;
+
+ if (dist < closest) closest = dist;
+ if (dist > furthest) furthest = dist;
+ }
+ }
}
diff --git a/ClassicalSharp/Selections/SelectionBoxComparer.cs b/ClassicalSharp/Selections/SelectionBoxComparer.cs
deleted file mode 100644
index cb0a4679e..000000000
--- a/ClassicalSharp/Selections/SelectionBoxComparer.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
-using System;
-using System.Collections.Generic;
-using OpenTK;
-
-namespace ClassicalSharp.Selections {
-
- internal class SelectionBoxComparer : IComparer {
-
- public int Compare(SelectionBox a, SelectionBox b) {
- // Reversed comparison order because we need to render back to front for alpha blending.
- return a.MinDist == b.MinDist ? b.MaxDist.CompareTo(a.MaxDist)
- : b.MinDist.CompareTo(a.MinDist);
- }
-
- internal void Intersect(SelectionBox box, Vector3 origin) {
- Vector3I min = box.Min, max = box.Max;
- float closest = float.PositiveInfinity, furthest = float.NegativeInfinity;
- // Bottom corners
- UpdateDist(origin, min.X, min.Y, min.Z, ref closest, ref furthest);
- UpdateDist(origin, max.X, min.Y, min.Z, ref closest, ref furthest);
- UpdateDist(origin, max.X, min.Y, max.Z, ref closest, ref furthest);
- UpdateDist(origin, min.X, min.Y, max.Z, ref closest, ref furthest);
- // Top corners
- UpdateDist(origin, min.X, max.Y, min.Z, ref closest, ref furthest);
- UpdateDist(origin, max.X, max.Y, min.Z, ref closest, ref furthest);
- UpdateDist(origin, max.X, max.Y, max.Z, ref closest, ref furthest);
- UpdateDist(origin, min.X, max.Y, max.Z, ref closest, ref furthest);
- box.MinDist = closest; box.MaxDist = furthest;
- }
-
- static void UpdateDist(Vector3 p, float x2, float y2, float z2,
- ref float closest, ref float furthest) {
- float dist = Utils.DistanceSquared(p.X, p.Y, p.Z, x2, y2, z2);
- if (dist < closest) closest = dist;
- if (dist > furthest) furthest = dist;
- }
- }
-}
\ No newline at end of file
diff --git a/ClassicalSharp/Utils/Utils.Math.cs b/ClassicalSharp/Utils/Utils.Math.cs
index ddc06e9d2..921334f23 100644
--- a/ClassicalSharp/Utils/Utils.Math.cs
+++ b/ClassicalSharp/Utils/Utils.Math.cs
@@ -81,14 +81,7 @@ namespace ClassicalSharp {
float cosA = (float)Math.Cos(angle), sinA = (float)Math.Sin(angle);
return new Vector3(cosA * v.X + sinA * v.Y, -sinA * v.X + cosA * v.Y, v.Z);
}
-
- /// Returns the square of the euclidean distance between two points.
- public static float DistanceSquared(float x1, float y1, float z1, float x2, float y2, float z2) {
- float dx = x2 - x1, dy = y2 - y1, dz = z2 - z1;
- return dx * dx + dy * dy + dz * dz;
- }
-
/// Returns a normalised vector that faces in the direction
/// described by the given yaw and pitch.
public static Vector3 GetDirVector(double yawRad, double pitchRad) {
diff --git a/src/Client/BordersRenderer.c b/src/Client/BordersRenderer.c
index 17ae30632..8c6b4d947 100644
--- a/src/Client/BordersRenderer.c
+++ b/src/Client/BordersRenderer.c
@@ -106,10 +106,10 @@ void BordersRenderer_DrawX(Int32 x, Int32 z1, Int32 z2, Int32 y1, Int32 y2, Int3
if (y2 > endY) y2 = endY;
Real32 u2 = (Real32)z2 - (Real32)z1, v2 = (Real32)y2 - (Real32)y1;
- v.Y = (Real32)y1; v.Z = (Real32)z1; v.U = 0.0f; v.V = v2; *ptr = v; ptr++;
- v.Y = (Real32)y2; v.V = 0.0f; *ptr = v; ptr++;
- v.Z = (Real32)z2; v.U = u2; *ptr = v; ptr++;
- v.Y = (Real32)y1; v.V = v2; *ptr = v; ptr++;
+ v.Y = (Real32)y1; v.Z = (Real32)z1; v.U = 0.0f; v.V = v2; *ptr++ = v;
+ v.Y = (Real32)y2; v.V = 0.0f; *ptr++ = v;
+ v.Z = (Real32)z2; v.U = u2; *ptr++ = v;
+ v.Y = (Real32)y1; v.V = v2; *ptr++ = v;
}
}
*vertices = ptr;
@@ -130,10 +130,10 @@ void BordersRenderer_DrawZ(Int32 z, Int32 x1, Int32 x2, Int32 y1, Int32 y2, Int3
if (y2 > endY) y2 = endY;
Real32 u2 = (Real32)x2 - (Real32)x1, v2 = (Real32)y2 - (Real32)y1;
- v.X = (Real32)x1; v.Y = (Real32)y1; v.U = 0.0f; v.V = v2; *ptr = v; ptr++;
- v.Y = (Real32)y2; v.V = 0.0f; *ptr = v; ptr++;
- v.X = (Real32)x2; v.U = u2; *ptr = v; ptr++;
- v.Y = (Real32)y1; v.V = v2; *ptr = v; ptr++;
+ v.X = (Real32)x1; v.Y = (Real32)y1; v.U = 0.0f; v.V = v2; *ptr++ = v;
+ v.Y = (Real32)y2; v.V = 0.0f; *ptr++ = v;
+ v.X = (Real32)x2; v.U = u2; *ptr++ = v;
+ v.Y = (Real32)y1; v.V = v2; *ptr++ = v;
}
}
*vertices = ptr;
@@ -154,10 +154,10 @@ void BordersRenderer_DrawY(Int32 x1, Int32 z1, Int32 x2, Int32 z2, Real32 y, Int
if (z2 > endZ) z2 = endZ;
Real32 u2 = (Real32)x2 - (Real32)x1, v2 = (Real32)z2 - (Real32)z1;
- v.X = (Real32)x1 + offset; v.Z = (Real32)z1 + offset; v.U = 0.0f; v.V = 0.0f; *ptr = v; ptr++;
- v.Z = (Real32)z2 + offset; v.V = v2; *ptr = v; ptr++;
- v.X = (Real32)x2 + offset; v.U = u2; *ptr = v; ptr++;
- v.Z = (Real32)z1 + offset; v.V = 0.0f; *ptr = v; ptr++;
+ v.X = (Real32)x1 + offset; v.Z = (Real32)z1 + offset; v.U = 0.0f; v.V = 0.0f; *ptr++ = v;
+ v.Z = (Real32)z2 + offset; v.V = v2; *ptr++ = v;
+ v.X = (Real32)x2 + offset; v.U = u2; *ptr++ = v;
+ v.Z = (Real32)z1 + offset; v.V = 0.0f; *ptr++ = v;
}
}
*vertices = ptr;
diff --git a/src/Client/Drawer.c b/src/Client/Drawer.c
index 3ef35dfd0..8794bfb72 100644
--- a/src/Client/Drawer.c
+++ b/src/Client/Drawer.c
@@ -2,8 +2,6 @@
#include "TerrainAtlas.h"
#include "Constants.h"
-#define AddVertex *ptr = v; ptr++
-
/* Performance critical, use macro to ensure always inlined. */
#define ApplyTint \
if (Drawer_Tinted) {\
@@ -23,10 +21,10 @@ void Drawer_XMin(Int32 count, PackedCol col, TextureLoc texLoc, VertexP3fT2fC4b*
VertexP3fT2fC4b* ptr = *vertices;
VertexP3fT2fC4b v; v.X = Drawer_X1; v.Col = col;
- v.Y = Drawer_Y2; v.Z = Drawer_Z2 + (count - 1); v.U = u2; v.V = v1; AddVertex;
- v.Z = Drawer_Z1; v.U = u1; AddVertex;
- v.Y = Drawer_Y1; v.V = v2; AddVertex;
- v.Z = Drawer_Z2 + (count - 1); v.U = u2; AddVertex;
+ v.Y = Drawer_Y2; v.Z = Drawer_Z2 + (count - 1); v.U = u2; v.V = v1; *ptr++ = v;
+ v.Z = Drawer_Z1; v.U = u1; *ptr++ = v;
+ v.Y = Drawer_Y1; v.V = v2; *ptr++ = v;
+ v.Z = Drawer_Z2 + (count - 1); v.U = u2; *ptr++ = v;
*vertices = ptr;
}
@@ -40,10 +38,10 @@ void Drawer_XMax(Int32 count, PackedCol col, TextureLoc texLoc, VertexP3fT2fC4b*
VertexP3fT2fC4b* ptr = *vertices;
VertexP3fT2fC4b v; v.X = Drawer_X2; v.Col = col;
- v.Y = Drawer_Y2; v.Z = Drawer_Z1; v.U = u1; v.V = v1; AddVertex;
- v.Z = Drawer_Z2 + (count - 1); v.U = u2; AddVertex;
- v.Y = Drawer_Y1; v.V = v2; AddVertex;
- v.Z = Drawer_Z1; v.U = u1; AddVertex;
+ v.Y = Drawer_Y2; v.Z = Drawer_Z1; v.U = u1; v.V = v1; *ptr++ = v;
+ v.Z = Drawer_Z2 + (count - 1); v.U = u2; *ptr++ = v;
+ v.Y = Drawer_Y1; v.V = v2; *ptr++ = v;
+ v.Z = Drawer_Z1; v.U = u1; *ptr++ = v;
*vertices = ptr;
}
@@ -57,10 +55,10 @@ void Drawer_ZMin(Int32 count, PackedCol col, TextureLoc texLoc, VertexP3fT2fC4b*
VertexP3fT2fC4b* ptr = *vertices;
VertexP3fT2fC4b v; v.Z = Drawer_Z1; v.Col = col;
- v.X = Drawer_X2 + (count - 1); v.Y = Drawer_Y1; v.U = u2; v.V = v2; AddVertex;
- v.X = Drawer_X1; v.U = u1; AddVertex;
- v.Y = Drawer_Y2; v.V = v1; AddVertex;
- v.X = Drawer_X2 + (count - 1); v.U = u2; AddVertex;
+ v.X = Drawer_X2 + (count - 1); v.Y = Drawer_Y1; v.U = u2; v.V = v2; *ptr++ = v;
+ v.X = Drawer_X1; v.U = u1; *ptr++ = v;
+ v.Y = Drawer_Y2; v.V = v1; *ptr++ = v;
+ v.X = Drawer_X2 + (count - 1); v.U = u2; *ptr++ = v;
*vertices = ptr;
}
@@ -74,10 +72,10 @@ void Drawer_ZMax(Int32 count, PackedCol col, TextureLoc texLoc, VertexP3fT2fC4b*
VertexP3fT2fC4b* ptr = *vertices;
VertexP3fT2fC4b v; v.Z = Drawer_Z2; v.Col = col;
- v.X = Drawer_X2 + (count - 1); v.Y = Drawer_Y2; v.U = u2; v.V = v1; AddVertex;
- v.X = Drawer_X1; v.U = u1; AddVertex;
- v.Y = Drawer_Y1; v.V = v2; AddVertex;
- v.X = Drawer_X2 + (count - 1); v.U = u2; AddVertex;
+ v.X = Drawer_X2 + (count - 1); v.Y = Drawer_Y2; v.U = u2; v.V = v1; *ptr++ = v;
+ v.X = Drawer_X1; v.U = u1; *ptr++ = v;
+ v.Y = Drawer_Y1; v.V = v2; *ptr++ = v;
+ v.X = Drawer_X2 + (count - 1); v.U = u2; *ptr++ = v;
*vertices = ptr;
}
@@ -91,10 +89,10 @@ void Drawer_YMin(Int32 count, PackedCol col, TextureLoc texLoc, VertexP3fT2fC4b*
VertexP3fT2fC4b* ptr = *vertices;
VertexP3fT2fC4b v; v.Y = Drawer_Y1; v.Col = col;
- v.X = Drawer_X2 + (count - 1); v.Z = Drawer_Z2; v.U = u2; v.V = v2; AddVertex;
- v.X = Drawer_X1; v.U = u1; AddVertex;
- v.Z = Drawer_Z1; v.V = v1; AddVertex;
- v.X = Drawer_X2 + (count - 1); v.U = u2; AddVertex;
+ v.X = Drawer_X2 + (count - 1); v.Z = Drawer_Z2; v.U = u2; v.V = v2; *ptr++ = v;
+ v.X = Drawer_X1; v.U = u1; *ptr++ = v;
+ v.Z = Drawer_Z1; v.V = v1; *ptr++ = v;
+ v.X = Drawer_X2 + (count - 1); v.U = u2; *ptr++ = v;
*vertices = ptr;
}
@@ -108,9 +106,9 @@ void Drawer_YMax(Int32 count, PackedCol col, TextureLoc texLoc, VertexP3fT2fC4b*
VertexP3fT2fC4b* ptr = *vertices;
VertexP3fT2fC4b v; v.Y = Drawer_Y2; v.Col = col;
- v.X = Drawer_X2 + (count - 1); v.Z = Drawer_Z1; v.U = u2; v.V = v1; AddVertex;
- v.X = Drawer_X1; v.U = u1; AddVertex;
- v.Z = Drawer_Z2; v.V = v2; AddVertex;
- v.X = Drawer_X2 + (count - 1); v.U = u2; AddVertex;
+ v.X = Drawer_X2 + (count - 1); v.Z = Drawer_Z1; v.U = u2; v.V = v1; *ptr++ = v;
+ v.X = Drawer_X1; v.U = u1; *ptr++ = v;
+ v.Z = Drawer_Z2; v.V = v2; *ptr++ = v;
+ v.X = Drawer_X2 + (count - 1); v.U = u2; *ptr++ = v;
*vertices = ptr;
}
\ No newline at end of file
diff --git a/src/Client/EnvRenderer.c b/src/Client/EnvRenderer.c
index 277f0a9b3..15b54a5db 100644
--- a/src/Client/EnvRenderer.c
+++ b/src/Client/EnvRenderer.c
@@ -165,10 +165,10 @@ void EnvRenderer_DrawSkyY(Int32 x1, Int32 z1, Int32 x2, Int32 z2, Int32 y, Int32
z2 = z1 + axisSize;
if (z2 > endZ) z2 = endZ;
- v.X = (Real32)x1; v.Z = (Real32)z1; *vertices = v; vertices++;
- v.Z = (Real32)z2; *vertices = v; vertices++;
- v.X = (Real32)x2; *vertices = v; vertices++;
- v.Z = (Real32)z1; *vertices = v; vertices++;
+ v.X = (Real32)x1; v.Z = (Real32)z1; *vertices++ = v;
+ v.Z = (Real32)z2; *vertices++ = v;
+ v.X = (Real32)x2; *vertices++ = v;
+ v.Z = (Real32)z1; *vertices++ = v;
}
}
}
@@ -190,10 +190,10 @@ void EnvRenderer_DrawCloudsY(Int32 x1, Int32 z1, Int32 x2, Int32 z2, Int32 y, In
Real32 u1 = (Real32)x1 / 2048.0f + offset, u2 = (Real32)x2 / 2048.0f + offset;
Real32 v1 = (Real32)z1 / 2048.0f + offset, v2 = (Real32)z2 / 2048.0f + offset;
- v.X = (Real32)x1; v.Z = (Real32)z1; v.U = u1; v.V = v1; *vertices = v; vertices++;
- v.Z = (Real32)z2; v.V = v2; *vertices = v; vertices++;
- v.X = (Real32)x2; v.U = u2; *vertices = v; vertices++;
- v.Z = (Real32)z1; v.V = v1; *vertices = v; vertices++;
+ v.X = (Real32)x1; v.Z = (Real32)z1; v.U = u1; v.V = v1; *vertices++ = v;
+ v.Z = (Real32)z2; v.V = v2; *vertices++ = v;
+ v.X = (Real32)x2; v.U = u2; *vertices++ = v;
+ v.Z = (Real32)z1; v.V = v1; *vertices++ = v;
}
}
}
diff --git a/src/Client/GraphicsAPI.h b/src/Client/GraphicsAPI.h
index f17dbfa2e..f042331d6 100644
--- a/src/Client/GraphicsAPI.h
+++ b/src/Client/GraphicsAPI.h
@@ -62,7 +62,7 @@ void Gfx_Clear(void);
void Gfx_ClearColour(PackedCol col);
void Gfx_SetDepthTest(bool enabled);
void Gfx_SetDepthTestFunc(Int32 compareFunc);
-void Gfx_SetColourWrite(bool enabled);
+void Gfx_SetColourWriteMask(bool r, bool g, bool b, bool a);
void Gfx_SetDepthWrite(bool enabled);
/* Creates a vertex buffer that can have its data dynamically updated. */
diff --git a/src/Client/PickedPosRenderer.c b/src/Client/PickedPosRenderer.c
index 67ae9cd0e..28320b13c 100644
--- a/src/Client/PickedPosRenderer.c
+++ b/src/Client/PickedPosRenderer.c
@@ -47,24 +47,27 @@ void PickedPosRenderer_Render(Real64 delta) {
}
void PickedPosRenderer_XQuad(Real32 x, Real32 z1, Real32 y1, Real32 z2, Real32 y2) {
- VertexP3fC4b_Set(pickedPos_ptr, x, y1, z1, pickedPos_col); pickedPos_ptr++;
- VertexP3fC4b_Set(pickedPos_ptr, x, y2, z1, pickedPos_col); pickedPos_ptr++;
- VertexP3fC4b_Set(pickedPos_ptr, x, y2, z2, pickedPos_col); pickedPos_ptr++;
- VertexP3fC4b_Set(pickedPos_ptr, x, y1, z2, pickedPos_col); pickedPos_ptr++;
-}
-
-void PickedPosRenderer_ZQuad(Real32 z, Real32 x1, Real32 y1, Real32 x2, Real32 y2) {
- VertexP3fC4b_Set(pickedPos_ptr, x1, y1, z, pickedPos_col); pickedPos_ptr++;
- VertexP3fC4b_Set(pickedPos_ptr, x1, y2, z, pickedPos_col); pickedPos_ptr++;
- VertexP3fC4b_Set(pickedPos_ptr, x2, y2, z, pickedPos_col); pickedPos_ptr++;
- VertexP3fC4b_Set(pickedPos_ptr, x2, y1, z, pickedPos_col); pickedPos_ptr++;
+ VertexP3fC4b v; v.X = x; v.Col = pickedPos_col;
+ v.Y = y1; v.Z = z1; *pickedPos_ptr++ = v;
+ v.Y = y2; *pickedPos_ptr++ = v;
+ v.Z = z2; *pickedPos_ptr++ = v;
+ v.Y = y1; *pickedPos_ptr++ = v;
}
void PickedPosRenderer_YQuad(Real32 y, Real32 x1, Real32 z1, Real32 x2, Real32 z2) {
- VertexP3fC4b_Set(pickedPos_ptr, x1, y, z1, pickedPos_col); pickedPos_ptr++;
- VertexP3fC4b_Set(pickedPos_ptr, x1, y, z2, pickedPos_col); pickedPos_ptr++;
- VertexP3fC4b_Set(pickedPos_ptr, x2, y, z2, pickedPos_col); pickedPos_ptr++;
- VertexP3fC4b_Set(pickedPos_ptr, x2, y, z1, pickedPos_col); pickedPos_ptr++;
+ VertexP3fC4b v; v.Y = y; v.Col = pickedPos_col;
+ v.X = x1; v.Z = z1; *pickedPos_ptr++ = v;
+ v.Z = z2; *pickedPos_ptr++ = v;
+ v.X = x2; *pickedPos_ptr++ = v;
+ v.Z = z1; *pickedPos_ptr++ = v;
+}
+
+void PickedPosRenderer_ZQuad(Real32 z, Real32 x1, Real32 y1, Real32 x2, Real32 y2) {
+ VertexP3fC4b v; v.Z = z; v.Col = pickedPos_col;
+ v.X = x1; v.Y = y1; *pickedPos_ptr++ = v;
+ v.Y = y2; *pickedPos_ptr++ = v;
+ v.X = x2; *pickedPos_ptr++ = v;
+ v.Y = y1; *pickedPos_ptr++ = v;
}
void PickedPosRenderer_UpdateState(PickedPos* selected) {
diff --git a/src/Client/Screens.c b/src/Client/Screens.c
index 02df20c37..72ecbdc65 100644
--- a/src/Client/Screens.c
+++ b/src/Client/Screens.c
@@ -456,7 +456,7 @@ void StatusScreen_Render(GuiElement* elem, Real64 delta) {
Widget_Render(&screen->Status, delta);
if (!Game_ClassicMode && Gui_Active == NULL) {
- if (StatusScreen_HacksChanged(screen)) { StatusScreen_UpdateHackState(screen, false); }
+ if (StatusScreen_HacksChanged(screen)) { StatusScreen_UpdateHackState(screen); }
StatusScreen_DrawPosition(screen);
Widget_Render(&screen->HackStates, delta);
}
@@ -974,7 +974,7 @@ bool HUDScreen_HandlesKeyDown(GuiElement* elem, Key key) {
if (key == playerListKey && handles) {
if (!screen->ShowingList && !ServerConnection_IsSinglePlayer) {
screen->WasShowingList = true;
- ContextRecreated();
+ HUDScreen_ContextRecreated(screen);
}
return true;
}
diff --git a/src/Client/SelectionBox.c b/src/Client/SelectionBox.c
index a63b85116..2077709fc 100644
--- a/src/Client/SelectionBox.c
+++ b/src/Client/SelectionBox.c
@@ -1,12 +1,16 @@
#include "SelectionBox.h"
+#include "ExtMath.h"
+#include "GraphicsAPI.h"
+#include "GraphicsCommon.h"
+#include "Event.h"
+#include "Funcs.h"
-void SelectionBox_Make(SelectionBox* box, Vector3I* p1, Vector3I* p2, PackedCol col) {
- box->ID = 0;
- box->MinDist = 0.0f; box->MaxDist = 0.0f;
- Vector3I_Min(&box->Min, p1, p2);
- Vector3I_Max(&box->Max, p1, p2);
- box->Col = col;
-}
+/* Data for a selection box. */
+typedef struct SelectionBox_ {
+ Vector3I Min, Max;
+ PackedCol Col;
+ Real32 MinDist, MaxDist;
+} SelectionBox;
void SelectionBox_Render(SelectionBox* box, VertexP3fC4b** vertices, VertexP3fC4b** lineVertices) {
Real32 offset = box->MinDist < 32.0f * 32.0f ? (1.0f / 32.0f) : (1.0f / 16.0f);
@@ -46,27 +50,197 @@ void SelectionBox_Render(SelectionBox* box, VertexP3fC4b** vertices, VertexP3fC4
void SelectionBox_VerQuad(VertexP3fC4b** vertices, PackedCol col,
Real32 x1, Real32 y1, Real32 z1, Real32 x2, Real32 y2, Real32 z2) {
VertexP3fC4b* ptr = *vertices;
- VertexP3fC4b_Set(ptr, x1, y1, z1, col); ptr++;
- VertexP3fC4b_Set(ptr, x1, y2, z1, col); ptr++;
- VertexP3fC4b_Set(ptr, x2, y2, z2, col); ptr++;
- VertexP3fC4b_Set(ptr, x2, y1, z2, col); ptr++;
+ VertexP3fC4b v; v.Col = col;
+
+ v.X = x1; v.Y = y1; v.Z = z1; *ptr++ = v;
+ v.Y = y2; *ptr++ = v;
+ v.X = x2; v.Z = z2; *ptr++ = v;
+ v.Y = y1; *ptr++ = v;
*vertices = ptr;
}
void SelectionBox_HorQuad(VertexP3fC4b** vertices, PackedCol col,
Real32 x1, Real32 z1, Real32 x2, Real32 z2, Real32 y) {
VertexP3fC4b* ptr = *vertices;
- VertexP3fC4b_Set(ptr, x1, y, z1, col); ptr++;
- VertexP3fC4b_Set(ptr, x1, y, z2, col); ptr++;
- VertexP3fC4b_Set(ptr, x2, y, z2, col); ptr++;
- VertexP3fC4b_Set(ptr, x2, y, z1, col); ptr++;
+ VertexP3fC4b v; v.Y = y; v.Col = col;
+
+ v.X = x1; v.Z = z1; *ptr++ = v;
+ v.Z = z2; *ptr++ = v;
+ v.X = x2; *ptr++ = v;
+ v.Z = z1; *ptr++ = v;
*vertices = ptr;
}
void SelectionBox_Line(VertexP3fC4b** vertices, PackedCol col,
Real32 x1, Real32 y1, Real32 z1, Real32 x2, Real32 y2, Real32 z2) {
- VertexP3fC4b* ptr = *vertices;
- VertexP3fC4b_Set(ptr, x1, y1, z1, col); ptr++;
- VertexP3fC4b_Set(ptr, x2, y2, z2, col); ptr++;
+ VertexP3fC4b* ptr = *vertices;
+ VertexP3fC4b v; v.Col = col;
+
+ v.X = x1; v.Y = y1; v.Z = z1; *ptr++ = v;
+ v.X = x2; v.Y = y2; v.Z = z2; *ptr++ = v;
*vertices = ptr;
+}
+
+
+Int32 SelectionBox_Compare(SelectionBox* a, SelectionBox* b) {
+ Real32 aDist, bDist;
+ if (a->MinDist == b->MinDist) {
+ aDist = a->MaxDist; bDist = b->MaxDist;
+ } else {
+ aDist = a->MinDist; bDist = b->MinDist;
+ }
+
+ /* 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;
+ return 0;
+}
+
+void SelectionBox_UpdateDist(Vector3 p, Real32 x2, Real32 y2, Real32 z2, Real32* closest, Real32* furthest) {
+ Real32 dx = x2 - p.X, dy = y2 - p.Y, dz = z2 - p.Z;
+ Real32 dist = dx * dx + dy * dy + dz * dz;
+
+ if (dist < *closest) *closest = dist;
+ if (dist > *furthest) *furthest = dist;
+}
+
+void SelectionBox_Intersect(SelectionBox* box, Vector3 origin) {
+ Vector3I min = box->Min, max = box->Max;
+ Real32 closest = MATH_POS_INF, furthest = -MATH_POS_INF;
+ /* Bottom corners */
+ SelectionBox_UpdateDist(origin, min.X, min.Y, min.Z, &closest, &furthest);
+ SelectionBox_UpdateDist(origin, max.X, min.Y, min.Z, &closest, &furthest);
+ SelectionBox_UpdateDist(origin, max.X, min.Y, max.Z, &closest, &furthest);
+ SelectionBox_UpdateDist(origin, min.X, min.Y, max.Z, &closest, &furthest);
+ /* Top corners */
+ SelectionBox_UpdateDist(origin, min.X, max.Y, min.Z, &closest, &furthest);
+ SelectionBox_UpdateDist(origin, max.X, max.Y, min.Z, &closest, &furthest);
+ SelectionBox_UpdateDist(origin, max.X, max.Y, max.Z, &closest, &furthest);
+ SelectionBox_UpdateDist(origin, min.X, max.Y, max.Z, &closest, &furthest);
+ box->MinDist = closest; box->MaxDist = furthest;
+}
+
+
+#define SELECTIONS_MAX 256
+#define SELECTIONS_VERTICES 24
+#define SELECTIONS_MAX_VERTICES SELECTIONS_MAX * SELECTIONS_VERTICES
+
+UInt32 selections_count;
+SelectionBox selections_list[SELECTIONS_MAX];
+UInt8 selections_ids[SELECTIONS_MAX];
+GfxResourceID selections_VB, selections_LineVB;
+bool selections_allocated;
+
+void Selections_Add(UInt8 id, Vector3I p1, Vector3I p2, PackedCol col) {
+ SelectionBox sel;
+ Vector3I_Min(&sel.Min, &p1, &p2);
+ Vector3I_Max(&sel.Max, &p1, &p2);
+ sel.Col = col;
+
+ Selections_Remove(id);
+ selections_list[selections_count] = sel;
+ selections_ids[selections_count] = id;
+ selections_count++;
+}
+
+void Selections_Remove(UInt8 id) {
+ UInt32 i;
+ for (i = 0; i < selections_count; i++) {
+ if (selections_ids[i] != id) continue;
+
+ for (; i < selections_count - 1; i++) {
+ selections_list[i] = selections_list[i + 1];
+ selections_ids[i] = selections_ids[i + 1];
+ }
+
+ selections_count--;
+ return;
+ }
+}
+
+void Selections_ContextLost(void) {
+ Gfx_DeleteVb(&selections_VB);
+ Gfx_DeleteVb(&selections_LineVB);
+}
+
+void Selections_ContextRecreated(void) {
+ if (!selections_allocated) return;
+ selections_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FC4B, SELECTIONS_MAX_VERTICES);
+ selections_LineVB = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FC4B, SELECTIONS_MAX_VERTICES);
+}
+
+void Selections_QuickSort(Int32 left, Int32 right) {
+ UInt8* values = selections_ids; UInt8 value;
+ SelectionBox* keys = selections_list; SelectionBox key;
+ while (left < right) {
+ Int32 i = left, j = right;
+ SelectionBox* pivot = &keys[(i + j) / 2];
+
+ /* partition the list */
+ while (i <= j) {
+ while (SelectionBox_Compare(pivot, &keys[i]) > 0) i++;
+ while (SelectionBox_Compare(pivot, &keys[j]) < 0) j--;
+ QuickSort_Swap_KV_Maybe();
+ }
+ /* recurse into the smaller subset */
+ QuickSort_Recurse(Selections_QuickSort)
+ }
+}
+
+void Selections_Render(Real64 delta) {
+ if (selections_count == 0 || Gfx_LostContext) return;
+ /* TODO: Proper selection box sorting. But this is very difficult because
+ we can have boxes within boxes, intersecting boxes, etc. Probably not worth it. */
+ Vector3 camPos = Game_CurrentCameraPos;
+ UInt32 i;
+ for (i = 0; i < selections_count; i++) {
+ SelectionBox_Intersect(&selections_list[i], camPos);
+ }
+ Selections_QuickSort(0, selections_count - 1);
+
+ if (!selections_allocated) { /* lazy init as most servers don't use this */
+ Selections_ContextRecreated();
+ selections_allocated = true;
+ }
+
+ VertexP3fC4b vertices[SELECTIONS_MAX_VERTICES]; VertexP3fC4b* ptr = vertices;
+ VertexP3fC4b lineVertices[SELECTIONS_MAX_VERTICES]; VertexP3fC4b* linePtr = lineVertices;
+ for (i = 0; i < selections_count; i++) {
+ SelectionBox_Render(&selections_list[i], &ptr, &linePtr);
+ }
+
+ Gfx_SetBatchFormat(VERTEX_FORMAT_P3FC4B);
+ GfxCommon_UpdateDynamicVb_Lines(selections_LineVB, lineVertices,
+ selections_count * SELECTIONS_VERTICES);
+
+ Gfx_SetDepthWrite(false);
+ Gfx_SetAlphaBlending(true);
+ GfxCommon_UpdateDynamicVb_IndexedTris(selections_VB, vertices,
+ selections_count * SELECTIONS_VERTICES);
+ Gfx_SetDepthWrite(true);
+ Gfx_SetAlphaBlending(false);
+}
+
+void Selections_Init(void) {
+ Event_RegisterVoid(&GfxEvents_ContextLost, NULL, Selections_ContextLost);
+ Event_RegisterVoid(&GfxEvents_ContextRecreated, NULL, Selections_ContextRecreated);
+}
+
+void Selections_Reset(void) {
+ selections_count = 0;
+}
+
+void Selections_Free(void) {
+ Selections_ContextLost();
+ Event_UnregisterVoid(&GfxEvents_ContextLost, NULL, Selections_ContextLost);
+ Event_UnregisterVoid(&GfxEvents_ContextRecreated, NULL, Selections_ContextRecreated);
+}
+
+IGameComponent Selections_MakeComponent(void) {
+ IGameComponent comp = IGameComponent_MakeEmpty();
+ comp.Init = Selections_Init;
+ comp.Free = Selections_Free;
+ comp.Reset = Selections_Reset;
+ comp.OnNewMap = Selections_Reset;
+ return comp;
}
\ No newline at end of file
diff --git a/src/Client/SelectionBox.h b/src/Client/SelectionBox.h
index 58c59c93c..40f06a46a 100644
--- a/src/Client/SelectionBox.h
+++ b/src/Client/SelectionBox.h
@@ -1,35 +1,13 @@
#ifndef CC_SELECTIONBOX_H
#define CC_SELECTIONBOX_H
#include "Typedefs.h"
-#include "PackedCol.h"
-#include "Vectors.h"
#include "VertexStructs.h"
+#include "GameStructs.h"
+#include "Vectors.h"
/* Describes a selection box, and contains methods related to the selection box.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/
-/* Data for a selection box. */
-typedef struct SelectionBox_ {
- /* ID of this selection box.*/
- UInt8 ID;
- /* Minimum corner of the box. */
- Vector3I Min;
- /* Maximum corner of the box. */
- Vector3I Max;
- /* Colour of this box. */
- PackedCol Col;
- /* Closest distance to player of any of the eight corners of the box. */
- Real32 MinDist;
- /* Furthest distance to player of any of the eight corners of the box. */
- Real32 MaxDist;
-} SelectionBox;
-
-
-/* Constructs a selection box. */
-void SelectionBox_Make(SelectionBox* box, Vector3I* p1, Vector3I* p2, PackedCol col);
-/* Constructs the vertices and line vertices for a selection box. */
-void SelectionBox_Render(SelectionBox* box, VertexP3fC4b** vertices, VertexP3fC4b** lineVertices);
-
/* Draws a vertical quad. */
void SelectionBox_VerQuad(VertexP3fC4b** vertices, PackedCol col,
Real32 x1, Real32 y1, Real32 z1, Real32 x2, Real32 y2, Real32 z2);
@@ -39,4 +17,9 @@ void SelectionBox_HorQuad(VertexP3fC4b** vertices, PackedCol col,
/* Draws a line between two points. */
void SelectionBox_Line(VertexP3fC4b** vertices, PackedCol col,
Real32 x1, Real32 y1, Real32 z1, Real32 x2, Real32 y2, Real32 z2);
+
+IGameComponent Selections_MakeComponent(void);
+void Selections_Render(Real64 delta);
+void Selections_Add(UInt8 id, Vector3I p1, Vector3I p2, PackedCol col);
+void Selections_Remove(UInt8 id);
#endif
\ No newline at end of file
diff --git a/src/Client/WeatherRenderer.c b/src/Client/WeatherRenderer.c
index 4e6618264..714e2a8f5 100644
--- a/src/Client/WeatherRenderer.c
+++ b/src/Client/WeatherRenderer.c
@@ -151,15 +151,15 @@ void WeatherRenderer_Render(Real64 deltaTime) {
Real32 x1 = (Real32)x, y1 = (Real32)y, z1 = (Real32)z;
Real32 x2 = (Real32)(x + 1), y2 = (Real32)(y + height), z2 = (Real32)(z + 1);
- v.X = x1; v.Y = y1; v.Z = z1; v.U = 0.0f; v.V = v1; *ptr = v; ptr++;
- v.Y = y2; v.V = v2; *ptr = v; ptr++;
- v.X = x2; v.Z = z2; v.U = 1.0f; *ptr = v; ptr++;
- v.Y = y1; v.V = v1; *ptr = v; ptr++;
+ v.X = x1; v.Y = y1; v.Z = z1; v.U = 0.0f; v.V = v1; *ptr++ = v;
+ v.Y = y2; v.V = v2; *ptr++ = v;
+ v.X = x2; v.Z = z2; v.U = 1.0f; *ptr++ = v;
+ v.Y = y1; v.V = v1; *ptr++ = v;
- v.Z = z1; *ptr = v; ptr++;
- v.Y = y2; v.V = v2; *ptr = v; ptr++;
- v.X = x1; v.Z = z2; v.U = 0.0f; *ptr = v; ptr++;
- v.Y = y1; v.V = v1; *ptr = v; ptr++;
+ v.Z = z1; *ptr++ = v;
+ v.Y = y2; v.V = v2; *ptr++ = v;
+ v.X = x1; v.Z = z2; v.U = 0.0f; *ptr++ = v;
+ v.Y = y1; v.V = v1; *ptr++ = v;
}
}
diff --git a/src/Client/Widgets.c b/src/Client/Widgets.c
index 141ea0567..a2d7e2525 100644
--- a/src/Client/Widgets.c
+++ b/src/Client/Widgets.c
@@ -1993,7 +1993,7 @@ Int32 PlayerListWidget_GetGroupCount(PlayerListWidget* widget, UInt16 id, Int32
Int32 PlayerListWidget_PlayerCompare(UInt16 x, UInt16 y) {
UInt8 xRank = TabList_GroupRanks[x];
UInt8 yRank = TabList_GroupRanks[y];
- if (xRank != yRank) return (xRank < yRank ? 1 : -1);
+ if (xRank != yRank) return (xRank < yRank ? -1 : 1);
UInt8 xNameBuffer[String_BufferSize(STRING_SIZE)];
String xName = String_InitAndClearArray(xNameBuffer);