Skip to content
This repository was archived by the owner on Feb 19, 2019. It is now read-only.

Commit 0c63f99

Browse files
committed
Updated Feather, Renamed 'ClientUtils' to 'ClientAPIUtils'
1 parent 96cf7fd commit 0c63f99

22 files changed

Lines changed: 816 additions & 678 deletions

src/main/java/me/zero/client/api/command/Command.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package me.zero.client.api.command;
1818

1919
import me.zero.client.api.command.exception.CommandInitException;
20-
import me.zero.client.api.util.ClientUtils;
20+
import me.zero.client.api.util.ClientAPIUtils;
2121

2222
/**
2323
* @author Brady
@@ -46,7 +46,7 @@ private void setup(String[] headers, String description, String[] syntax) {
4646
this.description = description;
4747
this.syntax = syntax;
4848

49-
if (ClientUtils.containsNull(headers, description, syntax))
49+
if (ClientAPIUtils.containsNull(headers, description, syntax))
5050
throw new NullPointerException("One or more Command members were null!");
5151
}
5252

src/main/java/me/zero/client/api/module/Module.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import me.zero.client.api.exception.ActionNotSupportedException;
2222
import me.zero.client.api.manage.Node;
2323
import me.zero.client.api.module.exception.ModuleInitException;
24-
import me.zero.client.api.util.ClientUtils;
24+
import me.zero.client.api.util.ClientAPIUtils;
2525
import me.zero.client.api.util.keybind.Keybind;
2626
import org.lwjgl.input.Keyboard;
2727

@@ -102,7 +102,7 @@ private void setup(String name, String description, int bind) {
102102
.filter(clazz -> clazz.isAnnotationPresent(Category.class))
103103
.findFirst().orElse(Category.Default.class);
104104

105-
if (ClientUtils.containsNull(name, description, type))
105+
if (ClientAPIUtils.containsNull(name, description, type))
106106
throw new NullPointerException("One or more Mod members were null!");
107107
}
108108

src/main/java/me/zero/client/api/util/ClientUtils.java renamed to src/main/java/me/zero/client/api/util/ClientAPIUtils.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
import java.util.Arrays;
2323

2424
/**
25-
* Utils that the Client API uses
25+
* Contains methods that ClientAPI uses throughout its code.
2626
*
2727
* @author Brady
2828
* @since 1/20/2017 12:00 PM
2929
*/
30-
public final class ClientUtils {
30+
public final class ClientAPIUtils {
3131

32-
private ClientUtils() {}
32+
private ClientAPIUtils() {}
3333

3434
/**
3535
* Concatenates an array of generic arrays
@@ -102,4 +102,25 @@ public static <T> T objectFrom(T object, T[] array) {
102102
}
103103
}
104104
}
105+
106+
/**
107+
* Determines if the specified array of generics contains
108+
* matching members.
109+
*
110+
* @param objects Objects being checked
111+
* @return Whether or not all members match
112+
*/
113+
@SafeVarargs
114+
public static <T> boolean matchingMembers(T... objects) {
115+
T baseline = null;
116+
boolean set = false;
117+
for (T object : objects) {
118+
if (!set)
119+
baseline = object;
120+
if (object != baseline)
121+
return false;
122+
set = true;
123+
}
124+
return true;
125+
}
105126
}

src/main/java/me/zero/client/api/util/render/RenderUtils.java

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
import me.zero.client.api.util.render.gl.GlUtils;
2323
import net.minecraft.client.renderer.GlStateManager;
2424
import net.minecraft.client.renderer.OpenGlHelper;
25-
import pw.knx.feather.tessellate.GrowingTess;
26-
import pw.knx.feather.tessellate.OffsetTess;
25+
import pw.knx.feather.tessellate.Tessellator;
2726

2827
import java.util.ArrayList;
2928
import java.util.List;
@@ -43,7 +42,7 @@ private RenderUtils() {}
4342
/**
4443
* Instance of the Tessellator
4544
*/
46-
public static final OffsetTess tessellator = new OffsetTess(new GrowingTess(4));
45+
public static final Tessellator tessellator = Tessellator.createExpanding(4, 1, 2);
4746

4847
/**
4948
* Stores ClientState Gl Caps when setting up
@@ -142,7 +141,7 @@ public static void drawLine(float x, float y, float z, float x1, float y1, float
142141

143142
setupRender(true);
144143
setupClientState(GLClientState.VERTEX, true);
145-
tessellator.vertex(x, y, z).vertex(x1, y1, z1).draw(GL_LINE_STRIP);
144+
tessellator.addVertex(x, y, z).addVertex(x1, y1, z1).draw(GL_LINE_STRIP);
146145
setupClientState(GLClientState.VERTEX, false);
147146
setupRender(false);
148147
}
@@ -159,10 +158,10 @@ public static void drawFlippedTexturedRect(float x1, float y1, float x2, float y
159158
setupClientState(GLClientState.TEXTURE, true);
160159

161160
tessellator
162-
.vertex(x1, y2, 0).texture(0, 0)
163-
.vertex(x2, y2, 0).texture(1, 0)
164-
.vertex(x2, y1, 0).texture(1, 1)
165-
.vertex(x1, y1, 0).texture(0, 1)
161+
.addVertex(x1, y2, 0).setTexture(0, 0)
162+
.addVertex(x2, y2, 0).setTexture(1, 0)
163+
.addVertex(x2, y1, 0).setTexture(1, 1)
164+
.addVertex(x1, y1, 0).setTexture(0, 1)
166165
.draw(GL_QUADS);
167166

168167
setupClientState(GLClientState.TEXTURE, false);
@@ -180,10 +179,10 @@ public static void drawReflectedTexturedRect(float x1, float y1, float x2, float
180179
setupClientState(GLClientState.TEXTURE, true);
181180

182181
tessellator
183-
.vertex(x1, y2, 0).texture(1, 0)
184-
.vertex(x2, y2, 0).texture(1, 0)
185-
.vertex(x2, y1, 0).texture(0, 1)
186-
.vertex(x1, y1, 0).texture(1, 1)
182+
.addVertex(x1, y2, 0).setTexture(1, 0)
183+
.addVertex(x2, y2, 0).setTexture(1, 0)
184+
.addVertex(x2, y1, 0).setTexture(0, 1)
185+
.addVertex(x1, y1, 0).setTexture(1, 1)
187186
.draw(GL_QUADS);
188187

189188
setupClientState(GLClientState.TEXTURE, false);
@@ -203,7 +202,7 @@ public static void rectangle(float x1, float y1, float x2, float y2, int color)
203202

204203
setupRender(true);
205204
setupClientState(GLClientState.VERTEX, true);
206-
tessellator.vertex(x1, y2, 0).vertex(x2, y2, 0).vertex(x2, y1, 0).vertex(x1, y1, 0).draw(GL_QUADS);
205+
tessellator.addVertex(x1, y2, 0).addVertex(x2, y2, 0).addVertex(x2, y1, 0).addVertex(x1, y1, 0).draw(GL_QUADS);
207206
setupClientState(GLClientState.VERTEX, false);
208207
setupRender(false);
209208
}
@@ -232,30 +231,23 @@ private static void rectangleGradient(float x1, float y1, float x2, float y2, in
232231
if (color.length == 0)
233232
throw new RuntimeException("At least one set of colors should be supplied");
234233

235-
float[] r = new float[color.length];
236-
float[] g = new float[color.length];
237-
float[] b = new float[color.length];
238-
float[] a = new float[color.length];
239-
for (int i = 0; i < color.length; i++) {
240-
float[] c = Colors.getColor(color[i]);
241-
r[i] = c[0]; g[i] = c[1]; b[i] = c[2]; a[i] = c[3];
242-
}
234+
int c1, c2, c3, c4;
243235

244236
if (color.length == 1) {
245-
r = new float[] { r[0], r[0], r[0], r[0] };
246-
g = new float[] { g[0], g[0], g[0], g[0] };
247-
b = new float[] { b[0], b[0], b[0], b[0] };
248-
a = new float[] { a[0], a[0], a[0], a[0] };
237+
c1 = color[0];
238+
c2 = color[1];
239+
c3 = color[2];
240+
c4 = color[3];
249241
} else if (color.length > 1 && color.length < 4) {
250-
r = new float[] { r[0], r[0], r[1], r[1] };
251-
g = new float[] { g[0], g[0], g[1], g[1] };
252-
b = new float[] { b[0], b[0], b[1], b[1] };
253-
a = new float[] { a[0], a[0], a[1], a[1] };
242+
c1 = color[0];
243+
c2 = color[0];
244+
c3 = color[1];
245+
c4 = color[2];
254246
} else {
255-
r = new float[] { r[0], r[1], r[2], r[3] };
256-
g = new float[] { g[0], g[1], g[2], g[3] };
257-
b = new float[] { b[0], b[1], b[2], b[3] };
258-
a = new float[] { a[0], a[1], a[2], a[3] };
247+
c1 = color[0];
248+
c2 = color[1];
249+
c3 = color[2];
250+
c4 = color[3];
259251
}
260252

261253
setupRender(true);
@@ -264,14 +256,13 @@ private static void rectangleGradient(float x1, float y1, float x2, float y2, in
264256
setupClientState(GLClientState.COLOR, true);
265257

266258
tessellator
267-
.color(r[0], g[0], b[0], a[0]).vertex(x1, y2, 0)
268-
.color(r[1], g[1], b[1], a[1]).vertex(x2, y2, 0)
269-
.color(r[2], g[2], b[2], a[2]).vertex(x2, y1, 0)
270-
.color(r[3], g[3], b[3], a[3]).vertex(x1, y1, 0)
259+
.setColor(c1).addVertex(x1, y2, 0)
260+
.setColor(c2).addVertex(x2, y2, 0)
261+
.setColor(c3).addVertex(x2, y1, 0)
262+
.setColor(c4).addVertex(x1, y1, 0)
271263
.draw(GL_QUADS);
272264

273265
setupClientState(GLClientState.COLOR, false);
274-
GlStateManager.shadeModel(GL_FLAT);
275266
setupRender(false);
276267
}
277268

src/main/java/me/zero/client/api/value/Values.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package me.zero.client.api.value;
1818

1919
import me.zero.client.api.exception.ValueException;
20-
import me.zero.client.api.util.ClientUtils;
20+
import me.zero.client.api.util.ClientAPIUtils;
2121
import me.zero.client.api.util.annotation.Label;
2222
import me.zero.client.api.value.annotation.*;
2323
import me.zero.client.api.value.holder.IValueHolder;
@@ -131,7 +131,7 @@ private static Value getValue(Object parent, Field field) {
131131
* @param data The resolver data for the annotation
132132
*/
133133
public static void define(Class<?> type, ResolverData data) {
134-
if (ClientUtils.containsNull(type, data))
134+
if (ClientAPIUtils.containsNull(type, data))
135135
throw new NullPointerException("One or more parameters were null");
136136

137137
if (RESOLVERS.get(type) != null)

src/main/java/me/zero/client/api/value/type/MultiType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
package me.zero.client.api.value.type;
1818

19-
import me.zero.client.api.util.ClientUtils;
19+
import me.zero.client.api.util.ClientAPIUtils;
2020
import me.zero.client.api.value.Value;
2121
import org.apache.commons.lang3.ArrayUtils;
2222

@@ -43,7 +43,7 @@ public MultiType(String name, String id, String description, Object object, Fiel
4343

4444
@Override
4545
public final void setValue(String value) {
46-
super.setValue(ClientUtils.objectFrom(value, values));
46+
super.setValue(ClientAPIUtils.objectFrom(value, values));
4747
}
4848

4949
/**
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package pw.knx.feather;
2+
3+
import pw.knx.feather.font.FontCache;
4+
import pw.knx.feather.font.FontGlyph;
5+
import pw.knx.feather.font.GlyphLayout;
6+
import pw.knx.feather.tessellate.Tessellator;
7+
import pw.knx.feather.texture.Texture;
8+
9+
import java.awt.*;
10+
import java.nio.ByteBuffer;
11+
import java.nio.ByteOrder;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
15+
import static org.lwjgl.opengl.GL11.*;
16+
import static org.lwjgl.opengl.GL15.*;
17+
18+
/**
19+
* The central class of the Feather library.
20+
*
21+
* Basically functions as a convenient state manager for OpenGL,
22+
* wrapping the most commonly used functions in intuitive, intelligent,
23+
* chainable methods. In this way, Feather reduces your required knowledge of
24+
* obscure OpenGL constants and compacts otherwise painfully verbose state management code.
25+
*
26+
* Probably going to use the enum singleton pattern for simplicity, thread safety and global access.
27+
* This should not pose an inconvenience since LWJGL only allows once thread to interact
28+
* with OpenGL anyways.
29+
*
30+
* WIP
31+
*
32+
* @author KNOXDEV
33+
* @since 6/7/2017 6:54 PM
34+
*/
35+
public enum Feather {
36+
feather;
37+
38+
/**
39+
* The simple Feather Tessellator we've designated to render our glyphs.
40+
*/
41+
private final Tessellator tess = Tessellator.createExpanding(4 * 4, 1, 2);
42+
43+
private final Map<Font, FontCache> fonts = new HashMap<>();
44+
private FontCache currentFont;
45+
46+
47+
/*
48+
* State Management - Most of these return Feather so they can be chained.
49+
*/
50+
51+
/**
52+
* Binds an existing texture object to the working texture2D buffer
53+
*
54+
* @param id The OpenGL ID of the texture object to be bound
55+
* @return the Feather manager, for additional chaining
56+
*/
57+
public Feather bindTexture(int id) {
58+
glBindTexture(GL_TEXTURE_2D, id);
59+
return this;
60+
}
61+
62+
/**
63+
* Binds an existing buffer object to the working array buffer
64+
*
65+
* @param id The OpenGL ID of the buffer object to be bound
66+
* @return the Feather manager, for additional chaining
67+
*/
68+
public Feather bindBuffer(int id) {
69+
glBindBuffer(GL_ARRAY_BUFFER, id);
70+
return this;
71+
}
72+
73+
74+
/*
75+
* Allocators - Methods that wrap Java's unfortunate Buffer API
76+
*/
77+
78+
/**
79+
* Allocates a ByteBuffer in the platform's native byte order
80+
*
81+
* @param capacity the size of the Buffer to be allocated in bytes
82+
* @return the allocated ByteBuffer
83+
*/
84+
public synchronized ByteBuffer allocateBuffer(int capacity) {
85+
return ByteBuffer.allocateDirect(capacity).order(ByteOrder.nativeOrder());
86+
}
87+
88+
89+
/*
90+
* Basic Rendering Routines
91+
*/
92+
93+
public Feather setFont(Font font) {
94+
// holy shit streams
95+
currentFont = fonts.computeIfAbsent(font, FontCache::from);
96+
return this;
97+
}
98+
99+
public Feather drawString(String str, float x, float y) {
100+
if(currentFont == null)
101+
throw new RuntimeException("You must first set the Font to draw");
102+
103+
/* Make sure the entire string is cached before rendering and return its glyph representation */
104+
final GlyphLayout entry = currentFont.cacheString(str);
105+
106+
/* Track which texture is currently bound to minimize the number of glBindTexture() and Tessellator.draw() calls needed */
107+
int boundTex = 0;
108+
109+
/* Cycle through the Glyphs to be rendered */
110+
for (FontGlyph glyph : entry.glyphs) {
111+
final Texture texture = glyph.texture;
112+
113+
/*
114+
* Make sure the OpenGL texture storing this glyph's image is bound (if not already bound). All pending glyphs in the
115+
* Tessellator's vertex array must be drawn before switching textures, otherwise they would erroneously use the new
116+
* texture as well.
117+
*/
118+
if (boundTex != texture.id()) {
119+
if (boundTex != 0)
120+
tess.draw(GL_QUADS);
121+
boundTex = texture.bind().id();
122+
}
123+
final float x1 = x + glyph.x;
124+
final float x2 = x1 + texture.width();
125+
final float y1 = y + glyph.y;
126+
final float y2 = y1 + texture.height();
127+
tess.setTexture(texture.u(), texture.v()).addVertex(x1, y1, 0);
128+
tess.setTexture(texture.u(), texture.v1()).addVertex(x1, y2, 0);
129+
tess.setTexture(texture.u1(), texture.v1()).addVertex(x2, y2, 0);
130+
tess.setTexture(texture.u1(), texture.v()).addVertex(x2, y1, 0);
131+
}
132+
133+
/* Draw any remaining glyphs in the Tessellator's vertex array (there should be at least one glyph pending) */
134+
tess.draw(GL_QUADS);
135+
136+
return this;
137+
}
138+
}

0 commit comments

Comments
 (0)