Loading screen: logo rotation is now optional; initial support for animated textures - animation rate is fixed for now.

This commit is contained in:
RainWarrior 2015-04-25 05:12:02 +03:00
parent 1fdd18398e
commit 794ff1d1b4
2 changed files with 243 additions and 115 deletions

View file

@ -1,19 +1,25 @@
package cpw.mods.fml.client;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.lang.Thread.UncaughtExceptionHandler;
import java.nio.IntBuffer;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.resources.FileResourcePack;
import net.minecraft.client.resources.FolderResourcePack;
import net.minecraft.client.resources.IResourcePack;
@ -22,11 +28,13 @@ import net.minecraft.util.ResourceLocation;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.Level;
import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.Drawable;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.SharedDrawable;
import org.lwjgl.util.glu.GLU;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.FMLLog;
@ -53,17 +61,16 @@ public class SplashProgress
private static final IResourcePack mcPack = Minecraft.getMinecraft().mcDefaultResourcePack;
private static final IResourcePack fmlPack = createFmlResourcePack();
private static int fontTexture;
private static ResourceLocation fontLocation = new ResourceLocation("textures/font/ascii.png");
private static int logoTexture;
private static ResourceLocation logoLocation = new ResourceLocation("textures/gui/title/mojang.png");
private static int forgeTexture;
private static ResourceLocation forgeLocation = new ResourceLocation("fml", "textures/gui/forge.png");
private static Texture fontTexture;
private static Texture logoTexture;
private static Texture forgeTexture;
private static ResourceLocation configLocation = new ResourceLocation("fml", "splash.properties");
private static final Properties config = loadConfig();
private static final boolean enabled = Boolean.parseBoolean(config.getProperty("enabled"));
private static final boolean rotate = Boolean.parseBoolean(config.getProperty("rotate"));
private static final int logoOffset = getInt("logoOffset");
private static final int backgroundColor = getInt("background");
private static final int fontColor = getInt("font");
private static final int barBorderColor = getInt("barBorder");
@ -78,9 +85,9 @@ public class SplashProgress
{
public String call() throws Exception
{
return "' Vendor: '" + GL11.glGetString(GL11.GL_VENDOR) +
"' Version: '" + GL11.glGetString(GL11.GL_VERSION) +
"' Renderer: '" + GL11.glGetString(GL11.GL_RENDERER) +
return "' Vendor: '" + glGetString(GL_VENDOR) +
"' Version: '" + glGetString(GL_VERSION) +
"' Renderer: '" + glGetString(GL_RENDERER) +
"'";
}
@ -91,12 +98,6 @@ public class SplashProgress
});
CrashReport report = CrashReport.makeCrashReport(new Throwable(), "Loading screen debug info");
System.out.println(report.getCompleteReport());
fontTexture = GL11.glGenTextures();
loadTexture(mcPack, fontTexture, fontLocation);
logoTexture = GL11.glGenTextures();
loadTexture(mcPack, logoTexture, logoLocation);
forgeTexture = GL11.glGenTextures();
loadTexture(fmlPack, forgeTexture, forgeLocation);
try
{
@ -120,6 +121,12 @@ public class SplashProgress
public void run()
{
setGL();
fontTexture = new Texture(mcPack, new ResourceLocation("textures/font/ascii.png"));
logoTexture = new Texture(mcPack, new ResourceLocation("textures/gui/title/mojang.png"));
forgeTexture = new Texture(fmlPack, new ResourceLocation(config.getProperty("forgeTexture")));
glEnable(GL_TEXTURE_2D);
fontRenderer = new SplashFontRenderer();
glDisable(GL_TEXTURE_2D);
while(!done)
{
ProgressBar first = null, penult = null, last = null;
@ -134,72 +141,83 @@ public class SplashProgress
}
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT);
// matrix setup
int w = Display.getWidth();
int h = Display.getHeight();
GL11.glViewport(0, 0, w, h);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(320 - w/2, 320 + w/2, 240 + h/2, 240 - h/2, -1, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(320 - w/2, 320 + w/2, 240 + h/2, 240 - h/2, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// mojang logo
setColor(backgroundColor);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, logoTexture);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(320 - 256, 240 - 256);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(320 - 256, 240 + 256);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(320 + 256, 240 + 256);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(320 + 256, 240 - 256);
GL11.glEnd();
GL11.glDisable(GL11.GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
logoTexture.bind();
glBegin(GL_QUADS);
logoTexture.texCoord(0, 0, 0);
glVertex2f(320 - 256, 240 - 256);
logoTexture.texCoord(0, 0, 1);
glVertex2f(320 - 256, 240 + 256);
logoTexture.texCoord(0, 1, 1);
glVertex2f(320 + 256, 240 + 256);
logoTexture.texCoord(0, 1, 0);
glVertex2f(320 + 256, 240 - 256);
glEnd();
glDisable(GL_TEXTURE_2D);
// bars
if(first != null)
{
GL11.glPushMatrix();
GL11.glTranslatef(320 - (float)barWidth / 2, 310, 0);
glPushMatrix();
glTranslatef(320 - (float)barWidth / 2, 310, 0);
drawBar(first);
if(penult != null)
{
GL11.glTranslatef(0, barOffset, 0);
glTranslatef(0, barOffset, 0);
drawBar(penult);
}
if(last != null)
{
GL11.glTranslatef(0, barOffset, 0);
glTranslatef(0, barOffset, 0);
drawBar(last);
}
GL11.glPopMatrix();
glPopMatrix();
}
angle += 1;
// forge logo
setColor(backgroundColor);
GL11.glTranslatef(680, 420, 0);
GL11.glRotatef(angle, 0, 0, 1);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, forgeTexture);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(-50, -50);
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(-50, 50);
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(50, 50);
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(50, -50);
GL11.glEnd();
GL11.glDisable(GL11.GL_TEXTURE_2D);
float fw = (float)forgeTexture.getWidth() / 2;
float fh = (float)forgeTexture.getHeight() / 2;
if(rotate)
{
float sh = Math.max(fw, fh);
glTranslatef(320 + w/2 - sh - logoOffset, 240 + h/2 - sh - logoOffset, 0);
glRotatef(angle, 0, 0, 1);
}
else
{
glTranslatef(320 + w/2 - fw - logoOffset, 240 + h/2 - fh - logoOffset, 0);
}
int f = (angle / 10) % forgeTexture.getFrames();
glEnable(GL_TEXTURE_2D);
forgeTexture.bind();
glBegin(GL_QUADS);
forgeTexture.texCoord(f, 0, 0);
glVertex2f(-fw, -fh);
forgeTexture.texCoord(f, 0, 1);
glVertex2f(-fw, fh);
forgeTexture.texCoord(f, 1, 1);
glVertex2f(fw, fh);
forgeTexture.texCoord(f, 1, 0);
glVertex2f(fw, -fh);
glEnd();
glDisable(GL_TEXTURE_2D);
Display.update();
if(pause)
@ -207,64 +225,56 @@ public class SplashProgress
clearGL();
setGL();
}
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
Display.sync(100);
}
clearGL();
}
private void setColor(int color)
{
GL11.glColor3ub((byte)((color >> 16) & 0xFF), (byte)((color >> 8) & 0xFF), (byte)(color & 0xFF));
glColor3ub((byte)((color >> 16) & 0xFF), (byte)((color >> 8) & 0xFF), (byte)(color & 0xFF));
}
private void drawBox(int w, int h)
{
GL11.glBegin(GL11.GL_QUADS);
GL11.glVertex2f(0, 0);
GL11.glVertex2f(0, h);
GL11.glVertex2f(w, h);
GL11.glVertex2f(w, 0);
GL11.glEnd();
glBegin(GL_QUADS);
glVertex2f(0, 0);
glVertex2f(0, h);
glVertex2f(w, h);
glVertex2f(w, 0);
glEnd();
}
private void drawBar(ProgressBar b)
{
GL11.glPushMatrix();
glPushMatrix();
// title - message
setColor(fontColor);
GL11.glScalef(2, 2, 1);
GL11.glEnable(GL11.GL_TEXTURE_2D);
glScalef(2, 2, 1);
glEnable(GL_TEXTURE_2D);
fontRenderer.drawString(b.getTitle() + " - " + b.getMessage(), 0, 0, 0x000000);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glPopMatrix();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
// border
GL11.glPushMatrix();
GL11.glTranslatef(0, textHeight2, 0);
glPushMatrix();
glTranslatef(0, textHeight2, 0);
setColor(barBorderColor);
drawBox(barWidth, barHeight);
// interior
setColor(barBackgroundColor);
GL11.glTranslatef(1, 1, 0);
glTranslatef(1, 1, 0);
drawBox(barWidth - 2, barHeight - 2);
// slidy part
setColor(barColor);
drawBox((barWidth - 2) * b.getStep() / b.getSteps(), barHeight - 2);
// progress text
String progress = "" + b.getStep() + "/" + b.getSteps();
GL11.glTranslatef(((float)barWidth - 2) / 2 - fontRenderer.getStringWidth(progress), 2, 0);
glTranslatef(((float)barWidth - 2) / 2 - fontRenderer.getStringWidth(progress), 2, 0);
setColor(fontColor);
GL11.glScalef(2, 2, 1);
GL11.glEnable(GL11.GL_TEXTURE_2D);
glScalef(2, 2, 1);
glEnable(GL_TEXTURE_2D);
fontRenderer.drawString(progress, 0, 0, 0x000000);
GL11.glPopMatrix();
glPopMatrix();
}
private void setGL()
@ -279,17 +289,11 @@ public class SplashProgress
e.printStackTrace();
throw new RuntimeException(e);
}
GL11.glClearColor((float)((backgroundColor >> 16) & 0xFF) / 0xFF, (float)((backgroundColor >> 8) & 0xFF) / 0xFF, (float)(backgroundColor & 0xFF) / 0xFF, 1);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glEnable(GL11.GL_TEXTURE_2D);
if(fontRenderer == null)
{
fontRenderer = new SplashFontRenderer();
}
GL11.glDisable(GL11.GL_TEXTURE_2D);
glClearColor((float)((backgroundColor >> 16) & 0xFF) / 0xFF, (float)((backgroundColor >> 8) & 0xFF) / 0xFF, (float)(backgroundColor & 0xFF) / 0xFF, 1);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
private void clearGL()
@ -298,11 +302,11 @@ public class SplashProgress
mc.displayWidth = Display.getWidth();
mc.displayHeight = Display.getHeight();
mc.resize(mc.displayWidth, mc.displayHeight);
GL11.glClearColor(1, 1, 1, 1);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LEQUAL);
GL11.glEnable(GL11.GL_ALPHA_TEST);
GL11.glAlphaFunc(GL11.GL_GREATER, .1f);
glClearColor(1, 1, 1, 1);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, .1f);
try
{
Display.getDrawable().releaseContext();
@ -394,9 +398,9 @@ public class SplashProgress
thread.join();
d.releaseContext();
Display.getDrawable().makeCurrent();
GL11.glDeleteTextures(fontTexture);
GL11.glDeleteTextures(logoTexture);
GL11.glDeleteTextures(forgeTexture);
fontTexture.delete();
logoTexture.delete();
forgeTexture.delete();
}
catch (Exception e)
{
@ -443,22 +447,134 @@ public class SplashProgress
return Integer.decode(config.getProperty(name));
}
private static void loadTexture(IResourcePack pack, int name, ResourceLocation location)
private static final IntBuffer buf = BufferUtils.createIntBuffer(4 * 1024 * 1024);
private static class Texture
{
InputStream s = null;
try
private final ResourceLocation location;
private final int name;
private final int width;
private final int height;
private final int frames;
private final int size;
public Texture(IResourcePack pack, ResourceLocation location)
{
s = pack.getInputStream(location);
TextureUtil.uploadTextureImageAllocate(name, ImageIO.read(pack.getInputStream(location)), false, false);
InputStream s = null;
try
{
this.location = location;
s = pack.getInputStream(location);
ImageInputStream stream = ImageIO.createImageInputStream(s);
Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
if(!readers.hasNext()) throw new IOException("No suitable reader found for image" + location);
ImageReader reader = readers.next();
reader.setInput(stream);
frames = reader.getNumImages(true);
BufferedImage[] images = new BufferedImage[frames];
for(int i = 0; i < frames; i++)
{
images[i] = reader.read(i);
}
reader.dispose();
int size = 1;
width = images[0].getWidth();
height = images[0].getHeight();
while((size / width) * (size / height) < frames) size *= 2;
this.size = size;
name = glGenTextures();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, name);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, (IntBuffer)null);
checkGLError("Texture creation");
for(int i = 0; i * (size / width) < frames; i++)
{
for(int j = 0; i * (size / width) + j < frames && j < size / width; j++)
{
FMLLog.info("loc: %s, i: %s, j: %s, size: %s, width: %s, height: %s", location, i, j, size, width, height);
buf.clear();
BufferedImage image = images[i * (size / width) + j];
for(int k = 0; k < height; k++)
{
for(int l = 0; l < width; l++)
{
buf.put(image.getRGB(l, k));
}
}
buf.position(0).limit(width * height);
glTexSubImage2D(GL_TEXTURE_2D, 0, j * width, i * height, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buf);
checkGLError("Texture uploading");
}
}
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
}
catch(IOException e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
finally
{
IOUtils.closeQuietly(s);
}
}
catch(IOException e)
public ResourceLocation getLocation()
{
e.printStackTrace();
throw new RuntimeException(e);
return location;
}
finally
public int getName()
{
IOUtils.closeQuietly(s);
return name;
}
public int getWidth()
{
return width;
}
public int getHeight()
{
return height;
}
public int getFrames()
{
return frames;
}
public int getSize()
{
return size;
}
public void bind()
{
glBindTexture(GL_TEXTURE_2D, name);
}
public void delete()
{
glDeleteTextures(name);
}
public float getU(int frame, float u)
{
return width * (frame % (size / width) + u) / size;
}
public float getV(int frame, float v)
{
return height * (frame / (size / width) + v) / size;
}
public void texCoord(int frame, float u, float v)
{
glTexCoord2f(getU(frame, u), getV(frame, v));
}
}
@ -466,7 +582,7 @@ public class SplashProgress
{
public SplashFontRenderer()
{
super(Minecraft.getMinecraft().gameSettings, fontLocation, null, false);
super(Minecraft.getMinecraft().gameSettings, fontTexture.getLocation(), null, false);
super.onResourceManagerReload(null);
}
@ -474,7 +590,7 @@ public class SplashProgress
protected void bindTexture(ResourceLocation location)
{
if(location != locationFontTexture) throw new IllegalArgumentException();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, fontTexture);
fontTexture.bind();
}
@Override
@ -499,4 +615,13 @@ public class SplashProgress
renderEngine.deleteTexture(mojangLogo);
}
}
public static void checkGLError(String where)
{
int err = GL11.glGetError();
if (err != 0)
{
throw new IllegalStateException(where + ": " + GLU.gluErrorString(err));
}
}
}

View file

@ -1,5 +1,8 @@
enabled = true
rotate = true
forgeTexture = fml:textures/gui/forge.png
logoOffset = 10
background = 0xFFFFFF
font = 0x000000
barBorder = 0xC0C0C0