package com.skcraft.playblock.projector;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
import com.skcraft.playblock.player.MediaManager;
import com.skcraft.playblock.player.MediaPlayerClient;
import com.skcraft.playblock.player.MediaRenderer;
import com.skcraft.playblock.player.RendererState;
import com.skcraft.playblock.util.DrawUtils;
import com.skcraft.playblock.util.MathUtils;
/**
* Renders the screen for the projector blocks.
*/
public class RenderProjector extends TileEntitySpecialRenderer {
private static final float TEXT_SCALE = 0.045f;
private static final int LINE_SPACING = 2;
private static final float LOGO_SCALE = 0.4f;
private static final float LOGO_DURATION = 3000;
private static final int LOGO_WIDTH = 512;
private static final int LOGO_HEIGHT = 128;
private static final float SPINNER_SCALE = 0.1f;
private static final float SPINNER_ANGLE = 30f;
private static final float STATUS_LOGO_SCALE = 0.5f;
private final MediaManager mediaManager;
/**
* Construct a new instance.
*
* @param mediaManager
* the media manager.
*/
public RenderProjector(MediaManager mediaManager) {
this.mediaManager = mediaManager;
}
@Override
public void renderTileEntityAt(TileEntity tileEntity, double x, double y, double z, float direction) {
TileEntityProjector projector = ((TileEntityProjector) tileEntity);
MediaPlayerClient mediaPlayer = (MediaPlayerClient) projector.getMediaPlayer();
float width = mediaPlayer.getWidth();
float height = mediaPlayer.getHeight();
int metadata = tileEntity.getBlockMetadata();
float rot;
// Calculate the rotation
switch (metadata) {
case 0:
rot = 180;
break;
case 2:
rot = 0;
break;
default:
rot = metadata * 90;
}
GL11.glPushMatrix();
{ // TODO: Consider using FBOs?
GL11.glTranslatef((float) x + 0.5f, (float) y + 0.5f, (float) z + 0.5f);
GL11.glRotatef(rot, 0, 1, 0);
GL11.glTranslatef((float) (width / 2.0), (float) (height / 2.0), -0.51f);
GL11.glScalef(-1, -1, 1);
GL11.glDisable(GL11.GL_LIGHTING);
drawScreen(projector, width, height);
GL11.glRotatef(180, 0, 1, 0);
// TODO: draw an actual texture
DrawUtils.drawRect(0, 0, -width, height, 0xff333333);
GL11.glEnable(GL11.GL_LIGHTING);
}
GL11.glPopMatrix();
}
/**
* Draw the video screen, which may include error messages.
*
* @param projector
* the projector
* @param width
* the width
* @param height
* the height
*/
private void drawScreen(TileEntityProjector projector, float width, float height) {
if (!mediaManager.isSupported()) {
if (projector.inRange()) {
drawPlayBlockStatus(width, height);
} else {
DrawUtils.drawRect(0, 0, width, height, 0xff000000);
}
} else {
MediaPlayerClient mediaPlayer = ((MediaPlayerClient) projector.getMediaPlayer());
MediaRenderer renderer = mediaPlayer.getRenderer();
if (renderer != null) {
renderer.drawMedia(0, 0, width, height);
RendererState status = renderer.getState();
if (!mediaPlayer.hasSomethingToPlay()) {
drawTextBox(0, 0, width, height, true, 0xffff0000, "No video set!");
} else if (status == RendererState.INITIALIZING) {
double t = System.currentTimeMillis() - renderer.getCreationTime();
if (drawLogo(t, width, height)) {
drawSpinner(t, width, height);
}
} else if (status == RendererState.BUFFERING) {
double t = System.currentTimeMillis() - renderer.getCreationTime();
if (drawLogo(t, width, height)) {
drawSpinner(t, width, height);
}
} else if (status == RendererState.ERROR) {
drawTextBox(0, 0, width, height, true, 0xffff0000, "Couldn't play video;", "maybe bad URL?");
} else if (status == RendererState.PAUSED) {
drawTextBox(0, 0, width, height, true, 0xffff0000, "Paused.");
} else if (status == RendererState.STOPPED) {
drawTextBox(0, 0, width, height, true, 0xffff0000, "Stopped.");
}
} else {
DrawUtils.drawRect(0, 0, width, height, 0xff000000);
}
}
}
/**
* Draw the screen indicating the status of the PlayBlock installation.
*
* @param width
* the width of the screen
* @param height
* the height of the screen
*/
private void drawPlayBlockStatus(float width, float height) {
DrawUtils.drawRect(0, 0, width, height, 0xff717171);
GL11.glPushMatrix();
{
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslatef(0, 0, -0.01f);
GL11.glColor4f(1, 1, 1, 1);
bindTexture(new ResourceLocation("playblock:textures/misc/screen_logo.png"));
float x = width * 0.04f;
float y = height * 0.04f;
float logoWidth = width * STATUS_LOGO_SCALE;
float logoHeight = width * STATUS_LOGO_SCALE * (LOGO_HEIGHT / (float) LOGO_WIDTH);
DrawUtils.drawTexture(x, y, logoWidth, logoHeight);
drawTextBox(x, logoHeight + y * 2, width - x, height - logoHeight - y * 2, false, 0xff333333, mediaManager.getUnsupportedMessage());
GL11.glDisable(GL11.GL_BLEND);
}
GL11.glPopMatrix();
}
/**
* Draw the logo animation.
*
* @param t
* the time offset
* @param width
* the width of the entire screen
* @param height
* the height of the entire screen
* @return true if the logo has finished animating
*/
private boolean drawLogo(double t, float width, float height) {
if (t > LOGO_DURATION) {
return true;
}
float alpha = (float) (MathUtils.easeInQuad(t, 0, 1, LOGO_DURATION * 0.4) - // Entrance
MathUtils.easeInOutCubic(t - LOGO_DURATION * 0.6, 0, 1, LOGO_DURATION * 0.4)); // Exit
GL11.glPushMatrix();
{
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslatef(0, 0, -0.01f);
GL11.glColor4f(1, 1, 1, alpha);
bindTexture(new ResourceLocation("playblock:textures/misc/screen_logo.png"));
float x = width / 2.0f;
float y = height / 2.0f;
if (width >= height) {
DrawUtils.drawCenteredTexture(x, y, width * LOGO_SCALE, width * LOGO_SCALE * (LOGO_HEIGHT / (float) LOGO_WIDTH));
} else {
DrawUtils.drawCenteredTexture(x, y, height * LOGO_SCALE * (LOGO_WIDTH / (float) LOGO_HEIGHT), height * LOGO_SCALE);
}
GL11.glDisable(GL11.GL_BLEND);
}
GL11.glPopMatrix();
return false;
}
/**
* Draw the spinner animation.
*
* @param t
* the time offset
* @param width
* the width of the entire screen
* @param height
* the height of the entire screen
*/
private void drawSpinner(double t, float width, float height) {
float x = width / 2.0f;
float y = height / 2.0f;
GL11.glPushMatrix();
{
// May want to convert this to OpenGL drawing calls rather than a
// texture if we stick with this spinner
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
float angle = (int) ((t / 7 / (360 / SPINNER_ANGLE)) % (360 / SPINNER_ANGLE)) * -SPINNER_ANGLE;
GL11.glTranslatef(x, y, -0.01f);
GL11.glRotatef(angle, 0, 0, -0.01f);
GL11.glColor4f(1, 1, 1, 1);
bindTexture(new ResourceLocation("playblock:textures/misc/spinner.png"));
if (width >= height) {
DrawUtils.drawCenteredTexture(0, 0, width * SPINNER_SCALE, width * SPINNER_SCALE);
} else {
DrawUtils.drawCenteredTexture(0, 0, height * SPINNER_SCALE, height * SPINNER_SCALE);
}
GL11.glDisable(GL11.GL_BLEND);
}
GL11.glPopMatrix();
}
/**
* Draws a textbox at a location.
*
* @param x0
* top left x
* @param y0
* top left y
* @param x1
* bottom right X
* @param y1
* bottom right Y
* @param centered
* true if centered
* @param bgColor
* background color
* @param lines
* text lines
*/
private void drawTextBox(float x0, float y0, float x1, float y1, boolean centered, int bgColor, String... lines) {
float width = x1 - x0;
float height = y1 - y0;
float[] textWidths = new float[lines.length];
float largestTextWidth = 0;
int textHeight = getFontRenderer().FONT_HEIGHT;
float totalHeight = lines.length * (getFontRenderer().FONT_HEIGHT + LINE_SPACING);
// Get the width of every line
for (int i = 0; i < lines.length; i++) {
textWidths[i] = getFontRenderer().getStringWidth(lines[i]);
if (textWidths[i] > largestTextWidth) {
largestTextWidth = textWidths[i];
}
}
float scale = TEXT_SCALE; // Start with the default scale
if (scale * largestTextWidth > width) {
scale = width / largestTextWidth; // Scale it down
}
// Center?
if (centered) {
x0 += (float) ((width - largestTextWidth * scale) / 2.0);
y0 += (float) ((height - totalHeight * scale) / 2.0);
}
GL11.glPushMatrix();
{
GL11.glTranslatef(x0, y0, -0.01f);
GL11.glScalef(scale, scale, 1f);
for (int i = 0; i < lines.length; i++) {
float a = i * (textHeight + LINE_SPACING);
DrawUtils.drawRect(0, a, textWidths[i], textHeight + a, bgColor);
}
}
GL11.glPopMatrix();
GL11.glPushMatrix();
{
GL11.glTranslatef(x0, y0, -0.02f);
GL11.glScalef(scale, scale, 1f);
for (int i = 0; i < lines.length; i++) {
getFontRenderer().drawString(lines[i], 0, i * (textHeight + LINE_SPACING), 0xffffffff, false);
}
}
GL11.glPopMatrix();
}
private FontRenderer getFontRenderer() {
return Minecraft.getMinecraft().fontRenderer;
}
}