the whole game

This commit is contained in:
Kolyah35
2026-03-02 22:04:18 +03:00
parent 816e9060b4
commit f0617a5d22
2069 changed files with 581500 additions and 0 deletions

372
src/client/gui/Font.cpp Executable file
View File

@@ -0,0 +1,372 @@
#include "Font.h"
//#include "SharedConstants.h"
#include "../Options.h"
#include "../renderer/Textures.h"
#include "../renderer/Tesselator.h"
#include "../../util/Mth.h"
#include <cstring>
Font::Font( Options* options, const std::string& name, Textures* textures )
: options(options),
fontTexture(0),
fontName(name),
index(0),
count(0),
_textures(textures),
_x(0), _y(0),
_cols(16), _rows(16),
_charOffset(0),
lineHeight(DefaultLineHeight)
{
init(options);
}
//Font::Font( Options* options, const std::string& name, Textures* textures, int imgW, int imgH, int x, int y, int cols, int rows, unsigned char charOffset )
//: options(options),
// fontTexture(0),
// fontName(name),
// index(0),
// count(0),
// _textures(textures),
// _x(x), _y(y),
// _cols(cols), _rows(rows),
// _charOffset(charOffset)
//{
// init(options);
//}
void Font::onGraphicsReset()
{
init(options);
}
void Font::init( Options* options )
{
TextureId fontTexture = _textures->loadTexture(fontName);
const TextureData* tex = _textures->getTemporaryTextureData(fontTexture);
if (!tex)
return;
unsigned char* rawPixels = tex->data;
const int numChars = _rows * _cols;
for (int i = 0; i < numChars; i++) {
int xt = i % _cols;
int yt = i / _cols;
int x = 7;
for (; x >= 0; x--) {
int xPixel = _x + xt * 8 + x;
bool emptyColumn = true;
for (int y = 0; y < 8 && emptyColumn; y++) {
int yPixel = _y + (yt * 8 + y) * tex->w;
unsigned char pixelalpha = rawPixels[(xPixel + yPixel) << 2];
if (pixelalpha > 0) emptyColumn = false;
}
if (!emptyColumn) {
break;
}
}
if (i == ' ') x = 4 - 2;
charWidths[i] = x + 2;
fcharWidths[i] = (float) charWidths[i];
}
#ifdef USE_VBO
return; // this <1
#endif
#ifndef USE_VBO
listPos = glGenLists(256 + 32);
Tesselator& t = Tesselator::instance;
for (int i = 0; i < 256; i++) {
glNewList(listPos + i, GL_COMPILE);
// @attn @huge @note: This is some dangerous code right here / Aron, added ^1
t.begin();
buildChar(i);
t.end(false, -1);
glTranslatef2((GLfloat)charWidths[i], 0.0f, 0.0f);
glEndList();
}
for (int i = 0; i < 32; i++) {
int br = ((i >> 3) & 1) * 0x55;
int r = ((i >> 2) & 1) * 0xaa + br;
int g = ((i >> 1) & 1) * 0xaa + br;
int b = ((i >> 0) & 1) * 0xaa + br;
if (i == 6) {
r += 0x55;
}
bool darken = i >= 16;
if (options->anaglyph3d) {
int cr = (r * 30 + g * 59 + b * 11) / 100;
int cg = (r * 30 + g * 70) / (100);
int cb = (r * 30 + b * 70) / (100);
r = cr;
g = cg;
b = cb;
}
// color = r << 16 | g << 8 | b;
if (darken) {
r /= 4;
g /= 4;
b /= 4;
}
glNewList(listPos + 256 + i, GL_COMPILE);
glColor3f(r / 255.0f, g / 255.0f, b / 255.0f);
glEndList();
}
#endif
}
void Font::drawShadow( const std::string& str, float x, float y, int color )
{
draw(str, x + 1, y + 1, color, true);
draw(str, x, y, color);
}
void Font::drawShadow( const char* str, float x, float y, int color )
{
draw(str, x + 1, y + 1, color, true);
draw(str, x, y, color);
}
void Font::draw( const std::string& str, float x, float y, int color )
{
draw(str, x, y, color, false);
}
void Font::draw( const char* str, float x, float y, int color )
{
draw(str, x, y, color, false);
}
void Font::draw( const char* str, float x, float y, int color, bool darken )
{
#ifdef USE_VBO
drawSlow(str, x, y, color, darken);
#endif
}
void Font::draw( const std::string& str, float x, float y, int color, bool darken )
{
#ifdef USE_VBO
drawSlow(str, x, y, color, darken);
return;
#endif
if (str.empty()) return;
if (darken) {
int oldAlpha = color & 0xff000000;
color = (color & 0xfcfcfc) >> 2;
color += oldAlpha;
}
_textures->loadAndBindTexture(fontName);
float r = ((color >> 16) & 0xff) / 255.0f;
float g = ((color >> 8) & 0xff) / 255.0f;
float b = ((color) & 0xff) / 255.0f;
float a = ((color >> 24) & 0xff) / 255.0f;
if (a == 0) a = 1;
glColor4f2(r, g, b, a);
static const std::string hex("0123456789abcdef");
index = 0;
glPushMatrix2();
glTranslatef2((GLfloat)x, (GLfloat)y, 0.0f);
for (unsigned int i = 0; i < str.length(); i++) {
while (str.length() > i + 1 && str[i] == '<EFBFBD>') {
int cc = hex.find((char)tolower(str[i + 1]));
if (cc < 0 || cc > 15) cc = 15;
lists[index++] = listPos + 256 + cc + (darken ? 16 : 0);
if (index == 1024) {
count = index;
index = 0;
#ifndef USE_VBO
glCallLists(count, GL_UNSIGNED_INT, lists);
#endif
count = 1024;
}
i += 2;
}
if (i < str.length()) {
//int ch = SharedConstants.acceptableLetters.indexOf(str.charAt(i));
char ch = str[i];
if (ch >= 0) {
//ib.put(listPos + ch + 32);
lists[index++] = listPos + ch;
}
}
if (index == 1024) {
count = index;
index = 0;
#ifndef USE_VBO
glCallLists(count, GL_UNSIGNED_INT, lists);
#endif
count = 1024;
}
}
count = index;
index = 0;
#ifndef USE_VBO
glCallLists(count, GL_UNSIGNED_INT, lists);
#endif
glPopMatrix2();
}
int Font::width( const std::string& str )
{
int maxLen = 0;
int len = 0;
for (unsigned int i = 0; i < str.length(); i++) {
if (str[i] == '<EFBFBD>') {
i++;
} else {
//int ch = SharedConstants.acceptableLetters.indexOf(str.charAt(i));
//if (ch >= 0) {
// len += charWidths[ch + 32];
//}
if (str[i] == '\n') {
if (len > maxLen) maxLen = len;
len = 0;
}
else {
int charWidth = charWidths[ (unsigned char) str[i] ];
len += charWidth;
}
}
}
return maxLen>len? maxLen : len;
}
int Font::height( const std::string& str ) {
int h = 0;
bool hasLine = false;
for (unsigned int i = 0; i < str.length(); ++i) {
if (str[i] == '\n') hasLine = true;
else {
if (hasLine) h += lineHeight;
hasLine = false;
}
}
return h;
}
std::string Font::sanitize( const std::string& str )
{
std::string sanitized(str.length() + 1, 0);
int j = 0;
for (unsigned int i = 0; i < str.length(); i++) {
if (str[i] == '<EFBFBD>') {
i++;
//} else if (SharedConstants.acceptableLetters.indexOf(str.charAt(i)) >= 0) {
} else {
sanitized[j++] = str[i];
}
}
return sanitized.erase(j);
}
void Font::drawWordWrap( const std::string& str, float x, float y, float w, int col )
{
char* cstr = new char[str.length() + 1];
strncpy(cstr, str.c_str(), str.length());
cstr[str.length()] = 0;
const char* lims = " \n\t\r";
char* ptok = strtok(cstr, lims);
std::vector<std::string> words;
while (ptok != NULL) {
words.push_back( ptok );
ptok = strtok(NULL, lims);
}
delete[] cstr;
int pos = 0;
while (pos < (int)words.size()) {
std::string line = words[pos++] + " ";
while (pos < (int)words.size() && width(line + words[pos]) < w) {
line += words[pos++] + " ";
}
drawShadow(line, x, y, col);
y += lineHeight;
}
}
void Font::drawSlow( const std::string& str, float x, float y, int color, bool darken /*= false*/ ) {
drawSlow(str.c_str(), x, y, color, darken);
}
void Font::drawSlow( const char* str, float x, float y, int color, bool darken /*= false*/ )
{
if (!str) return;
if (darken) {
int oldAlpha = color & 0xff000000;
color = (color & 0xfcfcfc) >> 2;
color += oldAlpha;
}
_textures->loadAndBindTexture(fontName);
Tesselator& t = Tesselator::instance;
t.begin();
int alpha = (0xff000000 & color) >> 24;
if (!alpha) alpha = 0xff;
t.color((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, alpha);
t.addOffset((float)x, (float)y, 0);
float xOffset = 0;
float yOffset = 0;
while (unsigned char ch = *(str++)) {
if (ch == '\n') {
xOffset = 0;
yOffset += lineHeight;
} else {
buildChar(ch, xOffset, yOffset);
xOffset += fcharWidths[ch];
}
}
t.draw();
t.addOffset(-(float)x, -(float)y, 0);
}
void Font::buildChar( unsigned char i, float x /*= 0*/, float y /*=0*/ )
{
Tesselator& t = Tesselator::instance;
//i -= _charOffset;
//int ix = (i % _cols) * 8 + _x;
//int iy = (i / _cols) * 8 + _y;
float ix = (float)((i & 15) * 8);
float iy = (float)((i >> 4) * 8);
float s = 7.99f;
float uo = (0.0f) / 128.0f;
float vo = (0.0f) / 128.0f;
t.vertexUV(x, y + s, 0, ix / 128.0f + uo, (iy + s) / 128.0f + vo);
t.vertexUV(x + s, y + s, 0, (ix + s) / 128.0f + uo, (iy + s) / 128.0f + vo);
t.vertexUV(x + s, y, 0, (ix + s) / 128.0f + uo, iy / 128.0f + vo);
t.vertexUV(x, y, 0, ix / 128.0f + uo, iy / 128.0f + vo);
}

63
src/client/gui/Font.h Executable file
View File

@@ -0,0 +1,63 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__Font_H__
#define NET_MINECRAFT_CLIENT_GUI__Font_H__
//package net.minecraft.client.gui;
#include <string>
#include <cctype>
#include "../renderer/gles.h"
class Textures;
class Options;
class Font
{
public:
Font(Options* options, const std::string& name, Textures* textures);
//Font(Options* options, const std::string& name, Textures* textures, int imgW, int imgH, int x, int y, int cols, int rows, unsigned char charOffset);
void init(Options* options);
void onGraphicsReset();
void draw(const char* str, float x, float y, int color);
void draw(const std::string& str, float x, float y, int color);
void draw(const char* str, float x, float y, int color, bool darken);
void draw(const std::string& str, float x, float y, int color, bool darken);
void drawShadow(const std::string& str, float x, float y, int color);
void drawShadow(const char* str, float x, float y, int color);
void drawWordWrap(const std::string& str, float x, float y, float w, int col);
int width(const std::string& str);
int height(const std::string& str);
static std::string sanitize(const std::string& str);
private:
void buildChar(unsigned char i, float x = 0, float y = 0);
void drawSlow(const std::string& str, float x, float y, int color, bool darken = false);
void drawSlow(const char* str, float x, float y, int color, bool darken = false);
public:
int fontTexture;
int lineHeight;
static const int DefaultLineHeight = 10;
private:
int charWidths[256];
float fcharWidths[256];
int listPos;
int index;
int count;
GLuint lists[1024];
std::string fontName;
Textures* _textures;
Options* options;
int _x, _y;
int _cols;
int _rows;
unsigned char _charOffset;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__Font_H__*/

810
src/client/gui/Gui.cpp Executable file
View File

@@ -0,0 +1,810 @@
#include "Gui.h"
#include "Font.h"
#include "screens/IngameBlockSelectionScreen.h"
#include "../Minecraft.h"
#include "../player/LocalPlayer.h"
#include "../renderer/Tesselator.h"
#include "../renderer/TileRenderer.h"
#include "../renderer/LevelRenderer.h"
#include "../renderer/GameRenderer.h"
#include "../renderer/entity/ItemRenderer.h"
#include "../player/input/IInputHolder.h"
#include "../gamemode/GameMode.h"
#include "../gamemode/CreativeMode.h"
#include "../renderer/Textures.h"
#include "../../AppConstants.h"
#include "../../world/entity/player/Inventory.h"
#include "../../world/level/material/Material.h"
#include "../../world/item/Item.h"
#include "../../world/item/ItemInstance.h"
#include "../../platform/input/Mouse.h"
#include "../../world/level/Level.h"
#include "../../world/PosTranslator.h"
float Gui::InvGuiScale = 1.0f / 3.0f;
float Gui::GuiScale = 1.0f / Gui::InvGuiScale;
const float Gui::DropTicks = 40.0f;
//#include <android/log.h>
Gui::Gui(Minecraft* minecraft)
: minecraft(minecraft),
tickCount(0),
progress(0),
overlayMessageTime(0),
animateOverlayMessageColor(false),
tbr(1),
_inventoryNeedsUpdate(true),
_flashSlotId(-1),
_flashSlotStartTime(-1),
_slotFont(NULL),
_numSlots(4),
_currentDropTicks(-1),
_currentDropSlot(-1),
MAX_MESSAGE_WIDTH(240),
itemNameOverlayTime(2)
{
glGenBuffers2(1, &_inventoryRc.vboId);
glGenBuffers2(1, &rcFeedbackInner.vboId);
glGenBuffers2(1, &rcFeedbackOuter.vboId);
//Gui::InvGuiScale = 1.0f / (int) (3 * Minecraft::width / 854);
}
Gui::~Gui()
{
if (_slotFont)
delete _slotFont;
glDeleteBuffers(1, &_inventoryRc.vboId);
}
void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
if (!minecraft->level || !minecraft->player)
return;
//minecraft->gameRenderer->setupGuiScreen();
Font* font = minecraft->font;
const bool isTouchInterface = minecraft->useTouchscreen();
const int screenWidth = (int)(minecraft->width * InvGuiScale);
const int screenHeight = (int)(minecraft->height * InvGuiScale);
blitOffset = -90;
renderProgressIndicator(isTouchInterface, screenWidth, screenHeight, a);
glColor4f2(1, 1, 1, 1);
// H: 4
// T: 7
// L: 6
// F: 3
int ySlot = screenHeight - 16 - 3;
if (minecraft->gameMode->canHurtPlayer()) {
minecraft->textures->loadAndBindTexture("gui/icons.png");
Tesselator& t = Tesselator::instance;
t.beginOverride();
t.colorABGR(0xffffffff);
renderHearts();
renderBubbles();
t.endOverrideAndDraw();
}
if(minecraft->player->getSleepTimer() > 0) {
glDisable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
renderSleepAnimation(screenWidth, screenHeight);
glEnable(GL_ALPHA_TEST);
glEnable(GL_DEPTH_TEST);
}
renderToolBar(a, ySlot, screenWidth);
//font->drawShadow(APP_NAME, 2, 2, 0xffffffff);
//font->drawShadow("This is a demo, not the finished product", 2, 10 + 2, 0xffffffff);
#ifdef APPLE_DEMO_PROMOTION
font->drawShadow("Demo version", 2, 0 + 2, 0xffffffff);
#endif /*APPLE_DEMO_PROMOTION*/
glEnable(GL_BLEND);
unsigned int max = 10;
bool isChatting = false;
renderChatMessages(screenHeight, max, isChatting, font);
#if !defined(RPI)
renderOnSelectItemNameText(screenWidth, font, ySlot);
#endif
#if defined(RPI)
renderDebugInfo();
#endif
// glPopMatrix2();
//
// glEnable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glEnable2(GL_ALPHA_TEST);
}
int Gui::getSlotIdAt(int x, int y) {
int screenWidth = (int)(minecraft->width * InvGuiScale);
int screenHeight = (int)(minecraft->height * InvGuiScale);
x = (int)(x * InvGuiScale);
y = (int)(y * InvGuiScale);
if (y < (screenHeight - 16 - 3) || y > screenHeight)
return -1;
int xBase = 2 + screenWidth / 2 - getNumSlots() * 10;
int xRel = (x - xBase);
if (xRel < 0)
return -1;
int slot = xRel / 20;
return (slot >= 0 && slot < getNumSlots())? slot : -1;
}
bool Gui::isInside(int x, int y) {
return getSlotIdAt(x, y) != -1;
}
int Gui::getNumSlots() {
return _numSlots;
}
void Gui::flashSlot(int slotId) {
_flashSlotId = slotId;
_flashSlotStartTime = getTimeS();
}
void Gui::getSlotPos(int slot, int& posX, int& posY) {
int screenWidth = (int)(minecraft->width * InvGuiScale);
int screenHeight = (int)(minecraft->height * InvGuiScale);
posX = screenWidth / 2 - getNumSlots() * 10 + slot * 20,
posY = screenHeight - 22;
}
RectangleArea Gui::getRectangleArea(int extendSide) {
const int Spacing = 3;
const float pCenterX = 2.0f + (float)(minecraft->width / 2);
const float pHalfWidth = (1.0f + (getNumSlots() * 10 + Spacing)) * Gui::GuiScale;
const float pHeight = (22 + Spacing) * Gui::GuiScale;
if (extendSide < 0)
return RectangleArea(0, (float)minecraft->height-pHeight, pCenterX+pHalfWidth+2, (float)minecraft->height);
if (extendSide > 0)
return RectangleArea(pCenterX-pHalfWidth, (float)minecraft->height-pHeight, (float)minecraft->width, (float)minecraft->height);
return RectangleArea(pCenterX-pHalfWidth, (float)minecraft->height-pHeight, pCenterX+pHalfWidth+2, (float)minecraft->height);
}
void Gui::handleClick(int button, int x, int y) {
if (button != MouseAction::ACTION_LEFT) return;
int slot = getSlotIdAt(x, y);
if (slot != -1)
{
if (slot == (getNumSlots()-1))
{
minecraft->screenChooser.setScreen(SCREEN_BLOCKSELECTION);
}
else
{
minecraft->player->inventory->selectSlot(slot);
itemNameOverlayTime = 0;
}
}
}
void Gui::handleKeyPressed(int key)
{
if (key == 99)
{
if (minecraft->player->inventory->selected > 0)
{
minecraft->player->inventory->selected--;
}
}
else if (key == 4)
{
if (minecraft->player->inventory->selected < (getNumSlots() - 2))
{
minecraft->player->inventory->selected++;
}
}
else if (key == 100)
{
minecraft->screenChooser.setScreen(SCREEN_BLOCKSELECTION);
}
}
void Gui::tick() {
if (overlayMessageTime > 0) overlayMessageTime--;
tickCount++;
if(itemNameOverlayTime < 2)
itemNameOverlayTime += 1.0f / SharedConstants::TicksPerSecond;
for (unsigned int i = 0; i < guiMessages.size(); i++) {
guiMessages.at(i).ticks++;
}
if (!minecraft->isCreativeMode())
tickItemDrop();
}
void Gui::addMessage(const std::string& _string) {
if (!minecraft->font)
return;
std::string string = _string;
while (minecraft->font->width(string) > MAX_MESSAGE_WIDTH) {
unsigned int i = 1;
while (i < string.length() && minecraft->font->width(string.substr(0, i + 1)) <= MAX_MESSAGE_WIDTH) {
i++;
}
addMessage(string.substr(0, i));
string = string.substr(i);
}
GuiMessage message;
message.message = string;
message.ticks = 0;
guiMessages.insert(guiMessages.begin(), message);
while (guiMessages.size() > 30) {
guiMessages.pop_back();
}
}
void Gui::setNowPlaying(const std::string& string) {
overlayMessageString = "Now playing: " + string;
overlayMessageTime = 20 * 3;
animateOverlayMessageColor = true;
}
void Gui::displayClientMessage(const std::string& messageId) {
//Language language = Language.getInstance();
//std::string languageString = language.getElement(messageId);
addMessage(std::string("Client message: ") + messageId);
}
void Gui::renderVignette(float br, int w, int h) {
br = 1 - br;
if (br < 0) br = 0;
if (br > 1) br = 1;
tbr += (br - tbr) * 0.01f;
glDisable(GL_DEPTH_TEST);
glDepthMask(false);
glBlendFunc2(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
glColor4f2(tbr, tbr, tbr, 1);
minecraft->textures->loadAndBindTexture("misc/vignette.png");
Tesselator& t = Tesselator::instance;
t.begin();
t.vertexUV(0, (float)h, -90, 0, 1);
t.vertexUV((float)w, (float)h, -90, 1, 1);
t.vertexUV((float)w, 0, -90, 1, 0);
t.vertexUV(0, 0, -90, 0, 0);
t.draw();
glDepthMask(true);
glEnable(GL_DEPTH_TEST);
glColor4f2(1, 1, 1, 1);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void Gui::renderSlot(int slot, int x, int y, float a) {
ItemInstance* item = minecraft->player->inventory->getItem(slot);
if (!item) {
//LOGW("Warning: item @ Gui::renderSlot is NULL\n");
return;
}
const bool fancy = true;
ItemRenderer::renderGuiItem(minecraft->font, minecraft->textures, item, (float)x, (float)y, fancy);
}
void Gui::renderSlotText( const ItemInstance* item, float x, float y, bool hasFinite, bool shadow )
{
//if (!item || item->getItem()->getMaxStackSize() <= 1) {
if (item->count <= 1) {
return;
}
int c = item->count;
char buffer[4] = {0,0,0,0};
if (hasFinite)
itemCountItoa(buffer, c);
else
buffer[0] = (char)157;
//LOGI("slot: %d - %s\n", slot, buffer);
if (shadow)
minecraft->font->drawShadow(buffer, x, y, item->count>0?0xffcccccc:0x60cccccc);
else
minecraft->font->draw(buffer, x, y, item->count>0?0xffcccccc:0x60cccccc);
}
void Gui::inventoryUpdated() {
_inventoryNeedsUpdate = true;
}
void Gui::onGraphicsReset() {
inventoryUpdated();
}
void Gui::texturesLoaded( Textures* textures ) {
//_slotFont = new Font(&minecraft->options, "gui/gui_blocks.png", textures, 0, 504, 10, 1, '0');
}
void Gui::onConfigChanged( const Config& c ) {
Tesselator& t = Tesselator::instance;
t.begin();
//
// Create outer feedback circle
//
#ifdef ANDROID
const float mm = 12;
#else
const float mm = 12;
#endif
const float maxRadius = minecraft->pixelCalcUi.millimetersToPixels(mm);
const float radius = Mth::Min(80.0f/2, maxRadius);
//LOGI("radius, maxradius: %f, %f\n", radius, maxRadius);
const float radiusInner = radius * 0.95f;
const int steps = 24;
const float fstep = Mth::TWO_PI / steps;
for (int i = 0; i < steps; ++i) {
float a = i * fstep;;
float b = a + fstep;
float aCos = Mth::cos(a);
float bCos = Mth::cos(b);
float aSin = Mth::sin(a);
float bSin = Mth::sin(b);
float x00 = radius * aCos;
float x01 = radiusInner * aCos;
float x10 = radius * bCos;
float x11 = radiusInner * bCos;
float y00 = radius * aSin;
float y01 = radiusInner * aSin;
float y10 = radius * bSin;
float y11 = radiusInner * bSin;
t.vertexUV(x01, y01, 0, 0, 1);
t.vertexUV(x11, y11, 0, 1, 1);
t.vertexUV(x10, y10, 0, 1, 0);
t.vertexUV(x00, y00, 0, 0, 0);
}
rcFeedbackOuter = t.end(true, rcFeedbackOuter.vboId);
//
// Create the inner feedback ring
//
t.begin(GL_TRIANGLE_FAN);
t.vertex(0, 0, 0);
for (int i = 0; i < steps + 1; ++i) {
float a = -i * fstep;
float xx = radiusInner * Mth::cos(a);
float yy = radiusInner * Mth::sin(a);
t.vertex(xx, yy, 0);
//LOGI("x,y: %f, %f\n", xx, yy);
}
rcFeedbackInner = t.end(true, rcFeedbackInner.vboId);
if (c.minecraft->useTouchscreen()) {
// I'll bump this up to 6.
int num = 6; // without "..." dots
if (!c.minecraft->options.isJoyTouchArea && c.width > 480) {
while (num < Inventory::MAX_SELECTION_SIZE - 1) {
int x0, x1, y;
getSlotPos(0, x0, y);
getSlotPos(num, x1, y);
int width = x1 - x0;
float leftoverPixels = c.width - c.guiScale*width;
if (c.pixelCalc.pixelsToMillimeters(leftoverPixels) < 80)
break;
num++;
}
}
_numSlots = num;
#if defined(__APPLE__)
_numSlots = Mth::Min(7, _numSlots);
#endif
} else {
_numSlots = Inventory::MAX_SELECTION_SIZE; // Xperia Play
}
MAX_MESSAGE_WIDTH = c.guiWidth;
}
float Gui::floorAlignToScreenPixel(float v) {
return (int)(v * Gui::GuiScale) * Gui::InvGuiScale;
}
int Gui::itemCountItoa( char* buffer, int count )
{
if (count < 0)
return 0;
if (count < 10) { // 1 digit
buffer[0] = '0' + count;
buffer[1] = 0;
return 1;
} else if (count < 100) { // 2 digits
int digit = count/10;
buffer[0] = '0' + digit;
buffer[1] = '0' + count - digit*10;
buffer[2] = 0;
} else { // 3 digits -> "99+"
buffer[0] = buffer[1] = '9';
buffer[2] = '+';
buffer[3] = 0;
return 3;
}
return 2;
}
void Gui::tickItemDrop()
{
// Handle item drop
static bool isCurrentlyActive = false;
isCurrentlyActive = false;
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) {
int slot = getSlotIdAt(Mouse::getX(), Mouse::getY());
if (slot >= 0 && slot < getNumSlots()-1) {
if (slot != _currentDropSlot) {
_currentDropTicks = 0;
_currentDropSlot = slot;
}
isCurrentlyActive = true;
if ((_currentDropTicks += 1.0f) >= DropTicks) {
minecraft->player->inventory->dropSlot(slot, false);
minecraft->level->playSound(minecraft->player, "random.pop", 0.3f, 1);
isCurrentlyActive = false;
}
}
}
if (!isCurrentlyActive) {
_currentDropSlot = -1;
_currentDropTicks = -1;
}
}
void Gui::postError( int errCode )
{
static std::set<int> posted;
if (posted.find(errCode) != posted.end())
return;
posted.insert(errCode);
std::stringstream s;
s << "Something went wrong! (errcode " << errCode << ")\n";
addMessage(s.str());
}
void Gui::setScissorRect( const IntRectangle& bbox )
{
GLuint x = (GLuint)(GuiScale * bbox.x);
GLuint y = minecraft->height - (GLuint)(GuiScale * (bbox.y + bbox.h));
GLuint w = (GLuint)(GuiScale * bbox.w);
GLuint h = (GLuint)(GuiScale * bbox.h);
glScissor(x, y, w, h);
}
float Gui::cubeSmoothStep(float percentage, float min, float max) {
//percentage = percentage * percentage;
//return (min * percentage) + (max * (1 - percentage));
return (percentage) * (percentage) * (3 - 2 * (percentage));
}
void Gui::renderProgressIndicator( const bool isTouchInterface, const int screenWidth, const int screenHeight, float a ) {
ItemInstance* currentItem = minecraft->player->inventory->getSelected();
bool bowEquipped = currentItem != NULL ? currentItem->getItem() == Item::bow : false;
bool itemInUse = currentItem != NULL ? currentItem->getItem() == minecraft->player->getUseItem()->getItem() : false;
if (!isTouchInterface || minecraft->options.isJoyTouchArea || (bowEquipped && itemInUse)) {
minecraft->textures->loadAndBindTexture("gui/icons.png");
glEnable(GL_BLEND);
glBlendFunc2(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
blit(screenWidth/2 - 8, screenHeight/2 - 8, 0, 0, 16, 16);
glDisable(GL_BLEND);
} else if(!bowEquipped) {
const float tprogress = minecraft->gameMode->destroyProgress;
const float alpha = Mth::clamp(minecraft->inputHolder->alpha, 0.0f, 1.0f);
//LOGI("alpha: %f\n", alpha);
if (tprogress <= 0 && minecraft->inputHolder->alpha >= 0) {
glDisable2(GL_TEXTURE_2D);
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (minecraft->hitResult.isHit())
glColor4f2(1, 1, 1, 0.8f * alpha);
else
glColor4f2(1, 1, 1, Mth::Min(0.4f, alpha*0.4f));
//LOGI("alpha2: %f\n", alpha);
const float x = InvGuiScale * minecraft->inputHolder->mousex;
const float y = InvGuiScale * minecraft->inputHolder->mousey;
glTranslatef2(x, y, 0);
drawArrayVT(rcFeedbackOuter.vboId, rcFeedbackOuter.vertexCount, 24);
glTranslatef2(-x, -y, 0);
glEnable2(GL_TEXTURE_2D);
glDisable(GL_BLEND);
} else if (tprogress > 0) {
const float oProgress = minecraft->gameMode->oDestroyProgress;
const float progress = 0.5f * (oProgress + (tprogress - oProgress) * a);
//static Stopwatch w;
//w.start();
glDisable2(GL_TEXTURE_2D);
glColor4f2(1, 1, 1, 0.8f * alpha);
glEnable(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
const float x = InvGuiScale * minecraft->inputHolder->mousex;
const float y = InvGuiScale * minecraft->inputHolder->mousey;
glPushMatrix2();
glTranslatef2(x, y, 0);
drawArrayVT(rcFeedbackOuter.vboId, rcFeedbackOuter.vertexCount, 24);
glScalef2(0.5f + progress, 0.5f + progress, 1);
//glDisable2(GL_CULL_FACE);
glColor4f2(1, 1, 1, 1);
glBlendFunc2(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
drawArrayVT(rcFeedbackInner.vboId, rcFeedbackInner.vertexCount, 24, GL_TRIANGLE_FAN);
glPopMatrix2();
glDisable(GL_BLEND);
glEnable2(GL_TEXTURE_2D);
//w.stop();
//w.printEvery(100, "feedback-r ");
}
}
}
void Gui::renderHearts() {
bool blink = (minecraft->player->invulnerableTime / 3) % 2 == 1;
if (minecraft->player->invulnerableTime < 10) blink = false;
int h = minecraft->player->health;
int oh = minecraft->player->lastHealth;
random.setSeed(tickCount * 312871);
int xx = 2;//screenWidth / 2 - getNumSlots() * 10;
int armor = minecraft->player->getArmorValue();
for (int i = 0; i < Player::MAX_HEALTH / 2; i++) {
int yo = 2;
int ip2 = i + i + 1;
if (armor > 0) {
int xo = xx + 80 + i * 8 + 4;
if (ip2 < armor) blit(xo, yo, 16 + 2 * 9, 9 * 1, 9, 9);
else if (ip2 == armor) blit(xo, yo, 16 + 4 * 9, 9 * 1, 9, 9);
else if (ip2 > armor) blit(xo, yo, 16 + 0 * 9, 9 * 1, 9, 9);
}
int bg = 0;
if (blink) bg = 1;
int xo = xx + i * 8;
if (h <= 4) {
yo = yo + random.nextInt(2) - 1;
}
blit(xo, yo, 16 + bg * 9, 9 * 0, 9, 9);
if (blink) {
if (ip2 < oh) blit(xo, yo, 16 + 6 * 9, 9 * 0, 9, 9);
else if (ip2 == oh) blit(xo, yo, 16 + 7 * 9, 9 * 0, 9, 9);
}
if (ip2 < h) blit(xo, yo, 16 + 4 * 9, 9 * 0, 9, 9);
else if (ip2 == h) blit(xo, yo, 16 + 5 * 9, 9 * 0, 9, 9);
}
}
void Gui::renderBubbles() {
if (minecraft->player->isUnderLiquid(Material::water)) {
int yo = 12;
int count = (int) std::ceil((minecraft->player->airSupply - 2) * 10.0f / Player::TOTAL_AIR_SUPPLY);
int extra = (int) std::ceil((minecraft->player->airSupply) * 10.0f / Player::TOTAL_AIR_SUPPLY) - count;
for (int i = 0; i < count + extra; i++) {
int xo = i * 8 + 2;
if (i < count) blit(xo, yo, 16, 9 * 2, 9, 9);
else blit(xo, yo, 16 + 9, 9 * 2, 9, 9);
}
}
}
static OffsetPosTranslator posTranslator;
void Gui::onLevelGenerated() {
if (Level* level = minecraft->level) {
Pos p = level->getSharedSpawnPos();
posTranslator = OffsetPosTranslator((float)-p.x, (float)-p.y, (float)-p.z);
}
}
void Gui::renderDebugInfo() {
static char buf[256];
float xx = minecraft->player->x;
float yy = minecraft->player->y - minecraft->player->heightOffset;
float zz = minecraft->player->z;
posTranslator.to(xx, yy, zz);
sprintf(buf, "pos: %3.1f, %3.1f, %3.1f\n", xx, yy, zz);
Tesselator& t = Tesselator::instance;
t.beginOverride();
t.scale2d(InvGuiScale, InvGuiScale);
minecraft->font->draw(buf, 2, 2, 0xffffff);
t.resetScale();
t.endOverrideAndDraw();
}
void Gui::renderSleepAnimation( const int screenWidth, const int screenHeight ) {
int timer = minecraft->player->getSleepTimer();
float amount = (float) timer / (float) Player::SLEEP_DURATION;
if (amount > 1) {
// waking up
amount = 1.0f - ((float) (timer - Player::SLEEP_DURATION) / (float) Player::WAKE_UP_DURATION);
}
int color = (int) (220.0f * amount) << 24 | (0x101020);
fill(0, 0, screenWidth, screenHeight, color);
}
void Gui::renderOnSelectItemNameText( const int screenWidth, Font* font, int ySlot ) {
if(itemNameOverlayTime < 1.0f) {
ItemInstance* item = minecraft->player->inventory->getSelected();
if(item != NULL) {
float x = float(screenWidth / 2 - font->width(item->getName()) / 2);
float y = float(ySlot - 22);
int alpha = 255;
if(itemNameOverlayTime > 0.75) {
float time = 0.25f - (itemNameOverlayTime - 0.75f);
float percentage = cubeSmoothStep(time * 4, 0.0f, 1.0f);
alpha = int(percentage * 255);
}
if(alpha != 0)
font->drawShadow(item->getName(), x, y, 0x00ffffff + (alpha << 24));
}
}
}
void Gui::renderChatMessages( const int screenHeight, unsigned int max, bool isChatting, Font* font ) {
// if (minecraft.screen instanceof ChatScreen) {
// max = 20;
// isChatting = true;
// }
//
// glEnable(GL_BLEND);
// glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// glDisable(GL_ALPHA_TEST);
//
// glPushMatrix2();
// glTranslatef2(0, screenHeight - 48, 0);
// // glScalef2(1.0f / ssc.scale, 1.0f / ssc.scale, 1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
int baseY = screenHeight - 48;
for (unsigned int i = 0; i < guiMessages.size() && i < max; i++) {
if (guiMessages.at(i).ticks < 20 * 10 || isChatting) {
float t = guiMessages.at(i).ticks / (20 * 10.0f);
t = 1 - t;
t = t * 10;
if (t < 0) t = 0;
if (t > 1) t = 1;
t = t * t;
int alpha = (int) (255 * t);
if (isChatting) alpha = 255;
if (alpha > 0) {
const float x = 2;
const float y = (float)(baseY - i * 9);
std::string msg = guiMessages.at(i).message;
this->fill(x, y - 1, x + MAX_MESSAGE_WIDTH, y + 8, (alpha / 2) << 24);
glEnable(GL_BLEND);
font->drawShadow(msg, x, y, 0xffffff + (alpha << 24));
}
}
}
}
void Gui::renderToolBar( float a, int ySlot, const int screenWidth ) {
glColor4f2(1, 1, 1, .5);
minecraft->textures->loadAndBindTexture("gui/gui.png");
Inventory* inventory = minecraft->player->inventory;
int xBase, yBase;
getSlotPos(0, xBase, yBase);
const float baseItemX = (float)xBase + 3;
const int slotsWidth = 20 * getNumSlots();
// Left + right side of the selection bar
blit(xBase, yBase, 0, 0, slotsWidth, 22);
blit(xBase + slotsWidth, yBase, 180, 0, 2, 22);
if (_currentDropSlot >= 0 && inventory->getItem(_currentDropSlot)) {
int x = xBase + 3 + _currentDropSlot * 20;
int color = 0x8000ff00;
int yy = (int)(17.0f * (_currentDropTicks + a) / DropTicks);
if (_currentDropTicks >= 3) {
glColor4f2(0, 1, 0, 0.5f);
}
fill(x, ySlot+16-yy, x+16, ySlot+16, color);
}
blit(xBase-1 + 20*inventory->selected, yBase - 1, 0, 22, 24, 22);
glColor4f2(1, 1, 1, 1);
// Flash a slot background
if (_flashSlotId >= 0) {
const float since = getTimeS() - _flashSlotStartTime;
if (since > 0.2f) _flashSlotId = -1;
else {
int x = screenWidth / 2 - getNumSlots() * 10 + _flashSlotId * 20 + 2;
int color = 0xffffff + (((int)(/*0x80 * since +*/ 0x51 - 0x50 * Mth::cos(10 * 6.28f * since))) << 24);
//LOGI("Color: %.8x\n", color);
fill(x, ySlot, x+16, ySlot+16, color);
}
}
glColor4f2(1, 1, 1, 1);
//static Stopwatch w;
//w.start();
Tesselator& t = Tesselator::instance;
t.beginOverride();
float x = baseItemX;
for (int i = 0; i < getNumSlots()-1; i++) {
renderSlot(i, (int)x, ySlot, a);
x += 20;
}
_inventoryNeedsUpdate = false;
//_inventoryRc = t.end(_inventoryRc.vboId);
//drawArrayVTC(_inventoryRc.vboId, _inventoryRc.vertexCount);
//renderSlotWatch.stop();
//renderSlotWatch.printEvery(100, "Render slots:");
//int x = screenWidth / 2 + getNumSlots() * 10 + (getNumSlots()-1) * 20 + 2;
blit(screenWidth / 2 + 10 * getNumSlots() - 20 + 4, ySlot + 6, 242, 252, 14, 4, 14, 4);
minecraft->textures->loadAndBindTexture("gui/gui_blocks.png");
t.endOverrideAndDraw();
// Render damaged items (@todo: investigate if it's faster by drawing in same batch)
glDisable2(GL_DEPTH_TEST);
glDisable2(GL_TEXTURE_2D);
t.beginOverride();
x = baseItemX;
for (int i = 0; i < getNumSlots()-1; i++) {
ItemRenderer::renderGuiItemDecorations(minecraft->player->inventory->getItem(i), x, (float)ySlot);
x += 20;
}
t.endOverrideAndDraw();
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
//w.stop();
//w.printEvery(100, "gui-slots");
// Draw count
//Tesselator& t = Tesselator::instance;
glPushMatrix2();
glScalef2(InvGuiScale + InvGuiScale, InvGuiScale + InvGuiScale, 1);
const float k = 0.5f * GuiScale;
t.beginOverride();
if (minecraft->gameMode->isSurvivalType()) {
x = baseItemX;
for (int i = 0; i < getNumSlots()-1; i++) {
ItemInstance* item = minecraft->player->inventory->getItem(i);
if (item && item->count >= 0)
renderSlotText(item, k*x, k*ySlot + 1, true, true);
x += 20;
}
}
minecraft->textures->loadAndBindTexture("font/default8.png");
t.endOverrideAndDraw();
glPopMatrix2();
}

122
src/client/gui/Gui.h Executable file
View File

@@ -0,0 +1,122 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__Gui_H__
#define NET_MINECRAFT_CLIENT_GUI__Gui_H__
//package net.minecraft.client.gui;
#include "GuiComponent.h"
#include "Font.h"
#include "../player/input/touchscreen/TouchAreaModel.h"
#include "../renderer/RenderChunk.h"
#include "../../util/Random.h"
#include "../IConfigListener.h"
class Minecraft;
class ItemInstance;
class Textures;
class Tesselator;
struct IntRectangle;
struct GuiMessage
{
std::string message;
int ticks;
};
typedef std::vector<GuiMessage> GuiMessageList;
class Gui: public GuiComponent, IConfigListener
{
public:
Gui(Minecraft* minecraft);
~Gui();
int getSlotIdAt(int x, int y);
void flashSlot(int slotId);
bool isInside(int x, int y);
RectangleArea getRectangleArea(int extendSide);
void getSlotPos(int slot, int& posX, int& posY);
int getNumSlots();
void handleClick(int button, int x, int y);
void handleKeyPressed( int key );
void tick();
void render(float a, bool mouseFree, int xMouse, int yMouse);
void renderToolBar( float a, int ySlot, const int screenWidth );
void renderChatMessages( const int screenHeight, unsigned int max, bool isChatting, Font* font );
void renderOnSelectItemNameText( const int screenWidth, Font* font, int ySlot );
void renderSleepAnimation( const int screenWidth, const int screenHeight );
void renderBubbles();
void renderHearts();
void renderDebugInfo();
void renderProgressIndicator( const bool isTouchInterface, const int screenWidth, const int screenHeight, float a );
void addMessage(const std::string& string);
void postError(int errCode);
void onGraphicsReset();
void inventoryUpdated();
void setNowPlaying(const std::string& string);
void displayClientMessage(const std::string& messageId);
void renderSlotText(const ItemInstance* item, float x, float y, bool hasFinite, bool shadow);
void texturesLoaded( Textures* textures );
void onConfigChanged(const Config& config);
void onLevelGenerated();
void setScissorRect(const IntRectangle& rect);
static float floorAlignToScreenPixel(float);
static int itemCountItoa(char* buf, int count);
private:
void renderVignette(float br, int w, int h);
void renderSlot(int slot, int x, int y, float a);
void tickItemDrop();
float cubeSmoothStep(float percentage, float min, float max);
public:
float progress;
std::string selectedName;
static float InvGuiScale;
static float GuiScale;
private:
int MAX_MESSAGE_WIDTH;
//ItemRenderer itemRenderer;
GuiMessageList guiMessages;
Random random;
Minecraft* minecraft;
int tickCount;
float itemNameOverlayTime;
std::string overlayMessageString;
int overlayMessageTime;
bool animateOverlayMessageColor;
float tbr;
RenderChunk _inventoryRc;
bool _inventoryNeedsUpdate;
int _flashSlotId;
float _flashSlotStartTime;
Font* _slotFont;
int _numSlots;
RenderChunk rcFeedbackOuter;
RenderChunk rcFeedbackInner;
// For dropping
static const float DropTicks;
float _currentDropTicks;
int _currentDropSlot;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__Gui_H__*/

156
src/client/gui/GuiComponent.cpp Executable file
View File

@@ -0,0 +1,156 @@
#include "GuiComponent.h"
#include "../renderer/Tesselator.h"
#include "../renderer/gles.h"
#include "Font.h"
GuiComponent::GuiComponent()
: blitOffset(0)
{
}
GuiComponent::~GuiComponent()
{
}
void GuiComponent::drawCenteredString( Font* font, const std::string& str, int x, int y, int color )
{
font->drawShadow(str, (float)(x - font->width(str) / 2), (float)(y - font->height(str) / 2), color);
}
void GuiComponent::drawString( Font* font, const std::string& str, int x, int y, int color )
{
font->drawShadow(str, (float)x, (float)y /*- font->height(str)/2*/, color);
}
void GuiComponent::blit( int x, int y, int sx, int sy, int w, int h, int sw/*=0*/, int sh/*=0*/ )
{
if (!sw) sw = w;
if (!sh) sh = h;
float us = 1 / 256.0f;
float vs = 1 / 256.0f;
Tesselator& t = Tesselator::instance;
t.begin();
t.vertexUV((float)(x) , (float)(y + h), blitOffset, (float)(sx ) * us, (float)(sy + sh) * vs);
t.vertexUV((float)(x + w), (float)(y + h), blitOffset, (float)(sx + sw) * us, (float)(sy + sh) * vs);
t.vertexUV((float)(x + w), (float)(y) , blitOffset, (float)(sx + sw) * us, (float)(sy ) * vs);
t.vertexUV((float)(x) , (float)(y) , blitOffset, (float)(sx ) * us, (float)(sy ) * vs);
t.draw();
}
void GuiComponent::blit( float x, float y, int sx, int sy, float w, float h, int sw/*=0*/, int sh/*=0*/ )
{
if (!sw) sw = (int)w;
if (!sh) sh = (int)h;
float us = 1 / 256.0f;
float vs = 1 / 256.0f;
Tesselator& t = Tesselator::instance;
t.begin();
t.vertexUV(x , y + h, blitOffset, (float)(sx ) * us, (float)(sy + sh) * vs);
t.vertexUV(x + w, y + h, blitOffset, (float)(sx + sw) * us, (float)(sy + sh) * vs);
t.vertexUV(x + w, y , blitOffset, (float)(sx + sw) * us, (float)(sy ) * vs);
t.vertexUV(x , y , blitOffset, (float)(sx ) * us, (float)(sy ) * vs);
t.draw();
}
void GuiComponent::fill( int x0, int y0, int x1, int y1, int col ) {
fill((float)x0, (float)y0, (float)x1, (float)y1, col);
}
void GuiComponent::fill( float x0, float y0, float x1, float y1, int col )
{
//float a = ((col >> 24) & 0xff) / 255.0f;
//float r = ((col >> 16) & 0xff) / 255.0f;
//float g = ((col >> 8) & 0xff) / 255.0f;
//float b = ((col) & 0xff) / 255.0f;
//glColor4f2(r, g, b, a);
Tesselator& t = Tesselator::instance;
glEnable2(GL_BLEND);
glDisable2(GL_TEXTURE_2D);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//LOGI("col: %f, %f, %f, %f\n", r, g, b, a);
t.begin();
const int color = (col&0xff00ff00) | ((col&0xff0000) >> 16) | ((col&0xff) << 16);
t.colorABGR(color);
t.vertex(x0, y1, 0);
t.vertex(x1, y1, 0);
t.vertex(x1, y0, 0);
t.vertex(x0, y0, 0);
t.draw();
glEnable2(GL_TEXTURE_2D);
glDisable2(GL_BLEND);
}
void GuiComponent::fillGradient( int x0, int y0, int x1, int y1, int col1, int col2 ) {
fillGradient((float)x0, (float)y0, (float)x1, (float)y1, col1, col2);
}
void GuiComponent::fillGradient( float x0, float y0, float x1, float y1, int col1, int col2 )
{
float a1 = ((col1 >> 24) & 0xff) / 255.0f;
float r1 = ((col1 >> 16) & 0xff) / 255.0f;
float g1 = ((col1 >> 8) & 0xff) / 255.0f;
float b1 = ((col1) & 0xff) / 255.0f;
float a2 = ((col2 >> 24) & 0xff) / 255.0f;
float r2 = ((col2 >> 16) & 0xff) / 255.0f;
float g2 = ((col2 >> 8) & 0xff) / 255.0f;
float b2 = ((col2) & 0xff) / 255.0f;
glDisable2(GL_TEXTURE_2D);
glEnable2(GL_BLEND);
glDisable2(GL_ALPHA_TEST);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel2(GL_SMOOTH);
Tesselator& t = Tesselator::instance;
t.begin();
t.color(r1, g1, b1, a1);
t.vertex(x1, y0, 0);
t.vertex(x0, y0, 0);
t.color(r2, g2, b2, a2);
t.vertex(x0, y1, 0);
t.vertex(x1, y1, 0);
t.draw();
glShadeModel2(GL_FLAT);
glDisable2(GL_BLEND);
glEnable2(GL_ALPHA_TEST);
glEnable2(GL_TEXTURE_2D);
}
void GuiComponent::fillHorizontalGradient( int x0, int y0, int x1, int y1, int col1, int col2 ) {
fillHorizontalGradient((float)x0, (float)y0, (float)x1, (float)y1, col1, col2);
}
void GuiComponent::fillHorizontalGradient( float x0, float y0, float x1, float y1, int col1, int col2 )
{
float a1 = ((col1 >> 24) & 0xff) / 255.0f;
float r1 = ((col1 >> 16) & 0xff) / 255.0f;
float g1 = ((col1 >> 8) & 0xff) / 255.0f;
float b1 = ((col1) & 0xff) / 255.0f;
float a2 = ((col2 >> 24) & 0xff) / 255.0f;
float r2 = ((col2 >> 16) & 0xff) / 255.0f;
float g2 = ((col2 >> 8) & 0xff) / 255.0f;
float b2 = ((col2) & 0xff) / 255.0f;
glDisable2(GL_TEXTURE_2D);
glEnable2(GL_BLEND);
glDisable2(GL_ALPHA_TEST);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glShadeModel2(GL_SMOOTH);
Tesselator& t = Tesselator::instance;
t.begin();
t.color(r2, g2, b2, a2);
t.vertex(x1, y0, 0);
t.color(r1, g1, b1, a1);
t.vertex(x0, y0, 0);
t.color(r1, g1, b1, a1);
t.vertex(x0, y1, 0);
t.color(r2, g2, b2, a2);
t.vertex(x1, y1, 0);
t.draw();
glShadeModel2(GL_FLAT);
glDisable2(GL_BLEND);
glEnable2(GL_ALPHA_TEST);
glEnable2(GL_TEXTURE_2D);
}

34
src/client/gui/GuiComponent.h Executable file
View File

@@ -0,0 +1,34 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__GuiComponent_H__
#define NET_MINECRAFT_CLIENT_GUI__GuiComponent_H__
//package net.minecraft.client.gui;
#include <string>
class Font;
class Minecraft;
class GuiComponent
{
public:
GuiComponent();
virtual ~GuiComponent();
void drawString(Font* font, const std::string& str, int x, int y, int color);
void drawCenteredString(Font* font, const std::string& str, int x, int y, int color);
void blit(int x, int y, int sx, int sy, int w, int h, int sw=0, int sh=0);
void blit(float x, float y, int sx, int sy, float w, float h, int sw=0, int sh=0);
protected:
void fill(int x0, int y0, int x1, int y1, int col);
void fill(float x0, float y0, float x1, float y1, int col);
void fillGradient(int x0, int y0, int x1, int y1, int col1, int col2);
void fillGradient(float x0, float y0, float x1, float y1, int col1, int col2);
void fillHorizontalGradient(int x0, int y0, int x1, int y1, int col1, int col2);
void fillHorizontalGradient(float x0, float y0, float x1, float y1, int col1, int col2);
float blitOffset;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__GuiComponent_H__*/

255
src/client/gui/Screen.cpp Executable file
View File

@@ -0,0 +1,255 @@
#include "Screen.h"
#include "components/Button.h"
#include "components/TextBox.h"
#include "../Minecraft.h"
#include "../renderer/Tesselator.h"
#include "../sound/SoundEngine.h"
#include "../../platform/input/Keyboard.h"
#include "../../platform/input/Mouse.h"
#include "../renderer/Textures.h"
Screen::Screen()
: passEvents(false),
clickedButton(NULL),
tabButtonIndex(0),
width(1),
height(1),
minecraft(NULL),
font(NULL)
{
}
void Screen::render( int xm, int ym, float a )
{
for (unsigned int i = 0; i < buttons.size(); i++) {
Button* button = buttons[i];
button->render(minecraft, xm, ym);
}
}
void Screen::init( Minecraft* minecraft, int width, int height )
{
//particles = /*new*/ GuiParticles(minecraft);
this->minecraft = minecraft;
this->font = minecraft->font;
this->width = width;
this->height = height;
init();
setupPositions();
updateTabButtonSelection();
}
void Screen::init()
{
}
void Screen::setSize( int width, int height )
{
this->width = width;
this->height = height;
setupPositions();
}
bool Screen::handleBackEvent( bool isDown )
{
return false;
}
void Screen::updateEvents()
{
if (passEvents)
return;
while (Mouse::next())
mouseEvent();
while (Keyboard::next())
keyboardEvent();
while (Keyboard::nextTextChar())
keyboardTextEvent();
}
void Screen::mouseEvent()
{
const MouseAction& e = Mouse::getEvent();
if (!e.isButton())
return;
if (Mouse::getEventButtonState()) {
int xm = e.x * width / minecraft->width;
int ym = e.y * height / minecraft->height - 1;
mouseClicked(xm, ym, Mouse::getEventButton());
} else {
int xm = e.x * width / minecraft->width;
int ym = e.y * height / minecraft->height - 1;
mouseReleased(xm, ym, Mouse::getEventButton());
}
}
void Screen::keyboardEvent()
{
if (Keyboard::getEventKeyState()) {
//if (Keyboard.getEventKey() == Keyboard.KEY_F11) {
// minecraft->toggleFullScreen();
// return;
//}
keyPressed(Keyboard::getEventKey());
}
}
void Screen::keyboardTextEvent()
{
keyboardNewChar(Keyboard::getChar());
}
void Screen::renderBackground()
{
renderBackground(0);
}
void Screen::renderBackground( int vo )
{
if (minecraft->isLevelGenerated()) {
fillGradient(0, 0, width, height, 0xc0101010, 0xd0101010);
} else {
renderDirtBackground(vo);
}
}
void Screen::renderDirtBackground( int vo )
{
//glDisable2(GL_LIGHTING);
glDisable2(GL_FOG);
Tesselator& t = Tesselator::instance;
minecraft->textures->loadAndBindTexture("gui/background.png");
glColor4f2(1, 1, 1, 1);
float s = 32;
float fvo = (float) vo;
t.begin();
t.color(0x404040);
t.vertexUV(0, (float)height, 0, 0, height / s + fvo);
t.vertexUV((float)width, (float)height, 0, width / s, (float)height / s + fvo);
t.vertexUV((float)width, 0, 0, (float)width / s, 0 + fvo);
t.vertexUV(0, 0, 0, 0, 0 + fvo);
t.draw();
}
bool Screen::isPauseScreen()
{
return true;
}
bool Screen::isErrorScreen()
{
return false;
}
bool Screen::isInGameScreen()
{
return true;
}
bool Screen::closeOnPlayerHurt() {
return false;
}
void Screen::keyPressed( int eventKey )
{
if (eventKey == Keyboard::KEY_ESCAPE) {
minecraft->setScreen(NULL);
//minecraft->grabMouse();
}
if (minecraft->useTouchscreen())
return;
// "Tabbing" the buttons (walking with keys)
const int tabButtonCount = tabButtons.size();
if (!tabButtonCount)
return;
Options& o = minecraft->options;
if (eventKey == o.keyMenuNext.key)
if (++tabButtonIndex == tabButtonCount) tabButtonIndex = 0;
if (eventKey == o.keyMenuPrevious.key)
if (--tabButtonIndex == -1) tabButtonIndex = tabButtonCount-1;
if (eventKey == o.keyMenuOk.key) {
Button* button = tabButtons[tabButtonIndex];
if (button->active) {
minecraft->soundEngine->playUI("random.click", 1, 1);
buttonClicked(button);
}
}
updateTabButtonSelection();
}
void Screen::updateTabButtonSelection()
{
if (minecraft->useTouchscreen())
return;
for (unsigned int i = 0; i < tabButtons.size(); ++i)
tabButtons[i]->selected = (i == tabButtonIndex);
}
void Screen::mouseClicked( int x, int y, int buttonNum )
{
if (buttonNum == MouseAction::ACTION_LEFT) {
for (unsigned int i = 0; i < buttons.size(); ++i) {
Button* button = buttons[i];
//LOGI("Hit-testing button: %p\n", button);
if (button->clicked(minecraft, x, y)) {
button->setPressed();
//LOGI("Hit-test successful: %p\n", button);
clickedButton = button;
/*
#if !defined(ANDROID) && !defined(__APPLE__) //if (!minecraft->isTouchscreen()) {
minecraft->soundEngine->playUI("random.click", 1, 1);
buttonClicked(button);
#endif }
*/
}
}
}
}
void Screen::mouseReleased( int x, int y, int buttonNum )
{
//LOGI("b_id: %d, (%p), text: %s\n", buttonNum, clickedButton, clickedButton?clickedButton->msg.c_str():"<null>");
if (!clickedButton || buttonNum != MouseAction::ACTION_LEFT) return;
#if 1
//#if defined(ANDROID) || defined(__APPLE__) //if (minecraft->isTouchscreen()) {
for (unsigned int i = 0; i < buttons.size(); ++i) {
Button* button = buttons[i];
if (clickedButton == button && button->clicked(minecraft, x, y)) {
buttonClicked(button);
minecraft->soundEngine->playUI("random.click", 1, 1);
clickedButton->released(x, y);
}
}
# else // } else {
clickedButton->released(x, y);
#endif // }
clickedButton = NULL;
}
bool Screen::renderGameBehind() {
return true;
}
bool Screen::hasClippingArea( IntRectangle& out )
{
return false;
}
void Screen::lostFocus() {
for(std::vector<TextBox*>::iterator it = textBoxes.begin(); it != textBoxes.end(); ++it) {
TextBox* tb = *it;
tb->loseFocus(minecraft);
}
}
void Screen::toGUICoordinate( int& x, int& y ) {
x = x * width / minecraft->width;
y = y * height / minecraft->height - 1;
}

80
src/client/gui/Screen.h Executable file
View File

@@ -0,0 +1,80 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__Screen_H__
#define NET_MINECRAFT_CLIENT_GUI__Screen_H__
//package net.minecraft.client.gui;
#include <vector>
#include "GuiComponent.h"
class Font;
class Minecraft;
class Button;
class TextBox;
struct IntRectangle;
class Screen: public GuiComponent
{
public:
Screen();
virtual void render(int xm, int ym, float a);
void init(Minecraft* minecraft, int width, int height);
virtual void init();
void setSize(int width, int height);
virtual void setupPositions() {};
virtual void updateEvents();
virtual void mouseEvent();
virtual void keyboardEvent();
virtual void keyboardTextEvent();
virtual bool handleBackEvent(bool isDown);
virtual void tick() {}
virtual void removed() {}
virtual void renderBackground();
virtual void renderBackground(int vo);
virtual void renderDirtBackground(int vo);
// query
virtual bool renderGameBehind();
virtual bool hasClippingArea(IntRectangle& out);
virtual bool isPauseScreen();
virtual bool isErrorScreen();
virtual bool isInGameScreen();
virtual bool closeOnPlayerHurt();
virtual void confirmResult(bool result, int id) {}
virtual void lostFocus();
virtual void toGUICoordinate(int& x, int& y);
protected:
void updateTabButtonSelection();
virtual void buttonClicked(Button* button) {}
virtual void mouseClicked(int x, int y, int buttonNum);
virtual void mouseReleased(int x, int y, int buttonNum);
virtual void keyPressed(int eventKey);
virtual void keyboardNewChar(char inputChar) {}
public:
int width;
int height;
bool passEvents;
//GuiParticles* particles;
protected:
Minecraft* minecraft;
std::vector<Button*> buttons;
std::vector<TextBox*> textBoxes;
std::vector<Button*> tabButtons;
int tabButtonIndex;
Font* font;
private:
Button* clickedButton;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__Screen_H__*/

11
src/client/gui/TweenData.h Executable file
View File

@@ -0,0 +1,11 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__TweenData_H__
#define NET_MINECRAFT_CLIENT_GUI__TweenData_H__
typedef struct TweenData {
float cur;
float dur;
float start;
float stop;
} TweenData;
#endif /*NET_MINECRAFT_CLIENT_GUI__TweenData_H__*/

View File

@@ -0,0 +1,218 @@
#include "Button.h"
#include "../../Minecraft.h"
#include "../../renderer/Textures.h"
Button::Button(int id, const std::string& msg)
: GuiElement(true, true, 0, 0, 200, 24),
id(id),
msg(msg),
selected(false),
_currentlyDown(false)
{
}
Button::Button( int id, int x, int y, const std::string& msg )
: GuiElement(true, true, x, y, 200, 24),
id(id),
msg(msg),
selected(false),
_currentlyDown(false)
{
}
Button::Button( int id, int x, int y, int w, int h, const std::string& msg )
: GuiElement(true, true, x, y, w, h),
id(id),
msg(msg),
selected(false),
_currentlyDown(false)
{
}
void Button::render( Minecraft* minecraft, int xm, int ym )
{
if (!visible) return;
/*
minecraft->textures->loadAndBindTexture("gui/gui.png");
glColor4f2(1, 1, 1, 1);
//printf("ButtonId: %d - Hovered? %d (cause: %d, %d, %d, %d, <> %d, %d)\n", id, hovered, x, y, x+w, y+h, xm, ym);
int yImage = getYImage(hovered || selected);
blit(x, y, 0, 46 + yImage * 20, w / 2, h, 0, 20);
blit(x + w / 2, y, 200 - w / 2, 46 + yImage * 20, w / 2, h, 0, 20);
*/
renderBg(minecraft, xm, ym);
renderFace(minecraft, xm , ym);
}
void Button::released( int mx, int my ) {
_currentlyDown = false;
}
bool Button::clicked( Minecraft* minecraft, int mx, int my )
{
return active && mx >= x && my >= y && mx < x + width && my < y + height;
}
void Button::setPressed() {
_currentlyDown = true;
}
int Button::getYImage( bool hovered )
{
int res = 1;
if (!active) res = 0;
else if (hovered) res = 2;
return res;
}
void Button::renderFace(Minecraft* mc, int xm, int ym) {
Font* font = mc->font;
if (!active) {
drawCenteredString(font, msg, x + width / 2, y + (height - 8) / 2, 0xffa0a0a0);
} else {
if (hovered(mc, xm, ym) || selected) {
drawCenteredString(font, msg, x + width / 2, y + (height - 8) / 2, 0xffffa0);
} else {
drawCenteredString(font, msg, x + width / 2, y + (height - 8) / 2, 0xe0e0e0);
}
}
}
void Button::renderBg( Minecraft* minecraft, int xm, int ym )
{
minecraft->textures->loadAndBindTexture("gui/gui.png");
glColor4f2(1, 1, 1, 1);
//printf("ButtonId: %d - Hovered? %d (cause: %d, %d, %d, %d, <> %d, %d)\n", id, hovered, x, y, x+w, y+h, xm, ym);
int yImage = getYImage(selected || hovered(minecraft, xm, ym));;
blit(x, y, 0, 46 + yImage * 20, width / 2, height, 0, 20);
blit(x + width / 2, y, 200 - width / 2, 46 + yImage * 20, width / 2, height, 0, 20);
}
bool Button::hovered(Minecraft* minecraft, int xm , int ym) {
return minecraft->useTouchscreen()? (_currentlyDown && isInside(xm, ym)) : false;
}
bool Button::isInside( int xm, int ym ) {
return xm >= x && ym >= y && xm < x + width && ym < y + height;
}
//
// BlankButton
//
BlankButton::BlankButton(int id)
: super(id, "")
{
visible = false;
}
BlankButton::BlankButton(int id, int x, int y, int w, int h)
: super(id, x, y, w, h, "")
{
visible = false;
}
//
// The Touch-interface button
//
namespace Touch {
TButton::TButton(int id, const std::string& msg)
: super(id, msg)
{
width = 66;
height = 26;
}
TButton::TButton( int id, int x, int y, const std::string& msg )
: super(id, x, y, msg)
{
width = 66;
height = 26;
}
TButton::TButton( int id, int x, int y, int w, int h, const std::string& msg )
: super(id, x, y, w, h, msg)
{
}
void TButton::renderBg( Minecraft* minecraft, int xm, int ym )
{
bool hovered = active && (minecraft->useTouchscreen()? (_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height) : false);
minecraft->textures->loadAndBindTexture("gui/touchgui.png");
//printf("ButtonId: %d - Hovered? %d (cause: %d, %d, %d, %d, <> %d, %d)\n", id, hovered, x, y, x+w, y+h, xm, ym);
if (active)
glColor4f2(1, 1, 1, 1);
else
glColor4f2(0.5f, 0.5f, 0.5f, 1);
blit(x, y, hovered?66:0, 0, width, height, 66, 26);
//blit(x + w / 2, y, 200 - w / 2, 46 + yImage * 20, w / 2, h, 0, 20);
}
//
// Header spacing in Touchscreen mode
//
THeader::THeader(int id, const std::string& msg)
: super(id, msg),
xText(-99999)
{
active = false;
width = 66;
height = 26;
}
THeader::THeader( int id, int x, int y, const std::string& msg )
: super(id, x, y, msg),
xText(-99999)
{
active = false;
width = 66;
height = 26;
}
THeader::THeader( int id, int x, int y, int w, int h, const std::string& msg )
: super(id, x, y, w, h, msg),
xText(-99999)
{
active = false;
}
void THeader::render( Minecraft* minecraft, int xm, int ym ) {
Font* font = minecraft->font;
renderBg(minecraft, xm, ym);
int xx = x + width/2;
if (xText != -99999)
xx = xText;
drawCenteredString(font, msg, xx, y + (height - 8) / 2, 0xe0e0e0);
}
void THeader::renderBg( Minecraft* minecraft, int xm, int ym )
{
minecraft->textures->loadAndBindTexture("gui/touchgui.png");
//printf("ButtonId: %d - Hovered? %d (cause: %d, %d, %d, %d, <> %d, %d)\n", id, hovered, x, y, x+w, y+h, xm, ym);
glColor4f2(1, 1, 1, 1);
// Left cap
blit(x, y, 150, 26, 2, height-1, 2, 25);
// Middle
blit(x+2, y, 153, 26, width-3, height-1, 8, 25);
// Right cap
blit(x+width-2, y, 162, 26, 2, height-1, 2, 25);
// Shadow
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
blit(x, y+height-1, 153, 52, width, 3, 8, 3);
}
};

View File

@@ -0,0 +1,80 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__Button_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__Button_H__
//package net.minecraft.client.gui;
#include <string>
#include "GuiElement.h"
#include "../../Options.h"
class Font;
class Minecraft;
class Button: public GuiElement
{
public:
Button(int id, const std::string& msg);
Button(int id, int x, int y, const std::string& msg);
Button(int id, int x, int y, int w, int h, const std::string& msg);
virtual ~Button() {}
virtual void render(Minecraft* minecraft, int xm, int ym);
virtual bool clicked(Minecraft* minecraft, int mx, int my);
virtual void released(int mx, int my);
virtual void setPressed();
bool isInside(int xm, int ym);
protected:
virtual int getYImage(bool hovered);
virtual void renderBg(Minecraft* minecraft, int xm, int ym);
virtual void renderFace(Minecraft* minecraft, int xm, int ym);
bool hovered(Minecraft* minecraft, int xm, int ym);
public:
std::string msg;
int id;
bool selected;
protected:
bool _currentlyDown;
};
// @note: A bit backwards, but this is a button that
// only reacts to clicks, but isn't rendered.
class BlankButton: public Button
{
typedef Button super;
public:
BlankButton(int id);
BlankButton(int id, int x, int y, int w, int h);
};
namespace Touch {
class TButton: public Button
{
typedef Button super;
public:
TButton(int id, const std::string& msg);
TButton(int id, int x, int y, const std::string& msg);
TButton(int id, int x, int y, int w, int h, const std::string& msg);
protected:
virtual void renderBg(Minecraft* minecraft, int xm, int ym);
};
// "Header" in Touchscreen mode
class THeader: public Button {
typedef Button super;
public:
THeader(int id, const std::string& msg);
THeader(int id, int x, int y, const std::string& msg);
THeader(int id, int x, int y, int w, int h, const std::string& msg);
protected:
virtual void renderBg(Minecraft* minecraft, int xm, int ym);
void render( Minecraft* minecraft, int xm, int ym );
public:
int xText;
};
}
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__Button_H__*/

View File

@@ -0,0 +1 @@
#include "GuiElement.h"

View File

@@ -0,0 +1,55 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__GButton_H__
#define NET_MINECRAFT_CLIENT_GUI__GButton_H__
#include "Button.h"
class GButton: public Button {
typedef Button super;
public:
static const int LayerDefault = 1;
static const int LayerSelected = 2;
static const int LayerMax = 4;
GButton(int id)
: super(id, "")
{}
~GButton() {
for (unsigned int i = 0; i < layers.size(); ++i) {
delete layers[i].first;
}
}
void addElement(int layerId, GuiElement* e) {
if (!e || layerId < 0 || layerId >= LayerMax) {
LOGE("Error @ GButton::element : Trying to add element %p at layer: %d\n", e, layerId);
return;
}
layers.push_back(std::make_pair(e, layerId));
}
void render( Minecraft* minecraft, int xm, int ym )
{
if (!visible) return;
bool isHovered = minecraft->isTouchscreen()?
(_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height): false;
int layer = isHovered? LayerSelected : LayerDefault;
if (layer < 0) return;
Tesselator& t = Tesselator::instance;
t.addOffset((float)x, (float)y, 0);
for (unsigned int i = 0; i < layers.size(); ++i) {
if ((layers[i].second & layer) != 0)
layers[i].first->render(minecraft, 0, 0);
}
t.addOffset((float)-x, (float)-y, 0);
}
private:
std::vector<std::pair<GuiElement*, int> > layers;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__GButton_H__*/

View File

@@ -0,0 +1,20 @@
#include "GuiElement.h"
GuiElement::GuiElement( bool active/*=false*/, bool visible/*=true*/, int x /*= 0*/, int y /*= 0*/, int width/*=24*/, int height/*=24*/ )
: active(active),
visible(visible),
x(x),
y(y),
width(width),
height(height) {
}
bool GuiElement::pointInside( int x, int y ) {
if(x >= this->x && x < this->x + this->width) {
if(y >= this->y && y < this->y + this->height) {
return true;
}
}
return false;
}

View File

@@ -0,0 +1,27 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__GuiElement_H__
#define NET_MINECRAFT_CLIENT_GUI__GuiElement_H__
#include "../GuiComponent.h"
class Tesselator;
class Minecraft;
class GuiElement : public GuiComponent {
public:
GuiElement(bool active=false, bool visible=true, int x = 0, int y = 0, int width=24, int height=24);
virtual ~GuiElement() {}
virtual void tick(Minecraft* minecraft) {}
virtual void render(Minecraft* minecraft, int xm, int ym) { }
virtual void setupPositions() {}
virtual void mouseClicked(Minecraft* minecraft, int x, int y, int buttonNum) {}
virtual void mouseReleased(Minecraft* minecraft, int x, int y, int buttonNum) {}
virtual bool pointInside(int x, int y);
void setVisible(bool visible);
bool active;
bool visible;
int x;
int y;
int width;
int height;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__GuiElement_H__*/

View File

@@ -0,0 +1,54 @@
#include "GuiElementContainer.h"
#include <algorithm>
GuiElementContainer::GuiElementContainer( bool active/*=false*/, bool visible/*=true*/, int x /*= 0*/, int y /*= 0*/, int width/*=24*/, int height/*=24*/ )
: GuiElement(active, visible, x, y, width, height) {
}
GuiElementContainer::~GuiElementContainer() {
while(!children.empty()) {
GuiElement* element = children.back();
children.pop_back();
delete element;
}
}
void GuiElementContainer::render( Minecraft* minecraft, int xm, int ym ) {
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->render(minecraft, xm, ym);
}
}
void GuiElementContainer::setupPositions() {
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->setupPositions();
}
}
void GuiElementContainer::addChild( GuiElement* element ) {
children.push_back(element);
}
void GuiElementContainer::removeChild( GuiElement* element ) {
std::vector<GuiElement*>::iterator it = std::find(children.begin(), children.end(), element);
if(it != children.end())
children.erase(it);
}
void GuiElementContainer::tick( Minecraft* minecraft ) {
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->tick(minecraft);
}
}
void GuiElementContainer::mouseClicked( Minecraft* minecraft, int x, int y, int buttonNum ) {
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->mouseClicked(minecraft, x, y, buttonNum);
}
}
void GuiElementContainer::mouseReleased( Minecraft* minecraft, int x, int y, int buttonNum ) {
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->mouseReleased(minecraft, x, y, buttonNum);
}
}

View File

@@ -0,0 +1,27 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__GuiElementContainer_H__
#define NET_MINECRAFT_CLIENT_GUI__GuiElementContainer_H__
#include "GuiElement.h"
#include <vector>
class Tesselator;
class Minecraft;
class GuiElementContainer : public GuiElement {
public:
GuiElementContainer(bool active=false, bool visible=true, int x = 0, int y = 0, int width=24, int height=24);
virtual ~GuiElementContainer();
virtual void render(Minecraft* minecraft, int xm, int ym);
virtual void setupPositions();
virtual void addChild(GuiElement* element);
virtual void removeChild(GuiElement* element);
virtual void tick( Minecraft* minecraft );
virtual void mouseClicked( Minecraft* minecraft, int x, int y, int buttonNum );
virtual void mouseReleased( Minecraft* minecraft, int x, int y, int buttonNum );
protected:
std::vector<GuiElement*> children;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__GuiElementContainer_H__*/

View File

@@ -0,0 +1,160 @@
#include "ImageButton.h"
#include "../../renderer/Tesselator.h"
#include "../../Minecraft.h"
#include "../../../platform/log.h"
#include "../../../util/Mth.h"
#include "../../renderer/Textures.h"
ImageButton::ImageButton(int id, const std::string& msg)
: super(id, msg)
{
setupDefault();
}
ImageButton::ImageButton(int id, const std::string& msg, const ImageDef& imagedef)
: super(id, msg),
_imageDef(imagedef)
{
setupDefault();
}
void ImageButton::setupDefault() {
width = 48;
height = 48;
scaleWhenPressed = true;
}
void ImageButton::setImageDef(const ImageDef& imageDef, bool setButtonSize) {
_imageDef = imageDef;
if (setButtonSize) {
width = (int)_imageDef.width;
height = (int)_imageDef.height;
}
}
void ImageButton::render(Minecraft* minecraft, int xm, int ym) {
if (!visible) return;
Font* font = minecraft->font;
//minecraft->textures->loadAndBindTexture("gui/gui.png");
glColor4f2(1, 1, 1, 1);
bool hovered = active && (minecraft->useTouchscreen()? (_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height) : false);
bool IsSecondImage = isSecondImage(hovered);
//printf("ButtonId: %d - Hovered? %d (cause: %d, %d, %d, %d, <> %d, %d)\n", id, hovered, x, y, x+w, y+h, xm, ym);
//int yImage = getYImage(hovered || selected);
//blit(x, y, 0, 46 + yImage * 20, w / 2, h, 0, 20);
//blit(x + w / 2, y, 200 - w / 2, 46 + yImage * 20, w / 2, h, 0, 20);
renderBg(minecraft, xm, ym);
TextureId texId = (_imageDef.name.length() > 0)? minecraft->textures->loadAndBindTexture(_imageDef.name) : Textures::InvalidId;
if ( Textures::isTextureIdValid(texId) ) {
const ImageDef& d = _imageDef;
Tesselator& t = Tesselator::instance;
t.begin();
if (!active) t.color(0xff808080);
//else if (hovered||selected) t.color(0xffffffff);
//else t.color(0xffe0e0e0);
else t.color(0xffffffff);
float hx = ((float) d.width) * 0.5f;
float hy = ((float) d.height) * 0.5f;
const float cx = ((float)x+d.x) + hx;
const float cy = ((float)y+d.y) + hy;
if (scaleWhenPressed && hovered) {
hx *= 0.95f;
hy *= 0.95f;
}
const IntRectangle* src = _imageDef.getSrc();
if (src) {
const TextureData* d = minecraft->textures->getTemporaryTextureData(texId);
if (d != NULL) {
float u0 = (src->x+(IsSecondImage?src->w:0)) / (float)d->w;
float u1 = (src->x+(IsSecondImage?2*src->w:src->w)) / (float)d->w;
float v0 = src->y / (float)d->h;
float v1 = (src->y+src->h) / (float)d->h;
t.vertexUV(cx-hx, cy-hy, blitOffset, u0, v0);
t.vertexUV(cx-hx, cy+hy, blitOffset, u0, v1);
t.vertexUV(cx+hx, cy+hy, blitOffset, u1, v1);
t.vertexUV(cx+hx, cy-hy, blitOffset, u1, v0);
}
} else {
t.vertexUV(cx-hx, cy-hy, blitOffset, 0, 0);
t.vertexUV(cx-hx, cy+hy, blitOffset, 0, 1);
t.vertexUV(cx+hx, cy+hy, blitOffset, 1, 1);
t.vertexUV(cx+hx, cy-hy, blitOffset, 1, 0);
}
t.draw();
}
//blit(0, 0, 0, 0, 64, 64, 256, 256);
//LOGI("%d %d\n", x+d.x, x+d.x+d.w);
if (!active) {
drawCenteredString(font, msg, x + width / 2, y + 16/*(h - 16)*/, 0xffa0a0a0);
} else {
if (hovered || selected) {
drawCenteredString(font, msg, x + width / 2, y + 17/*(h - 16)*/, 0xffffa0);
} else {
drawCenteredString(font, msg, x + width / 2, y + 16/*(h - 48)*/, 0xe0e0e0);
}
}
}
//
// A toggleable Button
//
OptionButton::OptionButton(const Options::Option* option)
: _option(option),
_isFloat(false),
super(ButtonId, "")
{
}
OptionButton::OptionButton(const Options::Option* option, float onValue, float offValue)
: _option(option),
_isFloat(true),
_onValue(onValue),
_offValue(offValue),
super(ButtonId, "")
{
}
bool OptionButton::isSecondImage(bool hovered) {
return _secondImage;
}
void OptionButton::toggle(Options* options) {
if (_isFloat) {
options->set(_option, (Mth::abs(_current - _onValue) < 0.01f) ? _offValue : _onValue);
} else {
options->toggle(_option, 1);
}
// Update graphics here
updateImage(options);
}
void OptionButton::updateImage(Options* options) {
if (_isFloat) {
_current = options->getProgressValue(_option);
_secondImage = Mth::abs(_current - _onValue) < 0.01f;
} else {
_secondImage = options->getBooleanValue(_option);
}
}
void OptionButton::mouseClicked( Minecraft* minecraft, int x, int y, int buttonNum ) {
if(buttonNum == MouseAction::ACTION_LEFT) {
if(clicked(minecraft, x, y)) {
toggle(&minecraft->options);
}
}
}

View File

@@ -0,0 +1,105 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ImageButton_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ImageButton_H__
#include "Button.h"
typedef struct IntRectangle {
IntRectangle()
: x(0),
y(0),
w(1),
h(1)
{}
IntRectangle(int x, int y, int w, int h)
: x(x),
y(y),
w(w),
h(h)
{}
int x, y;
int w, h;
} IntRectangle;
typedef struct ImageDef {
ImageDef()
: hasSrc(false),
x(0),
y(0),
width(16),
height(16)
{}
std::string name;
int x;
int y;
float width;
float height;
ImageDef& setSrc(const IntRectangle& srcRect) {
hasSrc = true;
src = srcRect;
return *this;
}
IntRectangle* getSrc() {
return hasSrc? &src : NULL;
}
protected:
IntRectangle src;
bool hasSrc;
} ImageDef;
class ImageButton: public Button
{
typedef Button super;
public:
ImageButton(int id, const std::string& msg);
ImageButton(int id, const std::string& msg, const ImageDef& imageDef);
void setImageDef(const ImageDef& imageDef, bool setButtonSize);
void render(Minecraft* minecraft, int xm, int ym);
void renderBg(Minecraft* minecraft, int xm, int ym) {}
protected:
virtual void setupDefault();
virtual bool isSecondImage(bool hovered) { return hovered; }
ImageDef _imageDef;
public:
bool scaleWhenPressed;
};
//
// A toggleable Button
//
class OptionButton: public ImageButton
{
typedef ImageButton super;
public:
OptionButton(const Options::Option* option);
OptionButton(const Options::Option* option, float onValue, float offValue);
void toggle(Options* options);
void updateImage(Options* options);
static const int ButtonId = 9999999;
protected:
bool isSecondImage(bool hovered);
virtual void mouseClicked( Minecraft* minecraft, int x, int y, int buttonNum );
private:
const Options::Option* _option;
bool _secondImage;
// If not float, it's considered to be a boolean value
bool _isFloat;
float _onValue;
float _offValue;
float _current;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ImageButton_H__*/

View File

@@ -0,0 +1,206 @@
#include "InventoryPane.h"
#include "../Gui.h"
#include "../../Minecraft.h"
#include "../../player/input/touchscreen/TouchAreaModel.h"
#include "../../renderer/entity/ItemRenderer.h"
#include "../../renderer/Tesselator.h"
#include "../../renderer/Textures.h"
#include "../../../world/item/ItemInstance.h"
#include "../../../world/entity/player/Inventory.h"
namespace Touch {
static const int By = 6; // Border Frame height
InventoryPane::InventoryPane( IInventoryPaneCallback* screen, Minecraft* mc, const IntRectangle& rect, int paneWidth, float clickMarginH, int numItems, int itemSize, int itemBorderSize)
: screen(screen),
mc(mc),
paneWidth(paneWidth),
rect(rect),
super(
SF_LockX|/*SF_Scissor|*/SF_ShowScrollbar|SF_NoHoldSelect,
rect, // Pane rect
IntRectangle(0, 0, itemSize, itemSize), // Item rect
0, numItems, Gui::GuiScale),
BorderPixels(itemBorderSize),
lastItemIndex(-1),
lastItemTicks(-1),
fillMarginX(2),
fillMarginY(4),
markerType(1),
markerIndex(-1),
markerShare(0),
renderDecorations(true)
{
_clickArea = new RectangleArea(0, 0, 0, 0);
area._x0 = rect.x - clickMarginH;
area._x1 = rect.x + rect.w + clickMarginH;
area._y0 -= By;
area._y1 += By;
/*
const int left = bbox.x + (bbox.w - paneWidth) / 2;
bg.x = left;
bg.w = left + paneWidth; // @note: read as x1, not width
bg.y = bbox.y - fillMarginY;
bg.h = bbox.y + bbox.h + fillMarginY; // @note: read as y1, not width
*/
}
InventoryPane::~InventoryPane() {
delete _clickArea;
}
void InventoryPane::renderBatch( std::vector<GridItem>& items, float alpha )
{
//fill(bg.x, bg.y, bg.w, bg.h, 0xff333333);
fill((float)(bbox.x-fillMarginX-1), (float)(bbox.y-fillMarginY), (float)(bbox.x + bbox.w + fillMarginX+1), (float)(bbox.y + bbox.h + fillMarginY), 0xff333333);
//fill(0.0f, (float)(bbox.y-fillMarginY), 400.0f, (float)(bbox.y + bbox.h + fillMarginY), 0xff333333);//(float)(bbox.x-fillMarginX), (float)(bbox.y-fillMarginY), (float)(bbox.x + bbox.w + fillMarginX), (float)(bbox.y + bbox.h + fillMarginY), 0xff333333);
glEnable2(GL_BLEND);
glDisable2(GL_ALPHA_TEST);
std::vector<const ItemInstance*> inventoryItems = screen->getItems(this);
glEnable2(GL_SCISSOR_TEST);
GLuint x = (GLuint)(screenScale * bbox.x);
GLuint y = mc->height - (GLuint)(screenScale * (bbox.y + bbox.h));
GLuint w = (GLuint)(screenScale * bbox.w);
GLuint h = (GLuint)(screenScale * bbox.h);
glScissor(x, y, w, h);
Tesselator& t = Tesselator::instance;
t.beginOverride();
t.colorABGR(0xffffffff);
for (unsigned int i = 0; i < items.size(); ++i) {
GridItem& item = items[i];
blit(item.xf, item.yf, 200, 46, (float)itemBbox.w, (float)itemBbox.h, 16, 16);
}
mc->textures->loadAndBindTexture("gui/gui.png");
t.endOverrideAndDraw();
GridItem* marked = NULL;
float mxx, myy;
t.beginOverride();
for (unsigned int i = 0; i < items.size(); ++i) {
GridItem& item = items[i];
int j = item.id;
const ItemInstance* citem = inventoryItems[j];
if (!citem) continue;
bool allowed = true;
t.enableColor();
//#ifdef DEMO_MODE //@huge @attn
if (!screen->isAllowed(j)) { allowed = false; t.color( 64, 64, 64); }
else
//#endif
if (lastItemTicks > 0 && lastItemIndex == j) {
int gv = 255 - lastItemTicks * 15;
t.color(gv, gv, gv, (allowed && citem->count <= 0)?0x60:0xff);
} else {
t.color(255, 255, 255, (allowed && citem->count <= 0)?0x60:0xff);
}
t.noColor();
float xx = Gui::floorAlignToScreenPixel(item.xf + BorderPixels + 4);
float yy = Gui::floorAlignToScreenPixel(item.yf + BorderPixels + 4);
ItemRenderer::renderGuiItem(NULL, mc->textures, citem, xx, yy, 16, 16, false);
if (j == markerIndex && markerShare >= 0)
marked = &item, mxx = xx, myy = yy;
}
t.endOverrideAndDraw();
if (marked) {
glDisable2(GL_TEXTURE_2D);
const float yy0 = myy - 5.0f;
const float yy1 = yy0 + 2;
fill(mxx, yy0, mxx + 16.0f, yy1, 0xff606060);
fill(mxx, yy0, mxx + markerShare * 16.0f, yy1, markerType==1?0xff00ff00:0xff476543);
glEnable2(GL_BLEND);
glEnable2(GL_TEXTURE_2D);
}
if (!mc->isCreativeMode()) {
const float ikText = Gui::InvGuiScale + Gui::InvGuiScale;
const float kText = 0.5f * Gui::GuiScale;
t.beginOverride();
t.scale2d(ikText, ikText);
for (unsigned int i = 0; i < items.size(); ++i) {
GridItem& item = items[i];
const ItemInstance* citem = inventoryItems[item.id];
if (!citem) continue;
char buf[64] = {0};
/*int c = */ Gui::itemCountItoa(buf, citem->count);
float tx = Gui::floorAlignToScreenPixel(kText * (item.xf + BorderPixels + 3));
float ty = Gui::floorAlignToScreenPixel(kText * (item.yf + BorderPixels + 3));
mc->gui.renderSlotText(citem, tx, ty, true, true);
}
t.resetScale();
glEnable2(GL_BLEND);
t.endOverrideAndDraw();
}
if (renderDecorations) {
t.beginOverride();
for (unsigned int i = 0; i < items.size(); ++i) {
GridItem& item = items[i];
const ItemInstance* citem = inventoryItems[item.id];
if (!citem || citem->isNull()) continue;
if (citem->isDamaged()) {
ItemRenderer::renderGuiItemDecorations(citem, item.xf + 8, item.yf + 12);
}
}
glDisable2(GL_TEXTURE_2D);
t.endOverrideAndDraw();
glEnable2(GL_TEXTURE_2D);
}
glDisable2(GL_SCISSOR_TEST);
//fillGradient(bbox.x - 1, bbox.y, bbox.x + bbox.w + 1, bbox.y + 20, 0x99000000, 0x00000000);
//fillGradient(bbox.x - 1, bbox.y + bbox.h - 20, bbox.x + bbox.w + 1, bbox.y + bbox.h, 0x00000000, 0x99000000);
fillGradient(bg.x - fillMarginX, bbox.y, bg.w + fillMarginX, bbox.y + 20, 0x99000000, 0x00000000);
fillGradient(bg.x - fillMarginX, bbox.y + bbox.h - 20, bg.w + fillMarginX, bbox.y + bbox.h, 0x00000000, 0x99000000);
drawScrollBar(hScroll);
drawScrollBar(vScroll);
}
bool InventoryPane::onSelect( int gridId, bool selected )
{
//screen->onItemSelected(gridId);
if (screen->isAllowed(gridId))
if (screen->addItem(this, gridId)) {
lastItemIndex = gridId;
lastItemTicks = 7;
}
return false;
}
void InventoryPane::drawScrollBar( ScrollBar& sb ) {
if (sb.alpha <= 0)
return;
const int color = ((int)(255.0f * sb.alpha) << 24) | 0xaaaaaa;
const float xx = (float)(bbox.x + bbox.w);
fill(xx - sb.w, sb.y, xx, sb.y + sb.h, color);
}
void InventoryPane::tick()
{
--lastItemTicks;
super::tick();
}
void InventoryPane::setRenderDecorations( bool value ) {
renderDecorations = value;
}
}

View File

@@ -0,0 +1,62 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__InventoryPane_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__InventoryPane_H__
#include "ScrollingPane.h"
#include "ImageButton.h"
class Minecraft;
class ItemInstance;
class Font;
class IArea;
namespace Touch {
class IInventoryPaneCallback;
class InventoryPane: public ScrollingPane
{
typedef ScrollingPane super;
public:
InventoryPane(IInventoryPaneCallback* screen, Minecraft* mc, const IntRectangle& rect, int paneWidth, float clickMarginH, int numItems, int itemSize, int itemBorderSize);
~InventoryPane();
void tick();
void renderBatch( std::vector<GridItem>& item, float alpha );
bool onSelect( int gridId, bool selected );
void drawScrollBar( ScrollBar& hScroll );
void setRenderDecorations(bool value);
IntRectangle rect;
int paneWidth;
IArea* _clickArea;
IInventoryPaneCallback* screen;
Minecraft* mc;
int fillMarginX;
int fillMarginY;
int markerType;
int markerIndex;
float markerShare;
private:
int lastItemIndex;
int lastItemTicks;
int BorderPixels;
bool renderDecorations;
IntRectangle bg;
};
class IInventoryPaneCallback
{
public:
virtual ~IInventoryPaneCallback() {}
virtual bool addItem(const InventoryPane* forPane, int index) = 0;
virtual bool isAllowed( int slot ) = 0;
virtual std::vector<const ItemInstance*> getItems(const InventoryPane* forPane) = 0;
};
}
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__InventoryPane_H__*/

View File

@@ -0,0 +1,148 @@
#include "ItemPane.h"
#include "../Gui.h"
#include "../../renderer/gles.h"
#include "../../renderer/Tesselator.h"
#include "NinePatch.h"
#include "../../renderer/entity/ItemRenderer.h"
const int rgbActive = 0xfff0f0f0;
const int rgbInactive = 0xc0635558;
const int rgbInactiveShadow = 0xc0aaaaaa;
ItemPane::ItemPane( IItemPaneCallback* screen,
Textures* textures,
const IntRectangle& rect,
int numItems,
int guiHeight,
int physicalScreenHeight,
bool isVertical /*= true*/)
: super(
(isVertical?SF_LockX:SF_LockY)/*|SF_Scissor*/|SF_ShowScrollbar,
rect, // Pane rect
isVertical?IntRectangle(0, 0, rect.w, 22) // Item rect if vertical
:IntRectangle(0, 0, 32, rect.h), // Item rect if horizontal
isVertical?1:numItems, numItems, Gui::GuiScale),
screen(screen),
textures(textures),
physicalScreenHeight(physicalScreenHeight),
guiSlotItem(NULL),
guiSlotItemSelected(NULL),
isVertical(isVertical)
{
// Expand the area to make it easier to scroll
area._x0 -= 4;
area._x1 += 4;
area._y0 = 0;
area._y1 = (float)guiHeight;
// GUI
NinePatchFactory builder(textures, "gui/spritesheet.png");
guiSlotItem = builder.createSymmetrical(IntRectangle(20, 32, 8, 8), 2, 2);
guiSlotItemSelected = builder.createSymmetrical(IntRectangle(28, 32, 8, 8), 2, 2);
guiSlotItem->setSize((float)rect.w + 4, 22);
guiSlotItemSelected->setSize((float)rect.w + 4, 22);
}
ItemPane::~ItemPane() {
delete guiSlotItem;
delete guiSlotItemSelected;
}
void ItemPane::renderBatch( std::vector<GridItem>& items, float alpha )
{
//fill(bbox.x, bbox.y, bbox.x + bbox.w, bbox.y + bbox.h, 0xff666666);
const std::vector<CItem*>& cat = screen->getItems(this);
if (cat.empty()) return;
glEnable2(GL_SCISSOR_TEST);
GLuint x = (GLuint)(screenScale * bbox.x);
GLuint y = physicalScreenHeight - (GLuint)(screenScale * (bbox.y + bbox.h));
GLuint w = (GLuint)(screenScale * bbox.w);
GLuint h = (GLuint)(screenScale * bbox.h);
glScissor(x, y, w, h);
Tesselator& t = Tesselator::instance;
t.beginOverride();
for (unsigned int i = 0; i < items.size(); ++i) {
GridItem& item = items[i];
(item.selected? guiSlotItemSelected : guiSlotItem)->draw(t, Gui::floorAlignToScreenPixel(item.xf-1), Gui::floorAlignToScreenPixel(item.yf));
}
t.endOverrideAndDraw();
t.beginOverride();
for (unsigned int i = 0; i < items.size(); ++i) {
GridItem& item = items[i];
CItem* citem = cat[item.id];
ItemRenderer::renderGuiItem(NULL, textures, &citem->item,
Gui::floorAlignToScreenPixel(item.xf + itemBbox.w - 16),
Gui::floorAlignToScreenPixel(2 + item.yf), 16, 16, false);
}
t.endOverrideAndDraw();
t.beginOverride();
for (unsigned int i = 0; i < items.size(); ++i) {
GridItem& item = items[i];
CItem* citem = cat[item.id];
char buf[64] = {0};
int c = Gui::itemCountItoa(buf, citem->inventoryCount);
float xf = item.xf - 1;
if (citem->canCraft()) {
f->drawShadow(citem->text,
Gui::floorAlignToScreenPixel(xf + 2),
Gui::floorAlignToScreenPixel(item.yf + 6), rgbActive);
t.scale2d(0.6667f, 0.6667f);
f->drawShadow(buf,
Gui::floorAlignToScreenPixel(1.5f * (xf + itemBbox.w - c*4)),
Gui::floorAlignToScreenPixel(1.5f * (item.yf + itemBbox.h - 8)), rgbActive);
t.resetScale();
} else {
f->draw(citem->text,
Gui::floorAlignToScreenPixel(xf + 3),
Gui::floorAlignToScreenPixel(item.yf + 7), rgbInactiveShadow);
f->draw(citem->text,
Gui::floorAlignToScreenPixel(xf + 2),
Gui::floorAlignToScreenPixel(item.yf + 6), rgbInactive);
t.scale2d(0.6667f, 0.6667f);
f->draw(buf,
Gui::floorAlignToScreenPixel(1.5f * (xf + itemBbox.w - c*4)),
Gui::floorAlignToScreenPixel(1.5f * (item.yf + itemBbox.h - 8)), rgbInactive);
t.resetScale();
}
}
t.endOverrideAndDraw();
//fillGradient(bbox.x, bbox.y, bbox.x + bbox.w, 20, 0x00000000, 0x80ff0000)
if (isVertical) {
fillGradient(bbox.x, bbox.y, bbox.x + bbox.w, bbox.y + 28, 0xbb000000, 0x00000000);
fillGradient(bbox.x, bbox.y + bbox.h - 28, bbox.x + bbox.w, bbox.y + bbox.h, 0x00000000, 0xbb000000);//0xbb2A272B);
} else {
fillHorizontalGradient(bbox.x, bbox.y, bbox.x + 28, bbox.y + bbox.h, 0xbb000000, 0x00000000);
fillHorizontalGradient(bbox.x + bbox.w - 28, bbox.y, bbox.x + bbox.w, bbox.y + bbox.h, 0x00000000, 0xbb000000);//0xbb2A272B);
}
//LOGI("scroll: %f - %f, %f :: %f, %f\n", hScroll.alpha, hScroll.x, hScroll.y, hScroll.w, hScroll.h);
glDisable2(GL_SCISSOR_TEST);
drawScrollBar(hScroll);
drawScrollBar(vScroll);
}
bool ItemPane::onSelect( int gridId, bool selected )
{
if (selected)
screen->onItemSelected(this, gridId);
return selected;
}
void ItemPane::drawScrollBar( ScrollBar& sb ) {
if (sb.alpha <= 0)
return;
int color = ((int)(255.0f * sb.alpha) << 24) | 0xffffff;
fill(2 + sb.x, sb.y, 2 + sb.x + sb.w, sb.y + sb.h, color);
}

View File

@@ -0,0 +1,95 @@
#ifndef ITEMPANE_H__
#define ITEMPANE_H__
#include <string>
#include <vector>
#include "ScrollingPane.h"
#include "../../../world/item/ItemInstance.h"
class Font;
class Textures;
class NinePatchLayer;
class Recipe;
class ItemPane;
class CItem
{
public:
CItem(const ItemInstance& ins, Recipe* recipe, const std::string& text)
: item(ins),
recipe(recipe),
text(text),
sortText(text),
//maxBuildCount(0),
numBuilt(0),
inventoryCount(0),
_canCraft(false)
{
}
typedef struct ReqItem {
ReqItem() {}
ReqItem(const ItemInstance& needItem, int has)
: item(needItem), has(has) {}
ItemInstance item;
int has;
bool enough() { return has >= item.count; }
} ReqItem;
bool canCraft() {
return _canCraft;// || maxBuildCount > 0;
}
void setCanCraft(bool status) {
_canCraft = status;
}
ItemInstance item;
Recipe* recipe;
std::string text;
std::string sortText;
//int maxBuildCount;
int numBuilt;
int inventoryCount;
std::vector<ReqItem> neededItems;
private:
bool _canCraft;
};
class IItemPaneCallback
{
public:
virtual ~IItemPaneCallback() {}
virtual void onItemSelected(const ItemPane* forPane, int index) = 0;
virtual const std::vector<CItem*>& getItems(const ItemPane* forPane) = 0;
};
class ItemPane: public ScrollingPane
{
typedef ScrollingPane super;
public:
ItemPane( IItemPaneCallback* screen,
Textures* textures,
const IntRectangle& rect,
int numItems,
int guiHeight,
int physicalScreenHeight,
bool isVertical = true);
~ItemPane();
void renderBatch( std::vector<GridItem>& item, float alpha );
bool onSelect( int gridId, bool selected );
void drawScrollBar( ScrollBar& hScroll );
//void setSize()
Font* f;
Textures* textures;
IItemPaneCallback* screen;
int physicalScreenHeight; // Needed for glScissor
bool isVertical;
NinePatchLayer* guiSlotItem;
NinePatchLayer* guiSlotItemSelected;
};
#endif /*ITEMPANE_H__*/

View File

@@ -0,0 +1,104 @@
#include "LargeImageButton.h"
#include "../../renderer/Tesselator.h"
#include "../../Minecraft.h"
#include "../../../util/Mth.h"
#include "../../../platform/log.h"
#include "../../../util/Mth.h"
#include "../../renderer/Textures.h"
LargeImageButton::LargeImageButton(int id, const std::string& msg)
: super(id, msg)
{
setupDefault();
}
LargeImageButton::LargeImageButton(int id, const std::string& msg, ImageDef& imagedef)
: super(id, msg)
{
_imageDef = imagedef;
setupDefault();
}
void LargeImageButton::setupDefault() {
_buttonScale = 1;
width = 72;
height = 72;
}
void LargeImageButton::render(Minecraft* minecraft, int xm, int ym) {
if (!visible) return;
Font* font = minecraft->font;
//minecraft->textures->loadAndBindTexture("gui/gui.png");
glColor4f2(1, 1, 1, 1);
bool hovered = active && (minecraft->useTouchscreen()? (_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height) : false);
//printf("ButtonId: %d - Hovered? %d (cause: %d, %d, %d, %d, <> %d, %d)\n", id, hovered, x, y, x+w, y+h, xm, ym);
//int yImage = getYImage(hovered || selected);
//blit(x, y, 0, 46 + yImage * 20, w / 2, h, 0, 20);
//blit(x + w / 2, y, 200 - w / 2, 46 + yImage * 20, w / 2, h, 0, 20);
renderBg(minecraft, xm, ym);
TextureId texId = (_imageDef.name.length() > 0)? minecraft->textures->loadAndBindTexture(_imageDef.name) : Textures::InvalidId;
if ( Textures::isTextureIdValid(texId) ) {
const ImageDef& d = _imageDef;
Tesselator& t = Tesselator::instance;
t.begin();
if (!active) t.color(0xff808080);
//else if (hovered||selected) t.color(0xffffffff);
//else t.color(0xffe0e0e0);
else t.color(0xffffffff);
float hx = ((float) d.width) * 0.5f;
float hy = ((float) d.height) * 0.5f;
const float cx = ((float)x+d.x) + hx;
const float cy = ((float)y+d.y) + hy;
if (hovered)
_buttonScale = Mth::Max(0.95f, _buttonScale-0.025f);
else
_buttonScale = Mth::Min(1.00f, _buttonScale+0.025f);
hx *= _buttonScale;
hy *= _buttonScale;
const IntRectangle* src = _imageDef.getSrc();
if (src) {
const TextureData* d = minecraft->textures->getTemporaryTextureData(texId);
if (d != NULL) {
float u0 = (src->x+(hovered?src->w:0)) / (float)d->w;
float u1 = (src->x+(hovered?2*src->w:src->w)) / (float)d->w;
float v0 = src->y / (float)d->h;
float v1 = (src->y+src->h) / (float)d->h;
t.vertexUV(cx-hx, cy-hy, blitOffset, u0, v0);
t.vertexUV(cx-hx, cy+hy, blitOffset, u0, v1);
t.vertexUV(cx+hx, cy+hy, blitOffset, u1, v1);
t.vertexUV(cx+hx, cy-hy, blitOffset, u1, v0);
}
} else {
t.vertexUV(cx-hx, cy-hy, blitOffset, 0, 0);
t.vertexUV(cx-hx, cy+hy, blitOffset, 0, 1);
t.vertexUV(cx+hx, cy+hy, blitOffset, 1, 1);
t.vertexUV(cx+hx, cy-hy, blitOffset, 1, 0);
}
t.draw();
}
//blit(0, 0, 0, 0, 64, 64, 256, 256);
//LOGI("%d %d\n", x+d.x, x+d.x+d.w);
if (!active) {
drawCenteredString(font, msg, x + width / 2, y + 11/*(h - 16)*/, 0xffa0a0a0);
} else {
if (hovered || selected) {
drawCenteredString(font, msg, x + width / 2, y + 11/*(h - 16)*/, 0xffffa0);
} else {
drawCenteredString(font, msg, x + width / 2, y + 11/*(h - 48)*/, 0xe0e0e0);
}
}
}

View File

@@ -0,0 +1,21 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__LargeImageButton_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__LargeImageButton_H__
#include "ImageButton.h"
class LargeImageButton: public ImageButton
{
typedef ImageButton super;
public:
LargeImageButton(int id, const std::string& msg);
LargeImageButton(int id, const std::string& msg, ImageDef& imageDef);
void render(Minecraft* minecraft, int xm, int ym);
private:
void setupDefault();
float _buttonScale;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__LargeImageButton_H__*/

View File

@@ -0,0 +1,141 @@
#include "NinePatch.h"
NinePatchDescription::NinePatchDescription( float x, float y, float x1, float x2, float x3, float y1, float y2, float y3, float w, float e, float n, float s ) : u0(x), u1(x + x1), u2(x + x2), u3(x + x3),
v0(y), v1(y + y1), v2(y + y2), v3(y + y3),
w(w), e(e), n(n), s(s),
imgW(-1),
imgH(-1) {
}
NinePatchDescription& NinePatchDescription::transformUVForImage( const TextureData& d ) {
return transformUVForImageSize(d.w, d.h);
}
NinePatchDescription& NinePatchDescription::transformUVForImageSize( int w, int h ) {
if (imgW < 0)
imgW = imgH = 1;
const float us = (float) imgW / w; // @todo: prepare for normal blit? (e.g. mult by 256)
const float vs = (float) imgH / h;
u0 *= us; u1 *= us; u2 *= us; u3 *= us;
v0 *= vs; v1 *= vs; v2 *= vs; v3 *= vs;
imgW = w;
imgH = h;
return *this;
}
NinePatchDescription NinePatchDescription::createSymmetrical( int texWidth, int texHeight, const IntRectangle& src, int xCutAt, int yCutAt ) {
NinePatchDescription patch((float)src.x, (float)src.y,// width and height of src
(float)xCutAt, (float)(src.w-xCutAt), (float)src.w, // u tex coordinates
(float)yCutAt, (float)(src.h-yCutAt), (float)src.h, // v tex coordinates
(float)xCutAt, (float)xCutAt, (float)yCutAt, (float)yCutAt); // border width and heights
if (texWidth > 0) patch.transformUVForImageSize(texWidth, texHeight);
return patch;
}
NinePatchLayer::NinePatchLayer(const NinePatchDescription& desc, const std::string& imageName, Textures* textures, float w, float h)
: desc(desc),
imageName(imageName),
textures(textures),
w(-1), h(-1),
excluded(0)
{
setSize(w, h);
}
void NinePatchLayer::setSize( float w, float h ) {
if (w == this->w && h == this->h)
return;
this->w = w;
this->h = h;
for (int i = 0; i < 9; ++i)
buildQuad(i);
}
void NinePatchLayer::draw( Tesselator& t, float x, float y ) {
textures->loadAndBindTexture(imageName);
t.begin();
t.addOffset(x, y, 0);
for (int i = 0, b = 1; i < 9; ++i, b += b)
if ((b & excluded) == 0)
d(t, quads[i]);
t.addOffset(-x, -y, 0);
t.draw();
}
NinePatchLayer* NinePatchLayer::exclude( int excludeId ) {
return setExcluded(excluded | (1 << excludeId));
}
NinePatchLayer* NinePatchLayer::setExcluded( int exludeBits ) {
excluded = exludeBits;
return this;
}
void NinePatchLayer::buildQuad( int qid ) {
//@attn; fix
CachedQuad& q = quads[qid];
const int yid = qid / 3;
const int xid = qid - 3 * yid;
q.u0 = (&desc.u0)[xid];
q.u1 = (&desc.u0)[xid + 1];
q.v0 = (&desc.v0)[yid];
q.v1 = (&desc.v0)[yid + 1];
q.z = 0;
getPatchInfo(xid, yid, q.x0, q.x1, q.y0, q.y1);
/* q.x0 = w * (q.u0 - desc.u0);
q.y0 = h * (q.v0 - desc.v0);
q.x1 = w * (q.u1 - desc.u0);
q.y1 = h * (q.v1 - desc.v0);
*/
}
void NinePatchLayer::getPatchInfo( int xc, int yc, float& x0, float& x1, float& y0, float& y1 ) {
if (xc == 0) { x0 = 0; x1 = desc.w; }
else if (xc == 1) { x0 = desc.w; x1 = w - desc.e; }
else if (xc == 2) { x0 = w-desc.e; x1 = w; }
if (yc == 0) { y0 = 0; y1 = desc.n; }
else if (yc == 1) { y0 = desc.n; y1 = h - desc.s; }
else if (yc == 2) { y0 = h-desc.s; y1 = h; }
}
void NinePatchLayer::d( Tesselator& t, const CachedQuad& q ) {
/*
t.vertexUV(x , y + h, blitOffset, (float)(sx ), (float)(sy + sh));
t.vertexUV(x + w, y + h, blitOffset, (float)(sx + sw), (float)(sy + sh));
t.vertexUV(x + w, y , blitOffset, (float)(sx + sw), (float)(sy ));
t.vertexUV(x , y , blitOffset, (float)(sx ), (float)(sy ));
*/
t.vertexUV(q.x0, q.y1, q.z, q.u0, q.v1);
t.vertexUV(q.x1, q.y1, q.z, q.u1, q.v1);
t.vertexUV(q.x1, q.y0, q.z, q.u1, q.v0);
t.vertexUV(q.x0, q.y0, q.z, q.u0, q.v0);
}
NinePatchFactory::NinePatchFactory( Textures* textures, const std::string& imageName ) : textures(textures),
imageName(imageName),
width(1),
height(1) {
TextureId id = textures->loadTexture(imageName);
if (id != Textures::InvalidId) {
const TextureData* data = textures->getTemporaryTextureData(id);
if (data) { // This should never be false
width = data->w;
height = data->h;
}
} else {
LOGE("Error @ NinePatchFactory::ctor - Couldn't find texture: %s\n", imageName.c_str());
}
}
NinePatchLayer* NinePatchFactory::createSymmetrical( const IntRectangle& src, int xCutAt, int yCutAt, float w /*= 32.0f*/, float h /*= 32.0f*/ ) {
return new NinePatchLayer(
NinePatchDescription::createSymmetrical(width, height, src, xCutAt, yCutAt),
imageName, textures, w, h);
}

View File

@@ -0,0 +1,78 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__NinePatch_H__
#define NET_MINECRAFT_CLIENT_GUI__NinePatch_H__
#include "ImageButton.h"
#include "../../renderer/TextureData.h"
#include "../../renderer/Textures.h"
#include "../../renderer/Tesselator.h"
#include "../../Minecraft.h"
class Tesselator;
class NinePatchDescription {
public:
NinePatchDescription& transformUVForImage(const TextureData& d);
NinePatchDescription& transformUVForImageSize(int w, int h);
float u0, u1, u2, u3;
float v0, v1, v2, v3;
float w, e, n, s;
static NinePatchDescription createSymmetrical(int texWidth, int texHeight, const IntRectangle& src, int xCutAt, int yCutAt);
private:
NinePatchDescription( float x, float y, float x1, float x2, float x3, float y1, float y2, float y3,
float w, float e, float n, float s);
int imgW;
int imgH;
};
class NinePatchLayer: public GuiElement
{
struct CachedQuad;
public:
NinePatchLayer(const NinePatchDescription& desc, const std::string& imageName, Textures* textures, float w = 32, float h = 32);
virtual ~NinePatchLayer() {};
void setSize(float w, float h);
void draw(Tesselator& t, float x, float y);
NinePatchLayer* exclude(int excludeId);
NinePatchLayer* setExcluded(int exludeBits);
float getWidth() { return w; }
float getHeight() { return h; }
private:
void buildQuad(int qid);
void getPatchInfo(int xc, int yc, float& x0, float& x1, float& y0, float& y1);
void d(Tesselator& t, const CachedQuad& q);
float w, h;
NinePatchDescription desc;
std::string imageName;
Textures* textures;
int excluded;
typedef struct CachedQuad {
float x0, x1, y0, y1, z;
float u0, u1, v0, v1;
} CachedQuad;
CachedQuad quads[9];
};
class NinePatchFactory {
public:
NinePatchFactory(Textures* textures, const std::string& imageName );
NinePatchLayer* createSymmetrical(const IntRectangle& src, int xCutAt, int yCutAt, float w = 32.0f, float h = 32.0f);
private:
Textures* textures;
std::string imageName;
int width;
int height;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__NinePatch_H__*/

View File

@@ -0,0 +1,68 @@
#include "OptionsGroup.h"
#include "../../Minecraft.h"
#include "ImageButton.h"
#include "OptionsItem.h"
#include "Slider.h"
#include "../../../locale/I18n.h"
OptionsGroup::OptionsGroup( std::string labelID ) {
label = I18n::get(labelID);
}
void OptionsGroup::setupPositions() {
// First we write the header and then we add the items
int curY = y + 10;
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->width = width - 5;
(*it)->y = curY;
(*it)->x = x + 10;
(*it)->setupPositions();
curY += (*it)->height + 3;
}
height = curY;
}
void OptionsGroup::render( Minecraft* minecraft, int xm, int ym ) {
minecraft->font->draw(label, (float)x + 2, (float)y, 0xffffffff, false);
super::render(minecraft, xm, ym);
}
OptionsGroup& OptionsGroup::addOptionItem( const Options::Option* option, Minecraft* minecraft ) {
if(option->isBoolean())
createToggle(option, minecraft);
else if(option->isProgress())
createProgressSlider(option, minecraft);
else if(option->isInt())
createStepSlider(option, minecraft);
return *this;
}
void OptionsGroup::createToggle( const Options::Option* option, Minecraft* minecraft ) {
ImageDef def;
def.setSrc(IntRectangle(160, 206, 39, 20));
def.name = "gui/touchgui.png";
def.width = 39 * 0.7f;
def.height = 20 * 0.7f;
OptionButton* element = new OptionButton(option);
element->setImageDef(def, true);
std::string itemLabel = I18n::get(option->getCaptionId());
OptionsItem* item = new OptionsItem(itemLabel, element);
addChild(item);
setupPositions();
}
void OptionsGroup::createProgressSlider( const Options::Option* option, Minecraft* minecraft ) {
Slider* element = new Slider(minecraft,
option,
minecraft->options.getProgrssMin(option),
minecraft->options.getProgrssMax(option));
element->width = 100;
element->height = 20;
OptionsItem* item = new OptionsItem(label, element);
addChild(item);
setupPositions();
}
void OptionsGroup::createStepSlider( const Options::Option* option, Minecraft* minecraft ) {
}

View File

@@ -0,0 +1,27 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__OptionsGroup_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__OptionsGroup_H__
//package net.minecraft.client.gui;
#include <string>
#include "GuiElementContainer.h"
#include "../../Options.h"
class Font;
class Minecraft;
class OptionsGroup: public GuiElementContainer {
typedef GuiElementContainer super;
public:
OptionsGroup(std::string labelID);
virtual void setupPositions();
virtual void render(Minecraft* minecraft, int xm, int ym);
virtual OptionsGroup& addOptionItem(const Options::Option* option, Minecraft* minecraft);
protected:
virtual void createToggle(const Options::Option* option, Minecraft* minecraft);
virtual void createProgressSlider(const Options::Option* option, Minecraft* minecraft);
virtual void createStepSlider(const Options::Option* option, Minecraft* minecraft);
std::string label;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__OptionsGroup_H__*/

View File

@@ -0,0 +1,24 @@
#include "OptionsItem.h"
#include "../../Minecraft.h"
#include "../../../util/Mth.h"
OptionsItem::OptionsItem( std::string label, GuiElement* element )
: GuiElementContainer(false, true, 0, 0, 24, 12),
label(label) {
addChild(element);
}
void OptionsItem::setupPositions() {
int currentHeight = 0;
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it) {
(*it)->x = x + width - (*it)->width - 15;
(*it)->y = y + currentHeight;
currentHeight += (*it)->height;
}
height = currentHeight;
}
void OptionsItem::render( Minecraft* minecraft, int xm, int ym ) {
int yOffset = (height - 8) / 2;
minecraft->font->draw(label, (float)x, (float)y + yOffset, 0x909090, false);
super::render(minecraft, xm, ym);
}

View File

@@ -0,0 +1,26 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__OptionsItem_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__OptionsItem_H__
#include <string>
#include <vector>
#include "GuiElementContainer.h"
#include "../../../world/item/ItemInstance.h"
#include "../../../client/Options.h"
class Font;
class Textures;
class NinePatchLayer;
class ItemPane;
class OptionsItem: public GuiElementContainer
{
typedef GuiElementContainer super;
public:
OptionsItem(std::string label, GuiElement* element);
virtual void render(Minecraft* minecraft, int xm, int ym);
void setupPositions();
private:
std::string label;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__OptionsItem_H__*/

View File

@@ -0,0 +1,64 @@
#include "OptionsPane.h"
#include "OptionsGroup.h"
#include "OptionsItem.h"
#include "ImageButton.h"
#include "Slider.h"
#include "../../Minecraft.h"
OptionsPane::OptionsPane() {
}
void OptionsPane::setupPositions() {
int currentHeight = y + 1;
for(std::vector<GuiElement*>::iterator it = children.begin(); it != children.end(); ++it ) {
(*it)->width = width;
(*it)->y = currentHeight;
(*it)->x = x;
currentHeight += (*it)->height + 1;
}
height = currentHeight;
super::setupPositions();
}
OptionsGroup& OptionsPane::createOptionsGroup( std::string label ) {
OptionsGroup* newGroup = new OptionsGroup(label);
children.push_back(newGroup);
// create and return a new group index
return *newGroup;
}
void OptionsPane::createToggle( unsigned int group, std::string label, const Options::Option* option ) {
// if(group > children.size()) return;
// ImageDef def;
// def.setSrc(IntRectangle(160, 206, 39, 20));
// def.name = "gui/touchgui.png";
// def.width = 39 * 0.7f;
// def.height = 20 * 0.7f;
// OptionButton* element = new OptionButton(option);
// element->setImageDef(def, true);
// OptionsItem* item = new OptionsItem(label, element);
// ((OptionsGroup*)children[group])->addChild(item);
// setupPositions();
}
void OptionsPane::createProgressSlider( Minecraft* minecraft, unsigned int group, std::string label, const Options::Option* option, float progressMin/*=1.0f*/, float progressMax/*=1.0f */ ) {
// if(group > children.size()) return;
// Slider* element = new Slider(minecraft, option, progressMin, progressMax);
// element->width = 100;
// element->height = 20;
// OptionsItem* item = new OptionsItem(label, element);
// ((OptionsGroup*)children[group])->addChild(item);
// setupPositions();
}
void OptionsPane::createStepSlider( Minecraft* minecraft, unsigned int group, std::string label, const Options::Option* option, const std::vector<int>& stepVec ) {
// if(group > children.size()) return;
// Slider* element = new Slider(minecraft, option, stepVec);
// element->width = 100;
// element->height = 20;
// sliders.push_back(element);
// OptionsItem* item = new OptionsItem(label, element);
// ((OptionsGroup*)children[group])->addChild(item);
// setupPositions();
}

View File

@@ -0,0 +1,30 @@
#ifndef ITEMPANE_H__
#define ITEMPANE_H__
#include <string>
#include <vector>
#include "GuiElementContainer.h"
#include "../../../world/item/ItemInstance.h"
#include "../../../client/Options.h"
class Font;
class Textures;
class NinePatchLayer;
class ItemPane;
class OptionButton;
class Button;
class OptionsGroup;
class Slider;
class Minecraft;
class OptionsPane: public GuiElementContainer
{
typedef GuiElementContainer super;
public:
OptionsPane();
OptionsGroup& createOptionsGroup( std::string label );
void createToggle( unsigned int group, std::string label, const Options::Option* option );
void createProgressSlider(Minecraft* minecraft, unsigned int group, std::string label, const Options::Option* option, float progressMin=1.0f, float progressMax=1.0f );
void createStepSlider(Minecraft* minecraft, unsigned int group, std::string label, const Options::Option* option, const std::vector<int>& stepVec );
void setupPositions();
};
#endif /*ITEMPANE_H__*/

View File

@@ -0,0 +1,299 @@
#include "RolledSelectionListH.h"
#include "../../Minecraft.h"
#include "../../renderer/Tesselator.h"
#include "../../renderer/gles.h"
#include "../../../platform/input/Mouse.h"
#include "../../../platform/input/Multitouch.h"
#include "../../../util/Mth.h"
#include "../../renderer/Textures.h"
RolledSelectionListH::RolledSelectionListH( Minecraft* minecraft, int width, int height, int x0, int x1, int y0, int y1, int itemWidth )
: minecraft(minecraft),
width(width),
height(height),
x0((float)x0),
x1((float)x1),
y0((float)y0),
y1((float)y1),
itemWidth(itemWidth),
selectionX(-1),
lastSelectionTime(0),
lastSelection(-1),
renderSelection(true),
doRenderHeader(false),
headerWidth(0),
dragState(DRAG_OUTSIDE),
xDrag(0.0f),
xo(0.0f),
xoo(0.0f),
xInertia(0.0f),
_componentSelected(false),
_renderTopBorder(true),
_renderBottomBorder(true),
_lastxoo(0),
_xinertia(0)
{
xo = xoo = (float)(itemWidth-width) * 0.5f;
_lastxoo = xoo;
}
void RolledSelectionListH::setRenderSelection( bool _renderSelection )
{
renderSelection = _renderSelection;
}
void RolledSelectionListH::setComponentSelected(bool selected) {
_componentSelected = selected;
}
void RolledSelectionListH::setRenderHeader( bool _renderHeader, int _headerHeight )
{
doRenderHeader = _renderHeader;
headerWidth = _headerHeight;
if (!doRenderHeader) {
headerWidth = 0;
}
}
int RolledSelectionListH::getMaxPosition()
{
return getNumberOfItems() * itemWidth + headerWidth;
}
int RolledSelectionListH::getItemAtPosition( int x, int y )
{
int clickSlotPos = (int)(x - x0 - headerWidth + (int) xo - 4);
int isInsideY = y >= y0 && y <= y1;
return isInsideY? getItemAtXPositionRaw(clickSlotPos) : -1;
}
int RolledSelectionListH::getItemAtXPositionRaw(int x) {
int slot = x / itemWidth;
bool isInsideX = slot >= 0 && x >= 0 && slot < getNumberOfItems();
return isInsideX? slot : -1;
}
bool RolledSelectionListH::capXPosition()
{
const float MinX = (float)(itemWidth-width)/2;
const float MaxX = MinX + (getNumberOfItems()-1) * itemWidth;
if (xo < MinX) { xo = MinX; xInertia = 0; return true; }
if (xo > MaxX) { xo = MaxX; xInertia = 0; return true; }
return false;
}
void RolledSelectionListH::tick() {
//if (Mouse::isButtonDown(MouseAction::ACTION_LEFT))
{
_xinertia = _lastxoo - xoo;
}
_lastxoo = xoo;
xoo = xo - xInertia;
}
float RolledSelectionListH::getPos(float alpha) {
return xoo - xInertia * alpha;
}
void RolledSelectionListH::render( int xm, int ym, float a )
{
renderBackground();
int itemCount = getNumberOfItems();
//float yy0 = height / 2.0f + 124;
//float yy1 = yy0 + 6;
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) {
touched();
//LOGI("DOWN ym: %d\n", ym);
if (ym >= y0 && ym <= y1) {
if (dragState == NO_DRAG) {
lastSelectionTime = getTimeMs();
lastSelection = getItemAtPosition(xm, height/2);
//float localX = (float)(xm*Gui::InvGuiScale - x0 - xo + lastSelection * itemWidth + headerWidth);
selectStart(lastSelection, 0, 0);//localX, ym-y0);
selectionX = xm;
}
else if (dragState >= 0) {
xo -= (xm - xDrag);
xoo = xo;
}
dragState = DRAG_NORMAL;
//const int* ids;
//LOGI("mtouch: %d\n", Multitouch::getActivePointerIds(&ids));
}
} else {
if (dragState >= 0) {
if (dragState >= 0) {
xInertia = _xinertia < 0? Mth::Max(-20.0f, _xinertia) : Mth::Min(20.0f, _xinertia);
}
//LOGI("Inertia: %f. Time: %d, delta-x: %d, (xm, sel: %d, %d)\n", xInertia, getTimeMs() - lastSelectionTime, std::abs(selectionX - xm), xm, selectionX);
// kill small inertia values when releasing scrollist
if (std::abs(xInertia) <= 2.0001f) {
xInertia = 0.0f;
}
if (std::abs(xInertia) <= 10 && getTimeMs() - lastSelectionTime < 300)
{
int slot = getItemAtPosition(xm, height/2);
//LOGI("slot: %d, lt: %d. diff: %d - %d\n", slot, lastSelection, selectionX, xm);
if (slot >= 0 && slot == lastSelection && std::abs(selectionX - xm) < 10)
selectItem(slot, false);
else
selectCancel();
} else {
selectCancel();
}
}
// if (slot >= 0 && std::abs(selectionX - xm) < itemWidth)
// {
// bool doubleClick = false;
// selectItem(slot, doubleClick);
// //xInertia = 0.0f;
// }
//}
dragState = NO_DRAG;
xo = getPos(a);
}
xDrag = (float)xm;
capXPosition();
Tesselator& t = Tesselator::instance;
float by0 = _renderTopBorder? y0 : 0;
float by1 = _renderBottomBorder? y1 : height;
//LOGI("x: %f\n", xo);
minecraft->textures->loadAndBindTexture("gui/background.png");
glColor4f2(1.0f, 1, 1, 1);
float s = 32;
t.begin();
t.color(0x202020);
t.vertexUV(x0, by1, 0, (x0 + (int) xo) / s, by1 / s);
t.vertexUV(x1, by1, 0, (x1 + (int) xo) / s, by1 / s);
t.vertexUV(x1, by0, 0, (x1 + (int) xo) / s, by0 / s);
t.vertexUV(x0, by0, 0, (x0 + (int) xo) / s, by0 / s);
t.draw();
const int HalfHeight = 48;
if (getNumberOfItems() == 0) xo = 0;
int rowY = (int)(height / 2 - HalfHeight + 8);
int rowBaseX = (int)(x0 /*+ 4*/ - (int) xo);
if (doRenderHeader) {
renderHeader(rowBaseX, rowY, t);
}
for (int i = 0; i < itemCount; i++) {
float x = (float)(rowBaseX + (i) * itemWidth + headerWidth);
float h = (float)itemWidth;
if (x > x1 || (x + h) < x0) {
continue;
}
if (renderSelection && isSelectedItem(i)) {
float y0 = height / 2.0f - HalfHeight - 4; //@kindle-res:+2
float y1 = height / 2.0f + HalfHeight - 4; //@kindle-res:-6
glColor4f2(1, 1, 1, 1);
glDisable2(GL_TEXTURE_2D);
int ew = 0;
int color = 0x808080;
if (_componentSelected) {
ew = 0;
color = 0x7F89BF;
}
t.begin();
t.color(color);
t.vertex(x - 1 - ew, y0 - ew, 0);
t.vertex(x - 1 - ew, y1 + ew, 0);
t.vertex(x + h + 1 + ew, y1 + ew, 0);
t.vertex(x + h + 1 + ew, y0 - ew, 0);
t.color(0x000000);
t.vertex(x, y0 + 1, 0);
t.vertex(x, y1 - 1, 0);
t.vertex(x + h, y1 - 1, 0);
t.vertex(x + h, y0 + 1, 0);
t.draw();
glEnable2(GL_TEXTURE_2D);
}
renderItem(i, (int)x, rowY, (int)h, t);
}
glDisable2(GL_DEPTH_TEST);
if (_renderTopBorder)
renderHoleBackground(0, y0, 255, 255);
if (_renderBottomBorder)
renderHoleBackground(y1, (float)height, 255, 255);
//glEnable2(GL_BLEND);
//glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glDisable2(GL_ALPHA_TEST);
//glShadeModel2(GL_SMOOTH);
//glDisable2(GL_TEXTURE_2D);
//const int d = 4;
//t.begin();
//t.color(0x000000, 0);
//t.vertexUV(y0, x0 + d, 0, 0, 1);
//t.vertexUV(y1, x0 + d, 0, 1, 1);
//t.color(0x000000, 255);
//t.vertexUV(y1, x0, 0, 1, 0);
//t.vertexUV(y0, x0, 0, 0, 0);
//t.draw();
//t.begin();
//t.color(0x000000, 255);
//t.vertexUV(y0, x1, 0, 0, 1);
//t.vertexUV(y1, x1, 0, 1, 1);
//t.color(0x000000, 0);
//t.vertexUV(y1, x1 - d, 0, 1, 0);
//t.vertexUV(y0, x1 - d, 0, 0, 0);
//t.draw();
//renderDecorations(xm, ym);
//glEnable2(GL_TEXTURE_2D);
glEnable2(GL_DEPTH_TEST);
//glShadeModel2(GL_FLAT);
//glEnable2(GL_ALPHA_TEST);
//glDisable2(GL_BLEND);
}
void RolledSelectionListH::renderHoleBackground( /*float x0, float x1,*/ float y0, float y1, int a0, int a1 )
{
Tesselator& t = Tesselator::instance;
minecraft->textures->loadAndBindTexture("gui/background.png");
glColor4f2(1.0f, 1, 1, 1);
float s = 32;
t.begin();
t.color(0x505050, a1);
t.vertexUV(0, y1, 0, 0, y1 / s);
t.vertexUV((float)width, y1, 0, width / s, y1 / s);
t.color(0x505050, a0);
t.vertexUV((float)width, y0, 0, width / s, y0 / s);
t.vertexUV(0, y0, 0, 0, y0 / s);
t.draw();
//printf("x, y, x1, y1: %d, %d, %d, %d\n", 0, (int)y0, width, (int)y1);
}
void RolledSelectionListH::touched()
{
}

View File

@@ -0,0 +1,82 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__RolledSelectionListH_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__RolledSelectionListH_H__
#include "../GuiComponent.h"
class Minecraft;
class Tesselator;
class RolledSelectionListH : public GuiComponent
{
static const int NO_DRAG = -1;
static const int DRAG_OUTSIDE = -2;
static const int DRAG_NORMAL = 0;
public:
RolledSelectionListH(Minecraft* minecraft, int width, int height, int x0, int x1, int y0, int y1, int itemWidth);
virtual int getItemAtPosition(int x, int y);
virtual bool capXPosition();
virtual void tick();
virtual void render(int xm, int ym, float a);
virtual void renderHoleBackground(/*float x0, float x1,*/ float y0, float y1, int a0, int a1);
virtual void setRenderSelection(bool _renderSelection);
virtual void setComponentSelected(bool selected);
protected:
void setRenderHeader(bool _renderHeader, int _headerHeight);
virtual int getNumberOfItems() = 0;
virtual void selectStart(int item, int localX, int localY) {}
virtual void selectCancel() {}
virtual void selectItem(int item, bool doubleClick) = 0;
virtual bool isSelectedItem(int item) = 0;
virtual int getMaxPosition();
virtual float getPos(float alpha);
virtual void touched();
virtual void renderItem(int i, int x, int y, int h, Tesselator& t) = 0;
virtual void renderHeader(int x, int y, Tesselator& t) {}
virtual void renderBackground() = 0;
virtual void renderDecorations(int mouseX, int mouseY) {}
virtual void clickedHeader(int headerMouseX, int headerMouseY) {}
int getItemAtXPositionRaw(int x);
protected:
Minecraft* minecraft;
float x0;
float x1;
int itemWidth;
int width;
int height;
//private:
float y0;
float y1;
int dragState;
float xDrag;
float xo;
float xoo;
float xInertia;
float _xinertia;
int selectionX;
bool renderSelection;
bool _componentSelected;
bool _renderTopBorder;
bool _renderBottomBorder;
private:
int headerWidth;
bool doRenderHeader;
long lastSelectionTime;
int lastSelection;
float _lastxoo;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__RolledSelectionListH_H__*/

View File

@@ -0,0 +1,352 @@
#include "RolledSelectionListV.h"
#include "../../Minecraft.h"
#include "../../renderer/Tesselator.h"
#include "../../renderer/gles.h"
#include "../../../platform/input/Mouse.h"
#include "../../../util/Mth.h"
#include "../../renderer/Textures.h"
RolledSelectionListV::RolledSelectionListV( Minecraft* minecraft_, int width_, int height_, int x0_, int x1_, int y0_, int y1_, int itemHeight_ )
: minecraft(minecraft_),
width(width_),
height(height_),
x0((float)x0_),
x1((float)x1_),
y0((float)y0_),
y1((float)y1_),
itemHeight(itemHeight_),
selectionY(-1),
lastSelectionTime(0),
lastSelection(-1),
renderSelection(true),
doRenderHeader(false),
headerHeight(0),
dragState(DRAG_OUTSIDE),
yDrag(0.0f),
yo(0.0f),
yoo(0.0f),
yInertia(0.0f),
_componentSelected(false),
_renderDirtBackground(true),
_renderTopBorder(true),
_renderBottomBorder(true),
_lastyoo(0),
_yinertia(0),
_stickPixels(0),
_lastxm(0),
_lastym(0)
{
yo = yoo = 0;//(float)(-itemHeight) * 0.5f;
_lastyoo = yoo;
}
void RolledSelectionListV::setRenderSelection( bool _renderSelection )
{
renderSelection = _renderSelection;
}
void RolledSelectionListV::setComponentSelected(bool selected) {
_componentSelected = selected;
}
void RolledSelectionListV::setRenderHeader( bool _renderHeader, int _headerHeight )
{
doRenderHeader = _renderHeader;
headerHeight = _headerHeight;
if (!doRenderHeader) {
headerHeight = 0;
}
}
int RolledSelectionListV::getMaxPosition()
{
return getNumberOfItems() * itemHeight + headerHeight;
}
int RolledSelectionListV::getItemAtPosition( int x, int y )
{
int clickSlotPos = (int)(y - y0 - headerHeight + (int) yo - 4);
int isInsideX = x >= x0 && x <= x1;
return isInsideX? getItemAtYPositionRaw(clickSlotPos) : -1;
}
int RolledSelectionListV::getItemAtYPositionRaw(int y) {
int slot = y / itemHeight;
bool isInsideX = slot >= 0 && y >= 0 && slot < getNumberOfItems();
return isInsideX? slot : -1;
}
bool RolledSelectionListV::capYPosition()
{
float max = getMaxPosition() - (y1 - y0 - 4);
if (max < 0) max /= 2;
if (yo < 0) yo = 0;
if (yo > max) yo = max;
return false;
/*
const float MinY = -itemHeight/2;//(float)(itemHeight-height)/2;
const float MaxY = MinY + (getNumberOfItems()-1) * itemHeight;
if (yo < MinY) { yo = MinY; yInertia = 0; return true; }
if (yo > MaxY) { yo = MaxY; yInertia = 0; return true; }
return false;
*/
}
void RolledSelectionListV::tick() {
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT))
{
_yinertia = _lastyoo - yoo;
}
_lastyoo = yoo;
//yInertia = Mth::absDecrease(yInertia, 1.0f, 0);
yoo = yo - yInertia;
//LOGI("tick: %f, %f, %f\n", yo, yInertia, _yinertia);
}
float RolledSelectionListV::getPos(float alpha) {
return yoo - yInertia * alpha;
}
void RolledSelectionListV::render( int xm, int ym, float a )
{
_lastxm = xm;
_lastym = ym;
renderBackground();
int itemCount = getNumberOfItems();
//float yy0 = height / 2.0f + 124;
//float yy1 = yy0 + 6;
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) {
touched();
//LOGI("DOWN ym: %d\n", ym);
if (ym >= y0 && ym <= y1) {
if (dragState == NO_DRAG) {
lastSelectionTime = getTimeMs();
lastSelection = convertSelection( getItemAtPosition(width/2, ym), xm, ym );
selectStart(lastSelection);
//LOGI("Sel : %d\n", lastSelection);
selectionY = ym;
_stickPixels = 10;
}
else if (dragState >= 0) {
float delta = (ym - yDrag);
float absDelta = Mth::abs(delta);
if (absDelta > _stickPixels) {
_stickPixels = 0;
delta -= delta>0? _stickPixels : -_stickPixels;
} else {
delta = 0;
_stickPixels -= absDelta;
}
yo -= delta;
yoo = yo;
}
dragState = DRAG_NORMAL;
}
} else {
if (dragState >= 0) {
if (dragState >= 0) {
yInertia = _yinertia < 0? Mth::Max(-10.0f, _yinertia) : Mth::Min(10.0f, _yinertia);
}
// kill small inertia values when releasing scrollist
if (std::abs(yInertia) <= 2.0001f) {
yInertia = 0.0f;
}
if (std::abs(yInertia) <= 10 /*&& getTimeMs() - lastSelectionTime < 300 */)
{
//float clickSlotPos = (ym - x0 - headerHeight + (int) yo - 4);
int slot = convertSelection( getItemAtPosition(width/2, ym), xm, ym);
//LOGI("slot: %d, lt: %d. diff: %d - %d\n", slot, lastSelection, selectionX, xm);
if (xm >= x0 && xm <= x1 && slot >= 0 && slot == lastSelection && std::abs(selectionY - ym) < 10)
selectItem(slot, false);
} else {
selectCancel();
}
}
// if (slot >= 0 && std::abs(selectionX - xm) < itemWidth)
// {
// bool doubleClick = false;
// selectItem(slot, doubleClick);
// //xInertia = 0.0f;
// }
//}
dragState = NO_DRAG;
yo = getPos(a);
}
yDrag = (float)ym;
evaluate(xm, ym);
capYPosition();
Tesselator& t = Tesselator::instance;
const int HalfWidth = 48;
int rowX = (int)(width / 2 - HalfWidth + 8);
int rowBaseY = (int)(y0 + 4 - (int) yo);
if (_renderDirtBackground)
renderDirtBackground();
if (getNumberOfItems() == 0) yo = 0;
//int rowY = (int)(height / 2 - HalfHeight + 8);
if (doRenderHeader) {
const int HalfWidth = 48;
int rowX = (int)(width / 2 - HalfWidth + 8);
int rowBaseY = (int)(y0 + 4 - (int) yo);
renderHeader(rowX, rowBaseY, t);
}
onPreRender();
for (int i = 0; i < itemCount; i++) {
float y = (float)(rowBaseY + (i) * itemHeight + headerHeight);
float h = itemHeight - 4.0f;
if (y > y1 || (y + h) < y0) {
continue;
}
if (renderSelection && isSelectedItem(i)) {
//float y0 = height / 2.0f - HalfHeight - 4;
//float y1 = height / 2.0f + HalfHeight - 4;
//glColor4f2(1, 1, 1, 1);
//glDisable2(GL_TEXTURE_2D);
//int ew = 0;
//int color = 0x808080;
//if (_componentSelected) {
// ew = 0;
// color = 0x7F89BF;
//}
//t.begin();
//t.color(color);
//t.vertex(x - 2 - ew, y0 - ew, 0);
//t.vertex(x - 2 - ew, y1 + ew, 0);
//t.vertex(x + h + 2 + ew, y1 + ew, 0);
//t.vertex(x + h + 2 + ew, y0 - ew, 0);
//t.color(0x000000);
//t.vertex(x - 1, y0 + 1, 0);
//t.vertex(x - 1, y1 - 1, 0);
//t.vertex(x + h + 1, y1 - 1, 0);
//t.vertex(x + h + 1, y0 + 1, 0);
//t.draw();
//glEnable2(GL_TEXTURE_2D);
}
renderItem(i, rowX, (int)y, (int)h, t);
}
onPostRender();
glDisable2(GL_DEPTH_TEST);
if (_renderTopBorder)
renderHoleBackground(0, y0, 255, 255);
if (_renderBottomBorder)
renderHoleBackground(y1, (float)height, 255, 255);
renderForeground();
//glEnable2(GL_BLEND);
//glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glDisable2(GL_ALPHA_TEST);
//glShadeModel2(GL_SMOOTH);
//glDisable2(GL_TEXTURE_2D);
//const int d = 4;
//t.begin();
//t.color(0x000000, 0);
//t.vertexUV(y0, x0 + d, 0, 0, 1);
//t.vertexUV(y1, x0 + d, 0, 1, 1);
//t.color(0x000000, 255);
//t.vertexUV(y1, x0, 0, 1, 0);
//t.vertexUV(y0, x0, 0, 0, 0);
//t.draw();
//t.begin();
//t.color(0x000000, 255);
//t.vertexUV(y0, x1, 0, 0, 1);
//t.vertexUV(y1, x1, 0, 1, 1);
//t.color(0x000000, 0);
//t.vertexUV(y1, x1 - d, 0, 1, 0);
//t.vertexUV(y0, x1 - d, 0, 0, 0);
//t.draw();
//renderDecorations(xm, ym);
//glEnable2(GL_TEXTURE_2D);
//glEnable2(GL_DEPTH_TEST);
//glShadeModel2(GL_FLAT);
//glEnable2(GL_ALPHA_TEST);
//glDisable2(GL_BLEND);
}
void RolledSelectionListV::renderHoleBackground( /*float x0, float x1,*/ float y0, float y1, int a0, int a1 )
{
Tesselator& t = Tesselator::instance;
minecraft->textures->loadAndBindTexture("gui/background.png");
glColor4f2(1.0f, 1, 1, 1);
float s = 32;
t.begin();
t.color(0x505050, a1);
t.vertexUV(0, y1, 0, 0, y1 / s);
t.vertexUV((float)width, y1, 0, width / s, y1 / s);
t.color(0x505050, a0);
t.vertexUV((float)width, y0, 0, width / s, y0 / s);
t.vertexUV(0, y0, 0, 0, y0 / s);
t.draw();
//printf("x, y, x1, y1: %d, %d, %d, %d\n", 0, (int)y0, width, (int)y1);
}
void RolledSelectionListV::touched()
{
}
void RolledSelectionListV::evaluate(int xm, int ym)
{
if (std::abs(selectionY - ym) >= 10) {
lastSelection = -1;
selectCancel();
}
}
void RolledSelectionListV::onPreRender()
{
}
void RolledSelectionListV::onPostRender()
{
}
void RolledSelectionListV::renderDirtBackground()
{
float by0 = _renderTopBorder? y0 : 0;
float by1 = _renderBottomBorder? y1 : height;
minecraft->textures->loadAndBindTexture("gui/background.png");
glColor4f2(1.0f, 1, 1, 1);
float s = 32;
const float uvy = (float)((int) yo);
Tesselator& t = Tesselator::instance;
t.begin();
t.color(0x202020);
t.vertexUV(x0, by1, 0, x0 / s, (by1+uvy) / s);
t.vertexUV(x1, by1, 0, x1 / s, (by1+uvy) / s);
t.vertexUV(x1, by0, 0, x1 / s, (by0+uvy) / s);
t.vertexUV(x0, by0, 0, x0 / s, (by0+uvy) / s);
t.draw();
//LOGI("%f, %f - %f, %f\n", x0, by0, x1, by1);
}

View File

@@ -0,0 +1,94 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__RolledSelectionListV_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__RolledSelectionListV_H__
#include "../GuiComponent.h"
class Minecraft;
class Tesselator;
class RolledSelectionListV : public GuiComponent
{
static const int NO_DRAG = -1;
static const int DRAG_OUTSIDE = -2;
static const int DRAG_NORMAL = 0;
public:
RolledSelectionListV(Minecraft* minecraft, int width, int height, int x0, int x1, int y0, int y1, int itemHeight);
virtual int getItemAtPosition(int x, int y);
virtual bool capYPosition();
virtual void tick();
virtual void render(int xm, int ym, float a);
virtual void renderHoleBackground(/*float x0, float x1,*/ float y0, float y1, int a0, int a1);
virtual void setRenderSelection(bool _renderSelection);
virtual void setComponentSelected(bool selected);
protected:
void setRenderHeader(bool _renderHeader, int _headerHeight);
virtual int getNumberOfItems() = 0;
virtual void selectStart(int item) {}
virtual void selectCancel() {}
virtual void selectItem(int item, bool doubleClick) = 0;
virtual bool isSelectedItem(int item) = 0;
virtual int getMaxPosition();
virtual float getPos(float alpha);
virtual void touched();
virtual void renderItem(int i, int x, int y, int h, Tesselator& t) = 0;
virtual void renderHeader(int x, int y, Tesselator& t) {}
virtual void renderBackground() = 0;
virtual void renderForeground() {}
virtual void renderDecorations(int mouseX, int mouseY) {}
virtual void clickedHeader(int headerMouseX, int headerMouseY) {}
virtual int convertSelection(int item, int xm, int ym) { return item; }
int getItemAtYPositionRaw(int y);
void evaluate(int xm, int ym);
virtual void onPreRender();
virtual void onPostRender();
void renderDirtBackground();
protected:
Minecraft* minecraft;
float x0;
float x1;
int itemHeight;
int width;
int height;
//private:
float y0;
float y1;
int dragState;
float yDrag;
float yo;
float yoo;
float yInertia;
float _yinertia;
int selectionY;
bool renderSelection;
bool _componentSelected;
bool _renderDirtBackground;
bool _renderTopBorder;
bool _renderBottomBorder;
int _lastxm;
int _lastym;
private:
int headerHeight;
bool doRenderHeader;
long lastSelectionTime;
int lastSelection;
float _lastyoo;
float _stickPixels;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__RolledSelectionListV_H__*/

View File

@@ -0,0 +1,296 @@
#include "ScrolledSelectionList.h"
#include "../../Minecraft.h"
#include "../../renderer/Tesselator.h"
#include "../../renderer/gles.h"
#include "../../../platform/input/Mouse.h"
#include "../../renderer/Textures.h"
static int Abs(int d) {
return d >= 0? d : -d;
}
ScrolledSelectionList::ScrolledSelectionList( Minecraft* _minecraft, int _width, int _height, int _y0, int _y1, int _itemHeight )
: minecraft(_minecraft),
width(_width),
height(_height),
y0((float)_y0),
y1((float)_y1),
itemHeight(_itemHeight),
x0(0.0f),
x1((float)_width),
selectionY(-1),
lastSelectionTime(0),
renderSelection(true),
doRenderHeader(false),
headerHeight(0),
dragState(DRAG_OUTSIDE),
yDrag(0.0f),
yo(0.0f),
yInertia(0.0f)
{
}
void ScrolledSelectionList::setRenderSelection( bool _renderSelection )
{
renderSelection = _renderSelection;
}
void ScrolledSelectionList::setRenderHeader( bool _renderHeader, int _headerHeight )
{
doRenderHeader = _renderHeader;
headerHeight = _headerHeight;
if (!doRenderHeader) {
headerHeight = 0;
}
}
int ScrolledSelectionList::getMaxPosition()
{
return getNumberOfItems() * itemHeight + headerHeight;
}
int ScrolledSelectionList::getItemAtPosition( int x, int y )
{
int x0 = width / 2 - (92 + 16 + 2);
int x1 = width / 2 + (92 + 16 + 2);
int clickSlotPos = (int)(y - y0 - headerHeight + (int) yo - 4);
int slot = clickSlotPos / itemHeight;
if (x >= x0 && x <= x1 && slot >= 0 && clickSlotPos >= 0 && slot < getNumberOfItems()) {
return slot;
}
return -1;
}
void ScrolledSelectionList::capYPosition()
{
float max = getMaxPosition() - (y1 - y0 - 4);
if (max < 0) max /= 2;
if (yo < 0) yo = 0;
if (yo > max) yo = max;
}
void ScrolledSelectionList::render( int xm, int ym, float a )
{
renderBackground();
int itemCount = getNumberOfItems();
//float xx0 = width / 2.0f + 124;
//float xx1 = xx0 + 6;
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT)) {
//LOGI("DOWN ym: %d\n", ym);
if (ym >= y0 && ym <= y1 && ym != ignoreY) {
if (dragState == NO_DRAG) {
dragState = DRAG_SKIP;
}
else if (dragState >= 0)
{
if (dragState == DRAG_SKIP)
{
lastSelectionTime = getTimeMs();
selectionY = ym;
}
else if (dragState == DRAG_NORMAL)
{
yo -= (ym - yDrag);
yInertia += (float)(ym - yDrag);
}
dragState = DRAG_NORMAL;
}
ignoreY = -1;
}
} else {
if (dragState != NO_DRAG)
{
//LOGI("UP ym: %d\n", ym);
}
//ignoreY = ym;
// kill small inertia values when releasing scrollist
if (dragState >= 0 && std::abs(yInertia) < 2)
{
yInertia = 0.0f;
}
if (dragState >= 0 && getTimeMs() - lastSelectionTime < 300)
{
float clickSlotPos = (ym - y0 - headerHeight + (int) yo - 4);
int slot = (int)clickSlotPos / itemHeight;
if (slot >= 0 && Abs(selectionY - ym) < itemHeight)
{
bool doubleClick = false;
selectItem(slot, doubleClick);
yInertia = 0.0f;
}
}
dragState = NO_DRAG;
yo -= yInertia;
}
yInertia = yInertia * .75f;
yDrag = (float)ym;
capYPosition();
Tesselator& t = Tesselator::instance;
renderDirtBackground();
int rowX = (int)(width / 2 - 92 - 16);
int rowBaseY = (int)(y0 + 4 - (int) yo);
if (doRenderHeader) {
renderHeader(rowX, rowBaseY, t);
}
for (int i = 0; i < itemCount; i++) {
float y = (float)(rowBaseY + (i) * itemHeight + headerHeight);
float h = itemHeight - 4.0f;
if (y > y1 || (y + h) < y0) {
continue;
}
if (renderSelection && isSelectedItem(i)) {
float x0 = width / 2.0f - (92 + 16 + 2);
float x1 = width / 2.0f + (92 + 16 + 2);
glColor4f2(1, 1, 1, 1);
glDisable2(GL_TEXTURE_2D);
t.begin();
t.color(0x808080);
t.vertexUV(x0, y + h + 2, 0, 0, 1);
t.vertexUV(x1, y + h + 2, 0, 1, 1);
t.vertexUV(x1, y - 2, 0, 1, 0);
t.vertexUV(x0, y - 2, 0, 0, 0);
t.color(0x000000);
t.vertexUV(x0 + 1, y + h + 1, 0, 0, 1);
t.vertexUV(x1 - 1, y + h + 1, 0, 1, 1);
t.vertexUV(x1 - 1, y - 1, 0, 1, 0);
t.vertexUV(x0 + 1, y - 1, 0, 0, 0);
t.draw();
glEnable2(GL_TEXTURE_2D);
}
renderItem(i, rowX, (int)y, (int)h, t);
}
glDisable2(GL_DEPTH_TEST);
int d = 4;
renderHoleBackground(0, y0, 255, 255);
renderHoleBackground(y1, (float)height, 255, 255);
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable2(GL_ALPHA_TEST);
glShadeModel2(GL_SMOOTH);
glDisable2(GL_TEXTURE_2D);
t.begin();
t.color(0x000000, 0);
t.vertexUV(x0, y0 + d, 0, 0, 1);
t.vertexUV(x1, y0 + d, 0, 1, 1);
t.color(0x000000, 255);
t.vertexUV(x1, y0, 0, 1, 0);
t.vertexUV(x0, y0, 0, 0, 0);
t.draw();
t.begin();
t.color(0x000000, 255);
t.vertexUV(x0, y1, 0, 0, 1);
t.vertexUV(x1, y1, 0, 1, 1);
t.color(0x000000, 0);
t.vertexUV(x1, y1 - d, 0, 1, 0);
t.vertexUV(x0, y1 - d, 0, 0, 0);
t.draw();
// {
// float max = getMaxPosition() - (y1 - y0 - 4);
// if (max > 0) {
// float barHeight = (y1 - y0) * (y1 - y0) / (getMaxPosition());
// if (barHeight < 32) barHeight = 32;
// if (barHeight > (y1 - y0 - 8)) barHeight = (y1 - y0 - 8);
//
// float yp = (int) yo * (y1 - y0 - barHeight) / max + y0;
// if (yp < y0) yp = y0;
//
// t.begin();
// t.color(0x000000, 255);
// t.vertexUV(xx0, y1, 0.0f, 0.0f, 1.0f);
// t.vertexUV(xx1, y1, 0.0f, 1.0f, 1.0f);
// t.vertexUV(xx1, y0, 0.0f, 1.0f, 0.0f);
// t.vertexUV(xx0, y0, 0.0f, 0.0f, 0.0f);
// t.draw();
//
// t.begin();
// t.color(0x808080, 255);
// t.vertexUV(xx0, yp + barHeight, 0, 0, 1);
// t.vertexUV(xx1, yp + barHeight, 0, 1, 1);
// t.vertexUV(xx1, yp, 0, 1, 0);
// t.vertexUV(xx0, yp, 0, 0, 0);
// t.draw();
//
// t.begin();
// t.color(0xc0c0c0, 255);
// t.vertexUV(xx0, yp + barHeight - 1, 0, 0, 1);
// t.vertexUV(xx1 - 1, yp + barHeight - 1, 0, 1, 1);
// t.vertexUV(xx1 - 1, yp, 0, 1, 0);
// t.vertexUV(xx0, yp, 0, 0, 0);
// t.draw();
// }
// }
renderDecorations(xm, ym);
glEnable2(GL_TEXTURE_2D);
glEnable2(GL_DEPTH_TEST);
glShadeModel2(GL_FLAT);
glEnable2(GL_ALPHA_TEST);
glDisable2(GL_BLEND);
}
void ScrolledSelectionList::renderHoleBackground( float y0, float y1, int a0, int a1 )
{
Tesselator& t = Tesselator::instance;
minecraft->textures->loadAndBindTexture("gui/background.png");
glColor4f2(1.0f, 1, 1, 1);
float s = 32;
t.begin();
t.color(0x505050, a1);
t.vertexUV(0, y1, 0, 0, y1 / s);
t.vertexUV((float)width, y1, 0, width / s, y1 / s);
t.color(0x505050, a0);
t.vertexUV((float)width, y0, 0, width / s, y0 / s);
t.vertexUV(0, y0, 0, 0, y0 / s);
t.draw();
}
void ScrolledSelectionList::renderDirtBackground()
{
Tesselator& t = Tesselator::instance;
minecraft->textures->loadAndBindTexture("gui/background.png");
glColor4f2(1.0f, 1, 1, 1);
float s = 32;
t.begin();
t.color(0x202020);
t.vertexUV(x0, y1, 0, x0 / s, (y1 + (int) yo) / s);
t.vertexUV(x1, y1, 0, x1 / s, (y1 + (int) yo) / s);
t.vertexUV(x1, y0, 0, x1 / s, (y0 + (int) yo) / s);
t.vertexUV(x0, y0, 0, x0 / s, (y0 + (int) yo) / s);
t.draw();
}

View File

@@ -0,0 +1,69 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ScrolledSelectionList_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ScrolledSelectionList_H__
#include "../GuiComponent.h"
class Minecraft;
class Tesselator;
class ScrolledSelectionList : public GuiComponent
{
static const int NO_DRAG = -1;
static const int DRAG_OUTSIDE = -2;
static const int DRAG_NORMAL = 0;
static const int DRAG_SKIP = 1; // special case to fix android jump bug
public:
ScrolledSelectionList(Minecraft* _minecraft, int _width, int _height, int _y0, int _y1, int _itemHeight);
virtual void setRenderSelection(bool _renderSelection);
protected:
void setRenderHeader(bool _renderHeader, int _headerHeight);
virtual int getNumberOfItems() = 0;
virtual void selectItem(int item, bool doubleClick) = 0;
virtual bool isSelectedItem(int item) = 0;
virtual int getMaxPosition();
virtual void renderItem(int i, int x, int y, int h, Tesselator& t) = 0;
virtual void renderHeader(int x, int y, Tesselator& t) {}
virtual void renderBackground() = 0;
virtual void renderDecorations(int mouseX, int mouseY) {}
virtual void clickedHeader(int headerMouseX, int headerMouseY) {}
public:
virtual int getItemAtPosition(int x, int y);
virtual void capYPosition();
virtual void render(int xm, int ym, float a);
virtual void renderHoleBackground(float y0, float y1, int a0, int a1);
void renderDirtBackground();
protected:
Minecraft* minecraft;
float y0;
float y1;
int itemHeight;
private:
int width;
int height;
float x1;
float x0;
int ignoreY; // new attempt to fix android jump bug
int dragState;
float yDrag;
float yo;
float yInertia;
int selectionY;
long lastSelectionTime;
bool renderSelection;
bool doRenderHeader;
int headerHeight;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ScrolledSelectionList_H__*/

View File

@@ -0,0 +1,732 @@
#include "ScrollingPane.h"
#include "../../renderer/gles.h"
#include "../Gui.h"
#include "../../../util/Mth.h"
#include "../../../SharedConstants.h"
#define STR(x) (x.toString().c_str())
static const float kPenetrationDeceleration = 0.03f;
static const float kPenetrationAcceleration = 0.08f;
static const float kMaxTrackingTime = 100.0f;
static const float kAcceleration = 15;
static const float kMinVelocityForDecelerationWithPaging = 4 / 3.0f;
static const float kMinVelocityForDeceleration = 1 / 3.0f;
static const float kDesiredAnimationFrameRate = 1000.0f / 60;
static const float kDecelerationFrictionFactor = 0.95f;
static const float kMinimumVelocityToHideScrollIndicators = 0.05f;
static const float kMinimumVelocity = 0.01f;
static const float kMinimumTrackingForDrag = 5;
static const float kMinIndicatorLength = 34.0f / 3;
static const float PKScrollIndicatorEndSize = 3;
static const float PKScrollIndicatorThickness = 7.0f /3;
ScrollingPane::ScrollingPane(
int optionFlags,
const IntRectangle& boundingBox,
const IntRectangle& itemRect,
int columns,
int numItems,
float screenScale /* = 1.0f */,
const IntRectangle& itemBoundingRect /*= IntRectangle(0,0,0,0)*/ )
: flags(optionFlags),
bbox(boundingBox),
size(boundingBox),
area((float)bbox.x, (float)bbox.y, (float)(bbox.x + bbox.w), (float)(bbox.y + bbox.h)),
bboxArea(area),
itemRect(itemRect),
numItems(numItems),
screenScale(screenScale),
invScreenScale(1.0f / screenScale),
//hasItemBounding(),
px(0), py(0), fpx(0), fpy(0),
dx(0), dy(0),
dragState(-1),
dragLastDeltaTimeStamp(-1.0f),
friction(0.95f),
highlightTimer(-1),
highlightStarted(-1),
selectedId(-1),
decelerating(false),
tracking(false),
dragging(false),
pagingEnabled(false),
_scrollEnabled(true),
_timer(60),
_doStepTimer(false),
_wasDown(false),//Mouse::isButtonDown(MouseAction::ACTION_LEFT)),
_lx(-9999), _ly(-9999)
{
if (itemBoundingRect.w > 0)
itemBbox = itemBoundingRect;
else
itemBbox = itemRect;
this->columns = (columns>0)? columns : bbox.w / itemBbox.w;
if (this->columns <= 0) {
LOGW("Columns are 0! Area width is smaller than item width. Setting columns to 1.\n");
this->columns = 1;
}
//LOGI("%d, %d :: %d\n", bbox.w, itemBbox.w, this->columns);
rows = 1 + (numItems-1) / this->columns,
/*
if (columns * itemBbox.w <= bbox.w) flags |= SF_LockX;
if (rows * itemBbox.h <= bbox.h) flags |= SF_LockY;
*/
dragDeltas.reserve(128);
te_moved = 0;
te_ended = 1;
selected = new bool[numItems];
for (int i = 0; i < numItems; ++i)
selected[i] = false;
// Setup the scroll bars
vScroll.w = vScroll.h = PKScrollIndicatorThickness;
hScroll.w = hScroll.h = PKScrollIndicatorThickness;
vScroll.x = bbox.x + bbox.w - vScroll.w;
vScroll.y = 0;
hScroll.x = 0;
hScroll.y = bbox.y + bbox.h - hScroll.h;
// vScroll.alpha
// vScroll.fading = hScroll.fading = -1;
}
ScrollingPane::~ScrollingPane() {
delete[] selected;
}
//void ScrollingPane::init(Minecraft* mc, int width, int height) {
// this->mc = mc;
// this->width = width;
// this->height = height;
//}
void ScrollingPane::tick() {
if (isSet(SF_ShowScrollbar)) {
updateScrollFade(vScroll);
updateScrollFade(hScroll);
}
}
bool ScrollingPane::getGridItemFor_slow(int itemIndex, GridItem& out) {
GridItem nw = getItemForPos(0, 0, false);
GridItem se = getItemForPos((float)bbox.w - 1, (float)bbox.h - 1, false);
const float bxx = bbox.x - (fpx /*+ dx*alpha*/) + (nw.xf - nw.x);
const float byy = bbox.y - (fpy /*+ dy*alpha*/) + (nw.yf - nw.y);
int y = itemIndex / columns;
int x = itemIndex - (y * columns);
out.id = itemIndex;
out.xf = bxx + x * itemBbox.w;
out.yf = byy + y * itemBbox.h;
out.x = x;
out.y = y;
return x >= nw.x && x <= se.x
&& y >= nw.y && y <= se.y;
}
void ScrollingPane::render( int xm, int ym, float alpha ) {
// Handle user interaction first
handleUserInput();
_timer.advanceTime();
if (_doStepTimer && !te_moved) {
for (int i = 0; i < _timer.ticks; ++i)
stepThroughDecelerationAnimation(false);
this->lastFrame = getTimeMs();
}
// Render
//if (isSet(SF_Scissor)) {
// glEnable2(GL_SCISSOR_TEST);
// GLuint x = (GLuint)(screenScale * bbox.x);
// GLuint y = 480 - (GLuint)(screenScale * (bbox.y + bbox.h));
// GLuint w = (GLuint)(screenScale * bbox.w);
// GLuint h = (GLuint)(screenScale * bbox.h);
// glScissor(x, y, w, h);
// LOGI("x, y, w, h: %d, %d, %d, %d\n", x, y, w, h);
//}
std::vector<GridItem> itemsToRender;
GridItem nw = getItemForPos(0, 0, false);
GridItem se = getItemForPos((float)bbox.w - 1, (float)bbox.h - 1, false);
//LOGI("getItem: %d, %d - %d, %d\n", nw.x, nw.y, se.x, se.y);
const float bxx = bbox.x - (fpx /*+ dx*alpha*/) + (nw.xf - nw.x);
const float byy = bbox.y - (fpy /*+ dy*alpha*/) + (nw.yf - nw.y);
for (int y = nw.y; y <= se.y; ++y)
for (int x = nw.x; x <= se.x; ++x) {
int id = y * columns + x;
if (y <0 || id < 0 || id >= numItems) continue; // @todo: break rather
if (isNotSet(SF_WrapX) && (x < 0 || x >= columns)) continue; // @todo: break rather
GridItem item; //@todo: v- Does not support SF_Wrapping
item.id = id;
item.xf = bxx + x * itemBbox.w;
item.yf = byy + y * itemBbox.h;
item.x = (int)item.xf;
item.y = (int)item.yf;
//LOGI("i: %d (%.1f, %.1f)\t", id, item.xf, item.yf);
if (isSet(SF_MultiSelect)) item.selected = selected[id];
else item.selected = (id == selectedId);
itemsToRender.push_back(item);
}
renderBatch(itemsToRender, alpha);
//if (isSet(SF_Scissor))
// glDisable2(GL_SCISSOR_TEST);
}
void ScrollingPane::renderBatch(std::vector<GridItem>& items, float alpha) {
for (unsigned int i = 0; i < items.size(); ++i)
renderItem(items[i], alpha);
}
void ScrollingPane::renderItem(GridItem& item, float alpha) {
}
ScrollingPane::GridItem ScrollingPane::getItemForPos( float x, float y, bool isScreenPos ) {
// Screen relative pos (rather than ScrollingPane relative pos)
if (isScreenPos) {
x -= bbox.x;
y -= bbox.y;
}
// Add the scrolled offset
x += fpx;
y += fpy;
// Does the grid SF_Wrap around?
if (isSet(SF_WrapX)) x = fmod(x, (float)(itemBbox.w * columns));
if (isSet(SF_WrapY)) y = fmod(y, (float)(itemBbox.h * rows));
GridItem out;
out.xf = x / itemBbox.w;
out.yf = y / itemBbox.h;
out.x = (int) out.xf;
out.y = (int) out.yf;
out.id = out.y * columns + out.x;
return out;
}
void ScrollingPane::addDeltaPos(float x, float y, float dt, int a) {
if (dt <= 0)
return;
Vec3 delta = (dragLastPos - Vec3(x, y, 0)) * (1.0f / dt);
dragDeltas.push_back(delta.x);
dragDeltas.push_back(delta.y);
dragLastPos.set(x, y, 0);
dragLastDeltaTimeStamp += dt; // @attn @fix: This relies on user to be correct
//LOGI(">> delta %d: %s\n", a, STR(delta));
}
static const int PKTableViewMinTouchDurationForCellSelection = 150;
void ScrollingPane::handleUserInput() {
bool isDown = Mouse::isButtonDown(MouseAction::ACTION_LEFT);
float x = Mouse::getX() * invScreenScale;
float y = Mouse::getY() * invScreenScale;
int t = getTimeMs();
bool isInside = area.isInside(x, y);
//LOGI("inside? %d\n", isInside);
bool moved = (x != _lx || y != _ly);
_lx = x;
_ly = y;
if (te_ended > 0 && _wasDown && !isDown)
touchesEnded(x, y, t);
else if (isDown && !_wasDown && isInside)
touchesBegan(x, y, t);
else if (te_moved > 0 && moved && isDown)
touchesMoved(x, y, t);
if (highlightTimer >= 0 && isNotSet(SF_NoHoldSelect)) {
if (getTimeMs() - highlightTimer >= PKTableViewMinTouchDurationForCellSelection)
onHoldItem();
}
_wasDown = isDown;
}
Vec3& ScrollingPane::contentOffset() {
return _contentOffset;
}
void ScrollingPane::beginTracking(float x, float y, int t) { //@param 1: MouseEvent a
if (this->tracking) {
return;
}
//a.preventDefault();
this->stopDecelerationAnimation();
//this->hostingLayer.style.webkitTransitionDuration = 0;
this->adjustContentSize(); //@todo @?
this->minPoint.set((float)(this->size.w - this->adjustedContentSize.w), (float)(this->size.h - this->adjustedContentSize.h), 0); //@todo
this->snapContentOffsetToBounds(false);
this->startPosition = this->_contentOffset;
this->startTouchPosition.set(x, y, 0);
this->startTime = (float)t;
this->startTimePosition = this->contentOffset();
this->tracking = true;
this->dragging = false;
this->touchesHaveMoved = false;
//window.addEventListener(PKMoveEvent, this, true); //@todo
//window.addEventListener(PKEndEvent, this, true);
//window.addEventListener("touchcancel", this, true);
//window.addEventListener(PKEndEvent, this, false)
};
void ScrollingPane::touchesBegan(float x, float y, int t) { //@param 1: MouseEvent a
if (!this->_scrollEnabled) {
return;
}
te_ended = 1;
//if (a.eventPhase == Event.CAPTURING_PHASE) {
// if (a._manufactured) {
// return
// }
//this->highlightItem = getItemForPos(x, y, true);
// if (this.delaysContentTouches) {
// a.stopPropagation();
// this.callMethodNameAfterDelay("beginTouchesInContent", kContentTouchesDelay, a);
this->beginTracking(x, y, t);
// }
//} else {
// this.beginTracking(a)
//}
te_moved = 2;
GridItem gi = getItemForPos(x, y, true);
if (gi.id >= 0 && gi.id < numItems) {
//LOGI("Pressed down at %d (%d, %d)\n", gi.id, gi.x, gi.y);
highlightItem.id = bboxArea.isInside(x, y)? gi.id : -1;
highlightStarted = highlightTimer = bboxArea.isInside(x, y)? getTimeMs() : -1;
} else {
highlightItem.id = -1;
highlightStarted = highlightTimer = -1;
}
}
void ScrollingPane::touchesMoved(float x, float y, int t)
{
this->touchesHaveMoved = true;
//this->callSuper(d);
Vec3 e(x, y, 0);
float b = e.x - this->startTouchPosition.x;
float c = e.y - this->startTouchPosition.y;
if (!this->dragging) {
if ((Mth::abs(b) >= kMinimumTrackingForDrag && isNotSet(SF_LockX)) || (Mth::abs(c) >= kMinimumTrackingForDrag && isNotSet(SF_LockY))) {
willBeginDragging();
this->dragging = true;
this->firstDrag = true;
if (isSet(SF_ShowScrollbar)) {
if (isNotSet(SF_LockX) && (this->adjustedContentSize.w > this->size.w))
//this->hScroll.visible = true;
this->hScroll.fading = 1;
if (isNotSet(SF_LockY) && (this->adjustedContentSize.h > this->size.h))
//this->vScroll.visible = true;
this->vScroll.fading = 1;
}
}
}
if (this->dragging) {
//d.stopPropagation();
float f = isNotSet(SF_LockX) ? (this->startPosition.x + b) : this->_contentOffset.x;
float a = isNotSet(SF_LockY) ? (this->startPosition.y + c) : this->_contentOffset.y;
if (isNotSet(SF_HardLimits)) {
f -= ((f < this->minPoint.x) ? (f - this->minPoint.x) : ((f > 0) ? f : 0)) / 2;
a -= ((a < this->minPoint.y) ? (a - this->minPoint.y) : ((a > 0) ? a : 0)) / 2;
} else {
f = Mth::Min(Mth::Max(this->minPoint.x, f), 0.0f);
a = Mth::Min(Mth::Max(this->minPoint.y, a), 0.0f);
}
if (this->firstDrag) {
this->firstDrag = false;
this->startTouchPosition = e;
return;
}
this->setContentOffset(f, a);
this->lastEventTime = t;//d.timeStamp;
}
}
void ScrollingPane::touchesEnded(float x, float y, int t) {
te_ended = 0;
highlightStarted = -1;
//te_moved = 0;
//this.callSuper(a);
this->tracking = false;
if (this->dragging) {
this->dragging = false;
//a.stopPropagation();
if (t - this->lastEventTime <= kMaxTrackingTime) {
this->_contentOffsetBeforeDeceleration = this->_contentOffset;
this->startDecelerationAnimation(false);
}
if (!this->decelerating) {}
//window.removeEventListener(PKEndEvent, this, false);
didEndDragging();
}
if (!this->decelerating) {
if (fpy < 0 || fpy > bbox.h) { //@todo: for x as well (or rather, x^y)
this->_contentOffsetBeforeDeceleration = this->_contentOffset;
this->startDecelerationAnimation(true);
} else {
this->snapContentOffsetToBounds(true); //@fix
this->hideScrollIndicators();
}
}
//if (a.eventPhase == Event.BUBBLING_PHASE) { //@? @todo
// window.removeEventListener(PKEndEvent, this, false);
//// old and shaky, doesn't work good with Xperia Play (and presumably lots of others)
//if (!this->touchesHaveMoved && this->highlightItem.id >= 0) {
// _onSelect(this->highlightItem.id);
//}
if (Vec3(x, y, 0).distanceToSqr(startTouchPosition) <= 6.0f * 6.0f && this->highlightItem.id >= 0) {
_onSelect(this->highlightItem.id);
}
//}
te_moved = 0;
};
void ScrollingPane::touchesCancelled(float x, float y, int a) {
touchesEnded(x, y, a);
}
void ScrollingPane::startDecelerationAnimation( bool force )
{
Vec3 a(this->_contentOffset.x - this->startTimePosition.x, this->_contentOffset.y - this->startTimePosition.y, 0);
float b = (getTimeMs()/*event.timeStamp*/ - this->startTime) / kAcceleration;
//LOGI("starting deceleration! %s, %f\n", STR(a), b);
this->decelerationVelocity = Vec3(a.x / b, a.y / b, 0);
this->minDecelerationPoint = this->minPoint;
this->maxDecelerationPoint = Vec3(0, 0, 0);
if (this->pagingEnabled) {
this->minDecelerationPoint.x = Mth::Max(this->minPoint.x, std::floor(this->_contentOffsetBeforeDeceleration.x / this->size.w) * this->size.w);
this->minDecelerationPoint.y = Mth::Max(this->minPoint.y, std::floor(this->_contentOffsetBeforeDeceleration.y / this->size.h) * this->size.h);
this->maxDecelerationPoint.x = Mth::Min(0.0f, std::ceil(this->_contentOffsetBeforeDeceleration.x / this->size.w) * this->size.w);
this->maxDecelerationPoint.y = Mth::Min(0.0f, std::ceil(this->_contentOffsetBeforeDeceleration.y / this->size.h) * this->size.h);
}
this->penetrationDeceleration = kPenetrationDeceleration;
this->penetrationAcceleration = kPenetrationAcceleration;
if (this->pagingEnabled) {
this->penetrationDeceleration *= 5;
}
float c = this->pagingEnabled ? kMinVelocityForDecelerationWithPaging : kMinVelocityForDeceleration;
if (force || (Mth::abs(this->decelerationVelocity.x) > c || Mth::abs(this->decelerationVelocity.y) > c)) {
this->decelerating = true;
//LOGI("accelerating True - A\n");
_doStepTimer = true;
//this->decelerationTimer = this->callMethodNameAfterDelay("stepThroughDecelerationAnimation", kDesiredAnimationFrameRate); //@?
this->lastFrame = getTimeMs();
willBeginDecelerating();
}
}
void ScrollingPane::hideScrollIndicators() {
//hScroll.visible = vScroll.visible = false;
hScroll.fading = vScroll.fading = 0;
}
void ScrollingPane::stopDecelerationAnimation()
{
//LOGI("decelerating False - A\n");
this->decelerating = false;
_doStepTimer = false;
//clearTimeout(this.decelerationTimer) //@?
}
void ScrollingPane::stepThroughDecelerationAnimation(bool noAnimation) {
if (!this->decelerating) {
return;
}
int d = getTimeMs();
int k = d - this->lastFrame;
int l = noAnimation ? 0 : (int)(std::floor(0.5f + ((float)k / kDesiredAnimationFrameRate) - 1));
//LOGI("k: %d, %d %d : %d\n", d, this->lastFrame, k, l);
for (int j = 0; j < l; j++)
this->stepThroughDecelerationAnimation(true);
float g = this->contentOffset().x + this->decelerationVelocity.x;
float h = this->contentOffset().y + this->decelerationVelocity.y;
if (isSet(SF_HardLimits)) {
float a = Mth::Min(Mth::Max(this->minPoint.x, g), 0.0f);
if (a != g) {
g = a;
this->decelerationVelocity.x = 0;
}
float c = Mth::Min(Mth::Max(this->minPoint.y, h), 0.0f);
if (c != h) {
h = c;
this->decelerationVelocity.y = 0;
}
}
if (noAnimation) {
this->contentOffset().x = g;
this->contentOffset().y = h;
} else {
this->setContentOffset(g, h);
}
if (!this->pagingEnabled) {
this->decelerationVelocity.x *= kDecelerationFrictionFactor;
this->decelerationVelocity.y *= kDecelerationFrictionFactor;
}
float b = Mth::abs(this->decelerationVelocity.x);
float i = Mth::abs(this->decelerationVelocity.y);
if (!noAnimation && b <= kMinimumVelocityToHideScrollIndicators && i <= kMinimumVelocityToHideScrollIndicators) {
this->hideScrollIndicators();
if (b <= kMinimumVelocity && i <= kMinimumVelocity) {
//LOGI("decelerating False - B\n");
this->decelerating = false;
didEndDecelerating();
return;
}
}
if (!noAnimation) {
//this->decelerationTimer = this->callMethodNameAfterDelay("stepThroughDecelerationAnimation", kDesiredAnimationFrameRate)
}
//if (noAnimation) doStepTimer = false;
if (isNotSet(SF_HardLimits)) {
Vec3 e;
if (g < this->minDecelerationPoint.x) {
e.x = this->minDecelerationPoint.x - g;
} else {
if (g > this->maxDecelerationPoint.x) {
e.x = this->maxDecelerationPoint.x - g;
}
}
if (h < this->minDecelerationPoint.y) {
e.y = this->minDecelerationPoint.y - h;
} else {
if (h > this->maxDecelerationPoint.y) {
e.y = this->maxDecelerationPoint.y - h;
}
}
if (e.x != 0) {
if (e.x * this->decelerationVelocity.x <= 0) {
this->decelerationVelocity.x += e.x * this->penetrationDeceleration;
} else {
this->decelerationVelocity.x = e.x * this->penetrationAcceleration;
}
}
if (e.y != 0) {
if (e.y * this->decelerationVelocity.y <= 0) {
this->decelerationVelocity.y += e.y * this->penetrationDeceleration;
} else {
this->decelerationVelocity.y = e.y * this->penetrationAcceleration;
}
}
}
if (!noAnimation) {
this->lastFrame = d;
}
}
void ScrollingPane::setContentOffset(float x, float y) {
this->setContentOffsetWithAnimation(Vec3(x, y, 0), false);
}
void ScrollingPane::setContentOffset(Vec3 a) {
this->setContentOffsetWithAnimation(a, false);
};
void ScrollingPane::setContentOffsetWithAnimation(Vec3 b, bool doScroll) {
this->_contentOffset = b;
fpx = -this->_contentOffset.x;
fpy = -this->_contentOffset.y;
/* //@todo //@?
this->hostingLayer.style.webkitTransform = PKUtils.t(this->_contentOffset.x, this->_contentOffset.y);
if (a) {
this->scrollTransitionsNeedRemoval = true;
this->hostingLayer.style.webkitTransitionDuration = kPagingTransitionDuration
} else {
this->didScroll(false)
}
*/
if (!doScroll) {
// @todo: for scroll indicator //@?
if (isSet(SF_ShowScrollbar)) {
if (isNotSet(SF_LockX)) this->updateHorizontalScrollIndicator();
if (isNotSet(SF_LockY)) this->updateVerticalScrollIndicator();
}
}
//this->notifyPropertyChange("contentOffset")
}
void ScrollingPane::snapContentOffsetToBounds(bool a) {
bool b = false;
Vec3 c;
if (this->pagingEnabled) {
c.x = std::floor(0.5f + this->_contentOffset.x / this->size.w) * this->size.w;
c.y = std::floor(0.5f + this->_contentOffset.y / this->size.h) * this->size.h;
b = true;
} else {
if (isNotSet(SF_HardLimits)) {
c.x = Mth::Min(Mth::Max(this->minPoint.x, this->_contentOffset.x), 0.0f);
c.y = Mth::Min(Mth::Max(this->minPoint.y, this->_contentOffset.y), 0.0f);
b = (c.x != this->_contentOffset.x || c.y != this->_contentOffset.y);
}
}
if (b) {
this->setContentOffsetWithAnimation(c, a);
}
}
void ScrollingPane::adjustContentSize()
{
this->adjustedContentSize.w = Mth::Max(itemBbox.w * columns, bbox.w);
this->adjustedContentSize.h = Mth::Max(itemBbox.h * rows, bbox.h);
}
void ScrollingPane::onHoldItem() {
//LOGI("dragging, tracking %d, %d\n", !this->dragging, this->tracking);
int id = highlightItem.id;
if (id != -1 && !this->dragging && this->tracking)
_onSelect(id);
highlightTimer = -1;
//highlightItem.id = -1;
}
bool ScrollingPane::onSelect( int gridId, bool selected )
{
return selected;
}
void ScrollingPane::updateHorizontalScrollIndicator()
{
float c = (isNotSet(SF_LockX) && isSet(SF_ShowScrollbar)) ? PKScrollIndicatorEndSize * 2 : 1;
float d = Mth::Max(kMinIndicatorLength, std::floor(0.5f + (this->size.w / this->adjustedContentSize.w) * (this->size.w - c)));
float a = (-this->_contentOffset.x / (this->adjustedContentSize.w - this->size.w)) * (this->size.w - c - d);
//float b = this->size.h - PKScrollIndicatorThickness - 1;
if (this->_contentOffset.x > 0) {
d = std::floor(0.5f + Mth::Max(d - this->_contentOffset.x, PKScrollIndicatorThickness));
a = 1;
} else {
if (this->_contentOffset.x < -(this->adjustedContentSize.w - this->size.w)) {
d = std::floor(0.5f + Mth::Max(d + this->adjustedContentSize.w - this->size.w + this->contentOffset().x, PKScrollIndicatorThickness));
a = this->size.w - d - c;
}
}
this->hScroll.x = a + bbox.x;
//this->hScroll.y = b;
this->hScroll.w = d; //@property
};
void ScrollingPane::updateVerticalScrollIndicator()
{
float c = (isNotSet(SF_LockY) && isSet(SF_ShowScrollbar)) ? PKScrollIndicatorEndSize * 2 : 1;
float d = Mth::Max(kMinIndicatorLength, std::floor(0.5f + (this->size.h / this->adjustedContentSize.h) * (this->size.h - c)));
//float a = this->size.w - PKScrollIndicatorThickness - 1;
float b = (-this->_contentOffset.y / (this->adjustedContentSize.h - this->size.h)) * (this->size.h - c - d);
if (this->_contentOffset.y > 0) {
d = std::floor(0.5f + Mth::Max(d - this->_contentOffset.y, PKScrollIndicatorThickness));
b = 1;
} else {
if (this->_contentOffset.y < -(this->adjustedContentSize.h - this->size.h)) {
d = std::floor(0.5f + Mth::Max(d + this->adjustedContentSize.h - this->size.h + this->contentOffset().y, PKScrollIndicatorThickness));
b = this->size.h - d - c;
}
}
//this->vScroll.x = a;
this->vScroll.y = b + bbox.y;
this->vScroll.h = d; //@property
};
void ScrollingPane::_onSelect( int id )
{
if (isSet(SF_MultiSelect)) {
selected[id] = onSelect(id, !selected[id]);
} else {
// Change the selection, if the user wants it
// @note: There's currently no way to clear a selection
bool doSelect = onSelect(id, true);
if (id != selectedId && doSelect) {
onSelect(selectedId, false);
selectedId = id;
}
}
}
void ScrollingPane::updateScrollFade( ScrollBar& sb ) {
if (sb.fading == 1 && ((sb.alpha += 0.33f) >= 1)) {
sb.alpha = 1;
sb.fading = -1;
}
if (sb.fading == 0 && ((sb.alpha -= 0.10f) <= 0)) {
sb.alpha = 0;
sb.fading = -1;
}
}
void ScrollingPane::setSelected( int id, bool selected )
{
if (isSet(SF_MultiSelect))
this->selected[id] = selected;
else {
if (selected) selectedId = selected? id : -1;
else if (id == selectedId)
selectedId = -1;
}
}
void ScrollingPane::translate( float xo, float yo )
{
bbox.x += (int)xo;
bbox.y += (int)yo;
area._x0 += xo;
area._x1 += xo;
area._y0 += yo;
area._y1 += yo;
bboxArea._x0 += xo;
bboxArea._x1 += xo;
bboxArea._y0 += yo;
bboxArea._y1 += yo;
hScroll.x += xo;
hScroll.y += yo;
vScroll.x += xo;
vScroll.y += yo;
}
bool ScrollingPane::queryHoldTime(int* gridItem, int* heldMs) {
*gridItem = -1;
*heldMs = -1;
if (!dragging && highlightStarted >= 0) {
GridItem item = getItemForPos(_lx, _ly, true);
if (item.id == highlightItem.id) {
*gridItem = highlightItem.id;
*heldMs = getTimeMs() - highlightStarted;
return true;
} else {
highlightStarted = -1;
}
}
return false;
}

View File

@@ -0,0 +1,199 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ScrollingPane_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ScrollingPane_H__
#include "../GuiComponent.h"
#include "ImageButton.h"
#include "../../player/input/touchscreen/TouchAreaModel.h"
#include "../../../world/phys/Vec3.h"
#include "../../Timer.h"
enum ScrollingPaneFlags {
SF_LockX = 1 << 0,
SF_LockY = 1 << 1,
SF_WrapX = 1 << 2,
SF_WrapY = 1 << 3,
SF_HardLimits = 1 << 4,
SF_MultiSelect = 1 << 5,
//SF_Snap = 1 << 6,
//SF_CustomSnap = 1 << 7,
//SF_Scissor = 1 << 8,
SF_ShowScrollbar= 1 << 9,
SF_NoHoldSelect = 1 << 10
};
typedef struct ScrollBar {
ScrollBar()
: alpha(0),
fading(-1)
{}
float x;
float y;
float w;
float h;
//bool visible;
float alpha;
int fading;
} ScrollBar;
class ScrollingPane: public GuiComponent {
public:
typedef struct GridItem {
int id;
int x, y;
// The GUI coordinates comes in (xf, yf)
float xf, yf;
bool selected;
} GridItem;
ScrollingPane(int flags, const IntRectangle& boundingBox, const IntRectangle& itemRect, int columns, int numItems, float screenScale = 1.0f, const IntRectangle& itemBoundingRect = IntRectangle(0,0,0,0));
~ScrollingPane();
//void init(Minecraft*, int width, int height);
void tick();
void render(int xm, int ym, float alpha);
bool getGridItemFor_slow(int itemIndex, GridItem& out);
void setSelected(int id, bool selected);
// This function is called with all visible GridItems. The base
// implementation just dispatches each item to renderItem in y,x order
virtual void renderBatch(std::vector<GridItem>& items, float alpha);
virtual void renderItem(GridItem& item, float alpha);
//void render(int xx, int yy);
bool queryHoldTime(int* gridId, int* heldMs);
protected:
GridItem getItemForPos(float x, float y, bool isScreenPos);
void handleUserInput();
void addDeltaPos(float x, float y, float dt, int z);
void translate(float xo, float yo);
int flags;
int columns;
int rows;
int numItems;
int px, py;
float fpx, fpy;
float screenScale;
float invScreenScale;
//bool hasItemBounding;
IntRectangle bbox;
IntRectangle itemRect;
IntRectangle itemBbox;
RectangleArea area;
RectangleArea bboxArea;
// Dragging info
std::vector<float> dragDeltas;
int dragState;
Vec3 dragBeginPos;
Vec3 dragBeginScreenPos;
int dragTicks;
float dragLastDeltaTimeStamp;
Vec3 dragLastPos;
float dx, dy;
float friction;
float dstx, dsty;
// Rewrite
bool dragging; //!
bool decelerating;
bool tracking; //!
bool pagingEnabled; //!
Vec3 _contentOffset; //!
Vec3 _contentOffsetBeforeDeceleration; //*
int lastEventTime; //<
Vec3 decelerationVelocity; //*
Vec3 minDecelerationPoint; //*
Vec3 maxDecelerationPoint; //*
float penetrationDeceleration; //<
float penetrationAcceleration; //<
Vec3 minPoint; //*
Vec3 startPosition; //*
Vec3 startTouchPosition; //*
Vec3 startTimePosition; //*
bool wasDeceleratingWhenTouchesBegan; //*
bool firstDrag; //<
float startTime; //<
//float startTime
IntRectangle size;
int lastFrame;
bool _scrollEnabled; //!
bool touchesHaveMoved; //*
virtual void didEndDragging() {}
virtual void didEndDecelerating() {}
virtual void willBeginDecelerating() {}
virtual void willBeginDragging() {}
int te_moved,
te_ended,
te_highlight;
int highlightTimer;
int highlightStarted;
GridItem highlightItem;
bool* selected;
int selectedId;
ScrollBar vScroll, hScroll;
IntRectangle adjustedContentSize;
void touchesBegan(float x, float y, int t);
void touchesMoved(float x, float y, int t);
void touchesEnded(float x, float y, int t);
void touchesCancelled(float x, float y, int t);
void beginTracking(float x, float y, int t);
void onHoldItem();
void _onSelect( int id );
virtual bool onSelect(int gridId, bool selected);
Vec3& contentOffset();
void startDecelerationAnimation(bool force);
void stopDecelerationAnimation();
void stepThroughDecelerationAnimation(bool f);
void setContentOffset(float x, float y);
void setContentOffset(Vec3 a);
void setContentOffsetWithAnimation(Vec3 b, bool doScroll);
void snapContentOffsetToBounds(bool snap); //*
void adjustContentSize();
//TouchAreaModel _areaModel;
bool isAllSet(int flag) { return (flags & flag) == flag; }
bool isSet(int flag) { return (flags & flag) != 0; }
bool isNotSet(int flag) { return !isSet(flag); }
void updateHorizontalScrollIndicator();
void updateVerticalScrollIndicator();
void hideScrollIndicators(); //*
void updateScrollFade( ScrollBar& vScroll );
private:
Timer _timer;
bool _doStepTimer;
bool _wasDown;
float _lx;
float _ly;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__ScrollingPane_H__*/

View File

@@ -0,0 +1,100 @@
#include "Slider.h"
#include "../../Minecraft.h"
#include "../../renderer/Textures.h"
#include "../Screen.h"
#include "../../../util/Mth.h"
#include <algorithm>
#include <assert.h>
Slider::Slider(Minecraft* minecraft, const Options::Option* option, float progressMin, float progressMax)
: sliderType(SliderProgress), mouseDownOnElement(false), option(option), numSteps(0), progressMin(progressMin), progressMax(progressMax) {
if(option != NULL) {
percentage = (minecraft->options.getProgressValue(option) - progressMin) / (progressMax - progressMin);
}
}
Slider::Slider(Minecraft* minecraft, const Options::Option* option, const std::vector<int>& stepVec )
: sliderType(SliderStep),
curStepValue(0),
curStep(0),
sliderSteps(stepVec),
mouseDownOnElement(false),
option(option),
percentage(0),
progressMin(0.0f),
progressMax(1.0) {
assert(stepVec.size() > 1);
numSteps = sliderSteps.size();
if(option != NULL) {
curStepValue;
int curStep;
curStepValue = minecraft->options.getIntValue(option);
std::vector<int>::iterator currentItem = std::find(sliderSteps.begin(), sliderSteps.end(), curStepValue);
if(currentItem != sliderSteps.end()) {
curStep = currentItem - sliderSteps.begin();
}
}
}
void Slider::render( Minecraft* minecraft, int xm, int ym ) {
int xSliderStart = x + 5;
int xSliderEnd = x + width - 5;
int ySliderStart = y + 6;
int ySliderEnd = y + 9;
int handleSizeX = 9;
int handleSizeY = 15;
int barWidth = xSliderEnd - xSliderStart;
//fill(x, y + 8, x + (int)(width * percentage), y + height, 0xffff00ff);
fill(xSliderStart, ySliderStart, xSliderEnd, ySliderEnd, 0xff606060);
if(sliderType == SliderStep) {
int stepDistance = barWidth / (numSteps -1);
for(int a = 0; a <= numSteps - 1; ++a) {
int renderSliderStepPosX = xSliderStart + a * stepDistance + 1;
fill(renderSliderStepPosX - 1, ySliderStart - 2, renderSliderStepPosX + 1, ySliderEnd + 2, 0xff606060);
}
}
minecraft->textures->loadAndBindTexture("gui/touchgui.png");
blit(xSliderStart + (int)(percentage * barWidth) - handleSizeX / 2, y, 226, 126, handleSizeX, handleSizeY, handleSizeX, handleSizeY);
}
void Slider::mouseClicked( Minecraft* minecraft, int x, int y, int buttonNum ) {
if(pointInside(x, y)) {
mouseDownOnElement = true;
}
}
void Slider::mouseReleased( Minecraft* minecraft, int x, int y, int buttonNum ) {
mouseDownOnElement = false;
if(sliderType == SliderStep) {
curStep = Mth::floor((percentage * (numSteps-1) + 0.5f));
curStepValue = sliderSteps[Mth::Min(curStep, numSteps-1)];
percentage = float(curStep) / (numSteps - 1);
setOption(minecraft);
}
}
void Slider::tick(Minecraft* minecraft) {
if(minecraft->screen != NULL) {
int xm = Mouse::getX();
int ym = Mouse::getY();
minecraft->screen->toGUICoordinate(xm, ym);
if(mouseDownOnElement) {
percentage = float(xm - x) / float(width);
percentage = Mth::clamp(percentage, 0.0f, 1.0f);
setOption(minecraft);
}
}
}
void Slider::setOption( Minecraft* minecraft ) {
if(option != NULL) {
if(sliderType == SliderStep) {
if(minecraft->options.getIntValue(option) != curStepValue) {
minecraft->options.set(option, curStepValue);
}
} else {
if(minecraft->options.getProgressValue(option) != percentage * (progressMax - progressMin) + progressMin) {
minecraft->options.set(option, percentage * (progressMax - progressMin) + progressMin);
}
}
}
}

View File

@@ -0,0 +1,40 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__Slider_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__Slider_H__
#include "GuiElement.h"
#include "../../../client/Options.h"
enum SliderType {
SliderProgress, // Sets slider between {0..1}
SliderStep // Uses the closest step
};
class Slider : public GuiElement {
typedef GuiElement super;
public:
// Creates a progress slider with no steps
Slider(Minecraft* minecraft, const Options::Option* option, float progressMin, float progressMax);
Slider(Minecraft* minecraft, const Options::Option* option, const std::vector<int>& stepVec);
virtual void render( Minecraft* minecraft, int xm, int ym );
virtual void mouseClicked( Minecraft* minecraft, int x, int y, int buttonNum );
virtual void mouseReleased( Minecraft* minecraft, int x, int y, int buttonNum );
virtual void tick(Minecraft* minecraft);
private:
virtual void setOption(Minecraft* minecraft);
private:
SliderType sliderType;
std::vector<int> sliderSteps;
bool mouseDownOnElement;
float percentage;
int curStepValue;
int curStep;
int numSteps;
float progressMin;
float progressMax;
const Options::Option* option;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__Slider_H__*/

View File

@@ -0,0 +1,24 @@
#include "SmallButton.h"
SmallButton::SmallButton( int id, int x, int y, const std::string& msg )
: super(id, x, y, 150, 20, msg),
option(NULL)
{
}
SmallButton::SmallButton( int id, int x, int y, int width, int height, const std::string& msg )
: super(id, x, y, width, height, msg),
option(NULL)
{
}
SmallButton::SmallButton( int id, int x, int y, Options::Option* item, const std::string& msg )
: super(id, x, y, 150, 20, msg),
option(item)
{
}
Options::Option* SmallButton::getOption()
{
return option;
}

View File

@@ -0,0 +1,23 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__SmallButton_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__SmallButton_H__
//package net.minecraft.client.gui;
#include <string>
#include "Button.h"
#include "../../Options.h"
class SmallButton: public Button
{
typedef Button super;
public:
SmallButton(int id, int x, int y, const std::string& msg);
SmallButton(int id, int x, int y, int width, int height, const std::string& msg);
SmallButton(int id, int x, int y, Options::Option* item, const std::string& msg);
Options::Option* getOption();
private:
Options::Option* option;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__SmallButton_H__*/

View File

@@ -0,0 +1,37 @@
#include "TextBox.h"
#include "../../Minecraft.h"
#include "../../../AppPlatform.h"
TextBox::TextBox( int id, const std::string& msg )
: id(0), w(0), h(0), x(0), y(0), text(msg), focused(false) {
}
TextBox::TextBox( int id, int x, int y, const std::string& msg )
: id(id), w(0), h(0), x(x), y(y), text(msg), focused(false) {
}
TextBox::TextBox( int id, int x, int y, int w, int h, const std::string& msg )
: id(id), w(w), h(h), x(x), y(y), text(msg) {
}
void TextBox::setFocus(Minecraft* minecraft) {
if(!focused) {
minecraft->platform()->showKeyboard();
focused = true;
}
}
bool TextBox::loseFocus(Minecraft* minecraft) {
if(focused) {
minecraft->platform()->showKeyboard();
focused = false;
return true;
}
return false;
}
void TextBox::render( Minecraft* minecraft, int xm, int ym ) {
}

View File

@@ -0,0 +1,34 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_COMPONENTS__TextBox_H__
#define NET_MINECRAFT_CLIENT_GUI_COMPONENTS__TextBox_H__
//package net.minecraft.client.gui;
#include <string>
#include "../GuiComponent.h"
#include "../../Options.h"
class Font;
class Minecraft;
class TextBox: public GuiComponent
{
public:
TextBox(int id, const std::string& msg);
TextBox(int id, int x, int y, const std::string& msg);
TextBox(int id, int x, int y, int w, int h, const std::string& msg);
virtual void setFocus(Minecraft* minecraft);
virtual bool loseFocus(Minecraft* minecraft);
virtual void render(Minecraft* minecraft, int xm, int ym);
public:
int w, h;
int x, y;
std::string text;
int id;
bool focused;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_COMPONENTS__TextBox_H__*/

View File

@@ -0,0 +1,370 @@
#include "ArmorScreen.h"
#include "../Screen.h"
#include "../components/NinePatch.h"
#include "../../Minecraft.h"
#include "../../player/LocalPlayer.h"
#include "../../renderer/Tesselator.h"
#include "../../renderer/entity/ItemRenderer.h"
#include "../../../world/item/Item.h"
#include "../../../world/item/ItemCategory.h"
#include "../../../world/entity/player/Inventory.h"
#include "../../../world/entity/item/ItemEntity.h"
#include "../../../world/level/Level.h"
#include "../../../network/RakNetInstance.h"
#include "../../renderer/entity/EntityRenderDispatcher.h"
#include "../../../world/item/ArmorItem.h"
static void setIfNotSet(bool& ref, bool condition) {
ref = (ref || condition);
}
const int descFrameWidth = 100;
const int rgbActive = 0xfff0f0f0;
const int rgbInactive = 0xc0635558;
const int rgbInactiveShadow = 0xc0aaaaaa;
#ifdef __APPLE__
static const float BorderPixels = 4;
#ifdef DEMO_MODE
static const float BlockPixels = 22;
#else
static const float BlockPixels = 22;
#endif
#else
static const float BorderPixels = 4;
static const float BlockPixels = 24;
#endif
static const int ItemSize = (int)(BlockPixels + 2*BorderPixels);
static const int Bx = 10; // Border Frame width
static const int By = 6; // Border Frame height
ArmorScreen::ArmorScreen():
inventoryPane(NULL),
btnArmor0(0),
btnArmor1(1),
btnArmor2(2),
btnArmor3(3),
btnClose(4, ""),
bHeader (5, "Armor"),
guiBackground(NULL),
guiSlot(NULL),
guiPaneFrame(NULL),
guiPlayerBg(NULL),
doRecreatePane(false),
descWidth(90)
//guiSlotItem(NULL),
//guiSlotItemSelected(NULL)
{
//LOGI("Creating ArmorScreen with %p, %d\n", furnace, furnace->runningId);
}
ArmorScreen::~ArmorScreen() {
delete inventoryPane;
delete guiBackground;
delete guiSlot;
delete guiPaneFrame;
delete guiPlayerBg;
}
void ArmorScreen::init() {
super::init();
player = minecraft->player;
ImageDef def;
def.name = "gui/spritesheet.png";
def.x = 0;
def.y = 1;
def.width = def.height = 18;
def.setSrc(IntRectangle(60, 0, 18, 18));
btnClose.setImageDef(def, true);
btnClose.scaleWhenPressed = false;
buttons.push_back(&bHeader);
buttons.push_back(&btnClose);
armorButtons[0] = &btnArmor0;
armorButtons[1] = &btnArmor1;
armorButtons[2] = &btnArmor2;
armorButtons[3] = &btnArmor3;
for (int i = 0; i < NUM_ARMORBUTTONS; ++i)
buttons.push_back(armorButtons[i]);
// GUI - nine patches
NinePatchFactory builder(minecraft->textures, "gui/spritesheet.png");
guiBackground = builder.createSymmetrical(IntRectangle(0, 0, 16, 16), 4, 4);
guiSlot = builder.createSymmetrical(IntRectangle(0, 32, 8, 8), 3, 3, 20, 20);
guiPaneFrame = builder.createSymmetrical(IntRectangle(28, 42, 4, 4), 1, 1)->setExcluded(1 << 4);
guiPlayerBg = builder.createSymmetrical(IntRectangle(0, 20, 8, 8), 3, 3);
updateItems();
}
void ArmorScreen::setupPositions() {
// Left - Categories
bHeader.x = bHeader.y = 0;
bHeader.width = width;// - bDone.w;
btnClose.width = btnClose.height = 19;
btnClose.x = width - btnClose.width;
btnClose.y = 0;
// Inventory pane
const int maxWidth = (int)(width/1.8f) - Bx - Bx;
const int InventoryColumns = maxWidth / ItemSize;
const int realWidth = InventoryColumns * ItemSize;
const int paneWidth = realWidth + Bx + Bx;
const int realBx = (paneWidth - realWidth) / 2;
inventoryPaneRect = IntRectangle(realBx,
#ifdef __APPLE__
26 + By - ((width==240)?1:0), realWidth, ((width==240)?1:0) + height-By-By-28);
#else
26 + By, realWidth, height-By-By-28);
#endif
for (int i = 0; i < NUM_ARMORBUTTONS; ++i) {
Button& b = *armorButtons[i];
b.x = paneWidth;
b.y = inventoryPaneRect.y + 24 * i;
b.width = 20;
b.height = 20;
}
guiPlayerBgRect.y = inventoryPaneRect.y;
int xx = armorButtons[0]->x + armorButtons[0]->width;
int xw = width - xx;
guiPlayerBgRect.x = xx + xw / 10;
guiPlayerBgRect.w = xw - (xw / 10) * 2;
guiPlayerBgRect.h = inventoryPaneRect.h;
guiPaneFrame->setSize((float)inventoryPaneRect.w + 2, (float)inventoryPaneRect.h + 2);
guiPlayerBg->setSize((float)guiPlayerBgRect.w, (float)guiPlayerBgRect.h);
guiBackground->setSize((float)width, (float)height);
updateItems();
setupInventoryPane();
}
void ArmorScreen::tick() {
if (inventoryPane)
inventoryPane->tick();
if (doRecreatePane) {
updateItems();
setupInventoryPane();
doRecreatePane = false;
}
}
void ArmorScreen::handleRenderPane(Touch::InventoryPane* pane, Tesselator& t, int xm, int ym, float a) {
if (pane) {
pane->render(xm, ym, a);
guiPaneFrame->draw(t, (float)(pane->rect.x - 1), (float)(pane->rect.y - 1));
}
}
void ArmorScreen::render(int xm, int ym, float a) {
//renderBackground();
Tesselator& t = Tesselator::instance;
t.addOffset(0, 0, -500);
guiBackground->draw(t, 0, 0);
t.addOffset(0, 0, 500);
glEnable2(GL_ALPHA_TEST);
// Buttons (Left side + crafting)
super::render(xm, ym, a);
handleRenderPane(inventoryPane, t, xm, ym, a);
t.colorABGR(0xffffffff);
glColor4f2(1, 1, 1, 1);
t.addOffset(0, 0, -490);
guiPlayerBg->draw(t, (float)guiPlayerBgRect.x, (float)guiPlayerBgRect.y);
t.addOffset(0, 0, 490);
renderPlayer((float)(guiPlayerBgRect.x + guiPlayerBgRect.w / 2), 0.85f * height);
for (int i = 0; i < NUM_ARMORBUTTONS; ++i) {
drawSlotItemAt(t, i, player->getArmor(i), armorButtons[i]->x, armorButtons[i]->y);
}
glDisable2(GL_ALPHA_TEST);
}
void ArmorScreen::buttonClicked(Button* button) {
if (button == &btnClose) {
minecraft->setScreen(NULL);
}
if (button->id >= 0 && button->id <= 3) {
takeAndClearSlot(button->id);
}
}
bool ArmorScreen::addItem(const Touch::InventoryPane* forPane, int itemIndex) {
const ItemInstance* instance = armorItems[itemIndex];
if (!ItemInstance::isArmorItem(instance))
return false;
ArmorItem* item = (ArmorItem*) instance->getItem();
ItemInstance* old = player->getArmor(item->slot);
ItemInstance oldArmor;
if (ItemInstance::isArmorItem(old)) {
oldArmor = *old;
}
player->setArmor(item->slot, instance);
player->inventory->removeItem(instance);
//@attn: this is hugely important
armorItems[itemIndex] = NULL;
if (!oldArmor.isNull()) {
if (!player->inventory->add(&oldArmor)) {
player->drop(new ItemInstance(oldArmor), false);
}
}
doRecreatePane = true;
return true;
}
bool ArmorScreen::isAllowed( int slot ) {
return true;
}
bool ArmorScreen::renderGameBehind() {
return false;
}
std::vector<const ItemInstance*> ArmorScreen::getItems( const Touch::InventoryPane* forPane ) {
return armorItems;
}
void ArmorScreen::updateItems() {
armorItems.clear();
for (int i = Inventory::MAX_SELECTION_SIZE; i < minecraft->player->inventory->getContainerSize(); ++i) {
ItemInstance* item = minecraft->player->inventory->getItem(i);
if (ItemInstance::isArmorItem(item))
armorItems.push_back(item);
}
}
bool ArmorScreen::canMoveToSlot(int slot, const ItemInstance* item) {
return ItemInstance::isArmorItem(item)
&& ((ArmorItem*)item)->slot == slot;
}
void ArmorScreen::setupInventoryPane() {
// IntRectangle(0, 0, 100, 100)
if (inventoryPane) delete inventoryPane;
inventoryPane = new Touch::InventoryPane(this, minecraft, inventoryPaneRect, inventoryPaneRect.w, BorderPixels, armorItems.size(), ItemSize, (int)BorderPixels);
inventoryPane->fillMarginX = 0;
inventoryPane->fillMarginY = 0;
//LOGI("Creating new pane: %d %p\n", inventoryItems.size(), inventoryPane);
}
void ArmorScreen::drawSlotItemAt( Tesselator& t, int slot, const ItemInstance* item, int x, int y)
{
float xx = (float)x;
float yy = (float)y;
guiSlot->draw(t, xx, yy);
if (item && !item->isNull()) {
ItemRenderer::renderGuiItem(minecraft->font, minecraft->textures, item, xx + 2, yy, true);
glDisable2(GL_TEXTURE_2D);
ItemRenderer::renderGuiItemDecorations(item, xx + 2, yy + 3);
glEnable2(GL_TEXTURE_2D);
//minecraft->gui.renderSlotText(item, xx + 3, yy + 3, true, true);
} else {
minecraft->textures->loadAndBindTexture("gui/items.png");
blit(x + 2, y, 15 * 16, slot * 16, 16, 16, 16, 16);
}
}
void ArmorScreen::takeAndClearSlot( int slot ) {
ItemInstance* item = player->getArmor(slot);
if (!item)
return;
int oldSize = minecraft->player->inventory->getNumEmptySlots();
if (!minecraft->player->inventory->add(item))
minecraft->player->drop(new ItemInstance(*item), false);
player->setArmor(slot, NULL);
int newSize = minecraft->player->inventory->getNumEmptySlots();
setIfNotSet(doRecreatePane, newSize != oldSize);
}
void ArmorScreen::renderPlayer(float xo, float yo) {
// Push GL and player state
glPushMatrix();
glTranslatef(xo, yo, -200);
float ss = 45;
glScalef(-ss, ss, ss);
glRotatef(180, 0, 0, 1);
//glDisable(GL_DEPTH_TEST);
Player* player = (Player*) minecraft->player;
float oybr = player->yBodyRot;
float oyr = player->yRot;
float oxr = player->xRot;
float t = getTimeS();
float xd = 10 * Mth::sin(t);//(xo + 51) - xm;
float yd = 10 * Mth::cos(t * 0.05f);//(yo + 75 - 50) - ym;
glRotatef(45 + 90, 0, 1, 0);
glRotatef(-45 - 90, 0, 1, 0);
const float xtan = Mth::atan(xd / 40.0f) * +20;
const float ytan = Mth::atan(yd / 40.0f) * -20;
glRotatef(ytan, 1, 0, 0);
player->yBodyRot = xtan;
player->yRot = xtan + xtan;
player->xRot = ytan;
glTranslatef(0, player->heightOffset, 0);
// Push walking anim
float oldWAP = player->walkAnimPos;
float oldWAS = player->walkAnimSpeed;
float oldWASO = player->walkAnimSpeedO;
// Set new walking anim
player->walkAnimSpeedO = player->walkAnimSpeed = 0.25f;
player->walkAnimPos = getTimeS() * player->walkAnimSpeed * SharedConstants::TicksPerSecond;
EntityRenderDispatcher* rd = EntityRenderDispatcher::getInstance();
rd->playerRotY = 180;
rd->render(player, 0, 0, 0, 0, 1);
// Pop walking anim
player->walkAnimPos = oldWAP;
player->walkAnimSpeed = oldWAS;
player->walkAnimSpeedO = oldWASO;
//glEnable(GL_DEPTH_TEST);
// Pop GL and player state
player->yBodyRot = oybr;
player->yRot = oyr;
player->xRot = oxr;
glPopMatrix();
}

View File

@@ -0,0 +1,79 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__ArmorScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__ArmorScreen_H__
#include "BaseContainerScreen.h"
#include "../components/InventoryPane.h"
#include "../components/Button.h"
class Font;
class CItem;
class Textures;
class NinePatchLayer;
class Tesselator;
class ArmorScreen: public Screen,
public Touch::IInventoryPaneCallback
{
typedef Screen super;
typedef std::vector<CItem*> ItemList;
static const int NUM_ARMORBUTTONS = 4;
public:
ArmorScreen();
~ArmorScreen();
void init();
void setupPositions();
void tick();
void render(int xm, int ym, float a);
bool renderGameBehind();
void buttonClicked(Button* button);
// IInventoryPaneCallback
bool addItem(const Touch::InventoryPane* pane, int itemId);
bool isAllowed( int slot );
std::vector<const ItemInstance*> getItems( const Touch::InventoryPane* forPane );
private:
void renderPlayer(float xo, float yo);
void setupInventoryPane();
void updateItems();
void drawSlotItemAt(Tesselator& t, int slot, const ItemInstance* item, int x, int y);
ItemInstance moveOver(const ItemInstance* item, int maxCount);
void takeAndClearSlot( int slot );
void handleRenderPane(Touch::InventoryPane* pane, Tesselator& t, int xm, int ym, float a);
bool canMoveToSlot(int slot, const ItemInstance* item);
ItemList _items;
std::string currentItemDesc;
ItemInstance burnResult;
float descWidth;
ImageButton btnClose;
BlankButton btnArmor0;
BlankButton btnArmor1;
BlankButton btnArmor2;
BlankButton btnArmor3;
BlankButton* armorButtons[4];
Touch::THeader bHeader;
Touch::InventoryPane* inventoryPane;
IntRectangle inventoryPaneRect;
IntRectangle guiPlayerBgRect;
std::vector<const ItemInstance*> armorItems;
bool doRecreatePane;
// GUI elements such as 9-Patches
NinePatchLayer* guiBackground;
NinePatchLayer* guiSlot;
NinePatchLayer* guiPaneFrame;
NinePatchLayer* guiPlayerBg;
Player* player;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__ArmorScreen_H__*/

View File

@@ -0,0 +1,50 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__BaseContainerScreen_H__
#define NET_MINECRAFT_CLIENT_GUI__BaseContainerScreen_H__
//package net.minecraft.client.gui.screens;
#include <vector>
#include "../Screen.h"
#include "../../Minecraft.h"
#include "../../player/LocalPlayer.h"
class BaseContainerMenu;
class BaseContainerScreen: public Screen
{
typedef Screen super;
public:
BaseContainerScreen(BaseContainerMenu* menu)
: menu(menu)
{
}
virtual void init() {
super::init();
minecraft->player->containerMenu = menu;
}
virtual void tick() {
super::tick();
if (!minecraft->player->isAlive() || minecraft->player->removed)
minecraft->player->closeContainer();
}
virtual void keyPressed( int eventKey )
{
if (eventKey == Keyboard::KEY_ESCAPE) {
minecraft->player->closeContainer();
} else {
super::keyPressed(eventKey);
}
}
virtual bool closeOnPlayerHurt() {
return true;
}
protected:
BaseContainerMenu* menu;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__BaseContainerScreen_H__*/

View File

@@ -0,0 +1,26 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__BuyGameScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__BuyGameScreen_H__
#include "../Screen.h"
#include "../components/Button.h"
class BuyGameScreen: public Screen
{
public:
BuyGameScreen() {}
virtual ~BuyGameScreen() {}
void init();
void render(int xm, int ym, float a);
void buttonClicked(Button* button) {
//if (button->id == bQuit.id)
}
private:
//Button bQuit;
//Button bBuyGame;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__BuyGameScreen_H__*/

View File

@@ -0,0 +1,24 @@
#include "ChatScreen.h"
#include "DialogDefinitions.h"
#include "../Gui.h"
#include "../../Minecraft.h"
#include "../../../AppPlatform.h"
#include "../../../platform/log.h"
void ChatScreen::init() {
minecraft->platform()->createUserInput(DialogDefinitions::DIALOG_NEW_CHAT_MESSAGE);
}
void ChatScreen::render(int xm, int ym, float a)
{
int status = minecraft->platform()->getUserInputStatus();
if (status > -1) {
if (status == 1) {
std::vector<std::string> v = minecraft->platform()->getUserInput();
if (v.size() && v[0].length() > 0)
minecraft->gui.addMessage(v[0]);
}
minecraft->setScreen(NULL);
}
}

View File

@@ -0,0 +1,21 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__ChatScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__ChatScreen_H__
#include "../Screen.h"
class ChatScreen: public Screen
{
public:
ChatScreen() {}
virtual ~ChatScreen() {}
void init();
void render(int xm, int ym, float a);
void buttonClicked(Button* button) {};
private:
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__ChatScreen_H__*/

View File

@@ -0,0 +1,474 @@
#include "ChestScreen.h"
#include "touch/TouchStartMenuScreen.h"
#include "../Screen.h"
#include "../components/NinePatch.h"
#include "../../Minecraft.h"
#include "../../player/LocalPlayer.h"
#include "../../renderer/Tesselator.h"
#include "../../renderer/entity/ItemRenderer.h"
#include "../../../world/item/Item.h"
#include "../../../world/item/ItemCategory.h"
#include "../../../world/entity/player/Inventory.h"
#include "../../../world/entity/item/ItemEntity.h"
#include "../../../world/level/Level.h"
#include "../../../locale/I18n.h"
#include "../../../util/StringUtils.h"
#include "../../../network/packet/ContainerSetSlotPacket.h"
#include "../../../network/RakNetInstance.h"
#include "../../../world/level/tile/entity/TileEntity.h"
#include "../../../world/level/tile/entity/ChestTileEntity.h"
#include "../../../world/inventory/ContainerMenu.h"
#include "../../../util/Mth.h"
//static NinePatchLayer* guiPaneFrame = NULL;
static __inline void setIfNotSet(bool& ref, bool condition) {
ref = (ref || condition);
}
template<typename T,typename V>
T* upcast(V* x) { return x; }
static int heldMs = -1;
static int percent = -1;
static const float MaxHoldMs = 500.0f;
static const int MinChargeMs = 200;
class ItemDiffer {
public:
ItemDiffer(int size)
: size(size),
count(0)
{
base = new ItemInstance[size];
}
ItemDiffer(const std::vector<const ItemInstance*>& v)
: size(v.size()),
count(0)
{
base = new ItemInstance[size];
init(v);
}
~ItemDiffer() {
delete[] base;
}
void init(const std::vector<const ItemInstance*>& v) {
for (int i = 0; i < size; ++i) {
if (v[i]) base[i] = *v[i];
else base[i].setNull();
}
}
int getDiff(const std::vector<const ItemInstance*>& v, std::vector<int>& outIndices) {
int diffLen = v.size() - size;
int minLen = Mth::Max((int)v.size(), size);
for (int i = 0; i < minLen; ++i) {
//LOGI("%s, %s\n", base[i].toString().c_str(), v[i]?v[i]->toString().c_str() : "null");
if (!ItemInstance::matchesNulls(&base[i], v[i]))
outIndices.push_back(i);
}
return diffLen;
}
private:
int size;
int count;
ItemInstance* base;
};
const int descFrameWidth = 100;
const int rgbActive = 0xfff0f0f0;
const int rgbInactive = 0xc0635558;
const int rgbInactiveShadow = 0xc0aaaaaa;
#ifdef __APPLE__
static const float BorderPixels = 3;
#ifdef DEMO_MODE
static const float BlockPixels = 22;
#else
static const float BlockPixels = 22;
#endif
#else
static const float BorderPixels = 4;
static const float BlockPixels = 24;
#endif
static const int ItemSize = (int)(BlockPixels + 2*BorderPixels);
static const int Bx = 10; // Border Frame width
static const int By = 6; // Border Frame height
typedef struct FlyingItem {
ItemInstance item;
float startTime;
float sx, sy;
float dx, dy;
} FlyingItem ;
static std::vector<FlyingItem> flyingItems;
ChestScreen::ChestScreen(Player* player, ChestTileEntity* chest)
: super(new ContainerMenu(chest, chest->runningId)), //@huge @attn
inventoryPane(NULL),
chestPane(NULL),
btnClose(4, ""),
bHeader (5, "Inventory"),
bHeaderChest (6, "Chest"),
guiBackground(NULL),
guiSlot(NULL),
guiSlotMarked(NULL),
guiSlotMarker(NULL),
player(player),
chest(chest),
selectedSlot(-1),
doRecreatePane(false)
//guiSlotItem(NULL),
//guiSlotItemSelected(NULL)
{
}
ChestScreen::~ChestScreen() {
delete inventoryPane;
delete chestPane;
delete guiBackground;
delete guiSlot;
delete guiSlotMarked;
delete guiSlotMarker;
delete guiPaneFrame;
delete menu;
if (chest->clientSideOnly)
delete chest;
}
void ChestScreen::init() {
super::init();
//printf("-> %d\n", width/2);
ImageDef def;
def.name = "gui/spritesheet.png";
def.x = 0;
def.y = 1;
def.width = def.height = 18;
def.setSrc(IntRectangle(60, 0, 18, 18));
btnClose.setImageDef(def, true);
btnClose.scaleWhenPressed = false;
buttons.push_back(&bHeader);
buttons.push_back(&bHeaderChest);
buttons.push_back(&btnClose);
// GUI - nine patches
NinePatchFactory builder(minecraft->textures, "gui/spritesheet.png");
guiBackground = builder.createSymmetrical(IntRectangle(0, 0, 16, 16), 4, 4);
guiSlot = builder.createSymmetrical(IntRectangle(0, 32, 8, 8), 3, 3);
guiSlotMarked = builder.createSymmetrical(IntRectangle(0, 44, 8, 8), 3, 3);
guiSlotMarker = builder.createSymmetrical(IntRectangle(10, 42, 16, 16), 5, 5);
guiPaneFrame = builder.createSymmetrical(IntRectangle(28, 42, 4, 4), 1, 1)->exclude(4);
}
void ChestScreen::setupPositions() {
// Left - Categories
bHeader.x = 0;
bHeader.y = bHeaderChest.y = 0;
bHeader.width = bHeaderChest.width = width / 2;// - bDone.w;
bHeaderChest.x = bHeader.x + bHeader.width;
// Right - Description
btnClose.width = btnClose.height = 19;
btnClose.x = width - btnClose.width;
btnClose.y = 0;
//guiPaneFrame->setSize((float)paneFuelRect.w + 2, (float)paneFuelRect.h + 4);
guiBackground->setSize((float)width, (float)height);
//guiSlotItem->setSize((float)width, 22); //@todo
//guiSlotItemSelected->setSize((float)width, 22);
setupPane();
}
void ChestScreen::tick() {
if (inventoryPane)
inventoryPane->tick();
if (chestPane)
chestPane->tick();
if (doRecreatePane) {
setupPane();
doRecreatePane = false;
}
}
void ChestScreen::handleRenderPane(Touch::InventoryPane* pane, Tesselator& t, int xm, int ym, float a) {
if (pane) {
int ms, id;
pane->markerIndex = -1;
if (pane->queryHoldTime(&id, &ms)) {
heldMs = ms;
FillingContainer* c = (pane == inventoryPane)?
upcast<FillingContainer>(minecraft->player->inventory)
: upcast<FillingContainer>(chest);
const int slotIndex = id + c->getNumLinkedSlots();
ItemInstance* item = c->getItem(slotIndex);
int count = (item && !item->isNull())? item->count : 0;
float maxHoldMs = item? 700 + 10 * item->count: MaxHoldMs;
if (count > 1) {
float share = (heldMs-MinChargeMs) / maxHoldMs;
pane->markerType = 1;//(heldMs >= MinChargeMs)? 1 : 0;
pane->markerIndex = id;
pane->markerShare = Mth::Max(share, 0.0f);
percent = (int)Mth::clamp(100.0f * share, 0.0f, 100.0f);
if (percent >= 100) {
addItem(pane, id);
}
}
}
pane->render(xm, ym, a);
guiPaneFrame->draw(t, (float)(pane->rect.x - 1), (float)(pane->rect.y - 1));
//LOGI("query-iv: %d, %d\n", gridId, heldMs);
}
}
void ChestScreen::render(int xm, int ym, float a) {
const int N = 5;
static StopwatchNLast r(N);
//renderBackground();
Tesselator& t = Tesselator::instance;
guiBackground->draw(t, 0, 0);
glEnable2(GL_ALPHA_TEST);
// Buttons (Left side + crafting)
super::render(xm, ym, a);
heldMs = -1;
handleRenderPane(inventoryPane, t, xm, ym, a);
handleRenderPane(chestPane, t, xm, ym, a);
float now = getTimeS();
float MaxTime = 0.3f;
std::vector<FlyingItem> flyingToSave;
glEnable2(GL_BLEND);
glColor4f(1, 1, 1, 0.2f);
t.beginOverride();
//t.color(1.0f, 0.0f, 0.0f, 0.2f);
//t.noColor();
glEnable2(GL_SCISSOR_TEST);
//LOGI("panesBox: %d, %d - %d, %d\n", panesBbox.x, panesBbox.y, panesBbox.w, panesBbox.h);
minecraft->gui.setScissorRect(panesBbox);
for (unsigned int i = 0; i < flyingItems.size(); ++i) {
FlyingItem& fi = flyingItems[i];
float since = (now - fi.startTime);
if (since > MaxTime) continue;
float t = since / MaxTime;
t *= t;
//float xx = fi.sx + t * 100.0f;
float xx = Mth::lerp(fi.sx, fi.dx, t);
float yy = Mth::lerp(fi.sy, fi.dy, t);
ItemRenderer::renderGuiItem(minecraft->font, minecraft->textures, &fi.item, xx + 7, yy + 8, true);
//minecraft->gui.renderSlotText(&fi.item, xx + 3, yy + 3, true, true);
flyingToSave.push_back(fi);
}
t.enableColor();
t.endOverrideAndDraw();
glDisable2(GL_SCISSOR_TEST);
flyingItems = flyingToSave;
t.colorABGR(0xffffffff);
glDisable2(GL_BLEND);
minecraft->textures->loadAndBindTexture("gui/spritesheet.png");
}
void ChestScreen::buttonClicked(Button* button) {
if (button == &btnClose) {
minecraft->player->closeContainer();
}
}
bool ChestScreen::handleAddItem(FillingContainer* from, FillingContainer* to, int itemIndex) {
const int itemOffset = from->getNumLinkedSlots();
const int slotIndex = itemIndex + itemOffset;
ItemInstance* item = from->getItem(slotIndex);
bool added = false;
bool fromChest = (from == chest);
Touch::InventoryPane* pane = fromChest? chestPane : inventoryPane;
Touch::InventoryPane* toPane = fromChest? inventoryPane : chestPane;
int wantedCount = (item && !item->isNull())? item->count * percent / 100 : 0;
if ((item && !item->isNull()) && (!wantedCount || heldMs < MinChargeMs)) {
wantedCount = 1;
}
if (wantedCount > 0) {
ItemInstance takenItem(*item);
takenItem.count = wantedCount;
ItemDiffer differ(getItems(toPane));
to->add(&takenItem);
added = (takenItem.count != wantedCount);
if (added) {
item->count -= (wantedCount - takenItem.count);
std::vector<int> changed;
std::vector<const ItemInstance*> items = getItems(toPane);
differ.getDiff(items, changed);
ScrollingPane::GridItem g, gTo;
pane->getGridItemFor_slow(itemIndex, g);
//LOGI("Changed: %d\n", changed.size());
for (unsigned int i = 0; i < changed.size(); ++i) {
FlyingItem fi;
fi.startTime = getTimeS();
fi.item = *item;
fi.sx = g.xf;
fi.sy = g.yf;
int toIndex = changed[i];
toPane->getGridItemFor_slow(toIndex, gTo);
fi.dx = gTo.xf;
fi.dy = gTo.yf;
flyingItems.push_back(fi);
if (!fromChest && minecraft->level->isClientSide) {
int j = toIndex;
ItemInstance item = items[j]? *items[j] : ItemInstance();
ContainerSetSlotPacket p(menu->containerId, j, item);
minecraft->raknetInstance->send(p);
}
}
}
// Send to server, needs a bit special handling
if (fromChest) {
ItemInstance ins(item->count <= 0? ItemInstance() : *item);
ContainerSetSlotPacket p(menu->containerId, slotIndex, ins);
minecraft->raknetInstance->send(p);
}
if (item->count <= 0)
from->clearSlot(slotIndex);
}
// Clear the marker indices
pane->markerIndex = toPane->markerIndex = -1;
return added;
}
bool ChestScreen::addItem(const Touch::InventoryPane* forPane, int itemIndex) {
//LOGI("items.size, index: %d, %d\n", inventoryItems.size(), itemIndex);
bool l2r = (forPane == inventoryPane);
return handleAddItem( l2r? upcast<FillingContainer>(minecraft->player->inventory) : upcast<FillingContainer>(chest),
l2r? upcast<FillingContainer>(chest) : upcast<FillingContainer>(minecraft->player->inventory),
itemIndex);
}
bool ChestScreen::isAllowed( int slot )
{
return true;
}
bool ChestScreen::renderGameBehind()
{
return false;
}
std::vector<const ItemInstance*> ChestScreen::getItems( const Touch::InventoryPane* forPane )
{
if (forPane == inventoryPane) {
for (int i = Inventory::MAX_SELECTION_SIZE, j = 0; i < minecraft->player->inventory->getContainerSize(); ++i, ++j)
inventoryItems[j] = minecraft->player->inventory->getItem(i);
return inventoryItems;
}
else {
for (int i = 0; i < chest->getContainerSize(); ++i)
chestItems[i] = chest->getItem(i);
return chestItems;
}
}
void ChestScreen::setupPane()
{
inventoryItems.clear();
for (int i = Inventory::MAX_SELECTION_SIZE; i < minecraft->player->inventory->getContainerSize(); ++i) {
ItemInstance* item = minecraft->player->inventory->getItem(i);
/*if (!item || item->isNull()) continue;*/
inventoryItems.push_back(item);
}
chestItems.clear();
for (int i = 0; i < chest->getContainerSize(); ++i) {
ItemInstance* item = chest->getItem(i);
/*if (!item || item->isNull()) continue;*/
chestItems.push_back(item);
}
int maxWidth = width/2 - Bx/2;//- Bx - Bx/*- Bx*/;
int InventoryColumns = maxWidth / ItemSize;
const int realWidth = InventoryColumns * ItemSize;
int paneWidth = realWidth;// + Bx + Bx;
const int realBx = (width/2 - realWidth) / 2;
IntRectangle rect(realBx,
#ifdef __APPLE__
24 + By - ((width==240)?1:0), realWidth, ((width==240)?1:0) + height-By-By-24);
#else
24 + By, realWidth, height-By-By-24);
#endif
// IntRectangle(0, 0, 100, 100)
if (inventoryPane) delete inventoryPane;
inventoryPane = new Touch::InventoryPane(this, minecraft, rect, paneWidth, BorderPixels, minecraft->player->inventory->getContainerSize() - Inventory::MAX_SELECTION_SIZE, ItemSize, (int)BorderPixels);
inventoryPane->fillMarginX = 0;
inventoryPane->fillMarginY = 0;
guiPaneFrame->setSize((float)rect.w + 2, (float)rect.h + 2);
panesBbox = rect;
rect.x += width/2;// - rect.w - Bx;
panesBbox.w += (rect.x - panesBbox.x);
if (chestPane) delete chestPane;
chestPane = new Touch::InventoryPane(this, minecraft, rect, paneWidth, BorderPixels, chest->getContainerSize(), ItemSize, (int)BorderPixels);
chestPane->fillMarginX = 0;
chestPane->fillMarginY = 0;
LOGI("Creating new panes\n:"
" Inventory %d %p\n"
" Chest %d %p\n", (int)inventoryItems.size(), inventoryPane, (int)chestItems.size(), chestPane);
}
void ChestScreen::drawSlotItemAt( Tesselator& t, const ItemInstance* item, int x, int y, bool selected)
{
float xx = (float)x;
float yy = (float)y;
(selected? guiSlot/*Marked*/ : guiSlot)->draw(t, xx, yy);
if (selected)
guiSlotMarker->draw(t, xx - 2, yy - 2);
if (item && !item->isNull()) {
ItemRenderer::renderGuiItem(minecraft->font, minecraft->textures, item, xx + 7, yy + 8, true);
minecraft->gui.renderSlotText(item, xx + 3, yy + 3, true, true);
}
}

View File

@@ -0,0 +1,72 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__ChestScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__ChestScreen_H__
#include "BaseContainerScreen.h"
#include "../components/InventoryPane.h"
#include "../components/Button.h"
class Font;
class CItem;
class Textures;
class NinePatchLayer;
class FillingContainer;
class ChestTileEntity;
class Tesselator;
class ChestScreen: public BaseContainerScreen,
public Touch::IInventoryPaneCallback
{
typedef BaseContainerScreen super;
typedef std::vector<CItem*> ItemList;
friend class ItemPane;
public:
ChestScreen(Player* player, ChestTileEntity* chest);
~ChestScreen();
void init();
void setupPositions();
void tick();
void render(int xm, int ym, float a);
bool renderGameBehind();
void buttonClicked(Button* button);
// IInventoryPaneCallback
bool addItem(const Touch::InventoryPane* pane, int itemId);
bool isAllowed( int slot );
std::vector<const ItemInstance*> getItems( const Touch::InventoryPane* forPane );
//const ItemList& getItems(const ItemPane* forPane);
private:
void setupPane();
void drawSlotItemAt(Tesselator& t, const ItemInstance* item, int x, int y, bool selected);
bool handleAddItem(FillingContainer* from, FillingContainer* to, int itemIndex);
void handleRenderPane(Touch::InventoryPane* pane, Tesselator& t, int xm, int ym, float a);
std::string currentItemDesc;
ImageButton btnClose;
Touch::THeader bHeader;
Touch::THeader bHeaderChest;
Touch::InventoryPane* inventoryPane;
Touch::InventoryPane* chestPane;
IntRectangle panesBbox;
std::vector<const ItemInstance*> inventoryItems;
std::vector<const ItemInstance*> chestItems;
bool doRecreatePane;
int selectedSlot;
// GUI elements such as 9-Patches
NinePatchLayer* guiBackground;
NinePatchLayer* guiSlot;
NinePatchLayer* guiSlotMarked;
NinePatchLayer* guiSlotMarker;
NinePatchLayer* guiPaneFrame;
Player* player;
ChestTileEntity* chest;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__ChestScreen_H__*/

View File

@@ -0,0 +1,26 @@
#include "ChooseLevelScreen.h"
#include <algorithm>
#include <set>
#include "../../Minecraft.h"
void ChooseLevelScreen::init() {
loadLevelSource();
}
void ChooseLevelScreen::loadLevelSource()
{
LevelStorageSource* levelSource = minecraft->getLevelSource();
levelSource->getLevelList(levels);
std::sort(levels.begin(), levels.end());
}
std::string ChooseLevelScreen::getUniqueLevelName( const std::string& level ) {
std::set<std::string> Set;
for (unsigned int i = 0; i < levels.size(); ++i)
Set.insert(levels[i].id);
std::string s = level;
while ( Set.find(s) != Set.end() )
s += "-";
return s;
}

View File

@@ -0,0 +1,21 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__ChooseLevelScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__ChooseLevelScreen_H__
#include "../Screen.h"
#include "../../../world/level/storage/LevelStorageSource.h"
class ChooseLevelScreen: public Screen
{
public:
void init();
protected:
std::string getUniqueLevelName(const std::string& level);
private:
void loadLevelSource();
LevelSummaryList levels;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__ChooseLevelScreen_H__*/

View File

@@ -0,0 +1,84 @@
#include "ConfirmScreen.h"
#include "../components/Button.h"
#include "../../Minecraft.h"
ConfirmScreen::ConfirmScreen(Screen* parent_, const std::string& title1_, const std::string& title2_, int id_)
: parent(parent_),
title1(title1_),
title2(title2_),
id(id_),
yesButtonText("Ok"),
noButtonText("Cancel"),
yesButton(0),
noButton(0)
{
}
ConfirmScreen::ConfirmScreen(Screen* parent_, const std::string& title1_, const std::string& title2_, const std::string& yesButton_, const std::string& noButton_, int id_ )
: parent(parent_),
title1(title1_),
title2(title2_),
id(id_),
yesButtonText(yesButton_),
noButtonText(noButton_)
{
}
ConfirmScreen::~ConfirmScreen() {
delete yesButton;
delete noButton;
}
void ConfirmScreen::init()
{
if (minecraft->useTouchscreen()) {
yesButton = new Touch::TButton(0, 0, 0, yesButtonText),
noButton = new Touch::TButton(1, 0, 0, noButtonText);
} else {
yesButton = new Button(0, 0, 0, yesButtonText),
noButton = new Button(1, 0, 0, noButtonText);
}
buttons.push_back(yesButton);
buttons.push_back(noButton);
tabButtons.push_back(yesButton);
tabButtons.push_back(noButton);
}
void ConfirmScreen::setupPositions() {
const int ButtonWidth = 120;
const int ButtonHeight = 24;
yesButton->x = width / 2 - ButtonWidth - 4;
yesButton->y = height / 6 + 72;
noButton->x = width / 2 + 4;
noButton->y = height / 6 + 72;
yesButton->width = noButton->width = ButtonWidth;
yesButton->height = noButton->height = ButtonHeight;
}
bool ConfirmScreen::handleBackEvent(bool isDown) {
if (!isDown)
postResult(false);
return true;
}
void ConfirmScreen::render( int xm, int ym, float a )
{
renderBackground();
drawCenteredString(font, title1, width / 2, 50, 0xffffff);
drawCenteredString(font, title2, width / 2, 70, 0xffffff);
super::render(xm, ym, a);
}
void ConfirmScreen::buttonClicked( Button* button )
{
postResult(button->id == 0);
}
void ConfirmScreen::postResult(bool isOk)
{
parent->confirmResult(isOk, id);
}

View File

@@ -0,0 +1,41 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__ConfirmScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__ConfirmScreen_H__
//package net.minecraft.client.gui;
#include "../Screen.h"
#include "../components/SmallButton.h"
#include <string>
class ConfirmScreen: public Screen
{
typedef Screen super;
public:
ConfirmScreen(Screen* parent_, const std::string& title1_, const std::string& title2_, int id_);
ConfirmScreen(Screen* parent_, const std::string& title1_, const std::string& title2_, const std::string& yesButton, const std::string& noButton, int id_);
~ConfirmScreen();
void init();
void setupPositions();
bool handleBackEvent(bool isDown);
void render(int xm, int ym, float a);
protected:
void buttonClicked(Button* button);
virtual void postResult(bool isOk);
Screen* parent;
int id;
private:
std::string title1;
std::string title2;
std::string yesButtonText;
std::string noButtonText;
Button* yesButton; // 0
Button* noButton; // 1
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__ConfirmScreen_H__*/

View File

@@ -0,0 +1,83 @@
#include "DeathScreen.h"
#include "ScreenChooser.h"
#include "../components/Button.h"
#include "../../Minecraft.h"
#include "../../player/LocalPlayer.h"
#include "../../../platform/time.h"
static const int WAIT_TICKS = 30;
DeathScreen::DeathScreen()
: bRespawn(0),
bTitle(0),
_hasChosen(false),
_tick(0)
{
}
DeathScreen::~DeathScreen()
{
delete bRespawn;
delete bTitle;
}
void DeathScreen::init()
{
if (minecraft->useTouchscreen()) {
bRespawn = new Touch::TButton(1, "Respawn!");
bTitle = new Touch::TButton(2, "Main menu");
} else {
bRespawn = new Button(1, "Respawn!");
bTitle = new Button(2, "Main menu");
}
buttons.push_back(bRespawn);
buttons.push_back(bTitle);
tabButtons.push_back(bRespawn);
tabButtons.push_back(bTitle);
}
void DeathScreen::setupPositions()
{
bRespawn->width = bTitle->width = width / 4;
bRespawn->y = bTitle->y = height / 2;
bRespawn->x = width/2 - bRespawn->width - 10;
bTitle->x = width/2 + 10;
LOGI("xyz: %d, %d (%d, %d)\n", bTitle->x, bTitle->y, width, height);
}
void DeathScreen::tick() {
++_tick;
}
void DeathScreen::render( int xm, int ym, float a )
{
fillGradient(0, 0, width, height, 0x60500000, 0xa0803030);
glPushMatrix2();
glScalef2(2, 2, 2);
drawCenteredString(font, "You died!", width / 2 / 2, height / 8, 0xffffff);
glPopMatrix2();
if (_tick >= WAIT_TICKS)
Screen::render(xm, ym, a);
}
void DeathScreen::buttonClicked( Button* button )
{
if (_tick < WAIT_TICKS) return;
if (button == bRespawn) {
//RespawnPacket packet();
//minecraft->raknetInstance->send(packet);
minecraft->player->respawn();
//minecraft->raknetInstance->send();
minecraft->setScreen(NULL);
}
if (button == bTitle)
minecraft->leaveGame();
}

View File

@@ -0,0 +1,30 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__DeathScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__DeathScreen_H__
#include "../Screen.h"
class Button;
class DeathScreen: public Screen
{
public:
DeathScreen();
virtual ~DeathScreen();
void init();
void setupPositions();
void tick();
void render(int xm, int ym, float a);
void buttonClicked(Button* button);
private:
Button* bRespawn;
Button* bTitle;
bool _hasChosen;
int _tick;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__DeathScreen_H__*/

View File

@@ -0,0 +1,13 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__DialogDefinitions_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__DialogDefinitions_H__
class DialogDefinitions {
public:
static const int DIALOG_CREATE_NEW_WORLD = 1;
static const int DIALOG_NEW_CHAT_MESSAGE = 2;
static const int DIALOG_MAINMENU_OPTIONS = 3;
static const int DIALOG_RENAME_MP_WORLD = 4;
static const int DIALOG_DEMO_FEATURE_DISABLED = 98;
};
#endif /*#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__DialogDefinitions_H__*/

View File

@@ -0,0 +1,57 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__DisconnectionScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__DisconnectionScreen_H__
#include "../Screen.h"
#include "../Font.h"
#include "../components/Button.h"
#include "../../Minecraft.h"
#include <string>
class DisconnectionScreen: public Screen
{
typedef Screen super;
public:
DisconnectionScreen(const std::string& msg)
: _msg(msg),
_back(NULL)
{}
~DisconnectionScreen() {
delete _back;
}
void init() {
if (minecraft->useTouchscreen())
_back = new Touch::TButton(1, "Ok");
else
_back = new Button(1, "Ok");
buttons.push_back(_back);
tabButtons.push_back(_back);
_back->width = 128;
_back->x = (width - _back->width) / 2;
_back->y = height / 2;
}
void render( int xm, int ym, float a ) {
renderBackground();
super::render(xm, ym, a);
int center = (width - minecraft->font->width(_msg)) / 2;
minecraft->font->drawShadow(_msg, (float)center, (float)(height / 2 - 32), 0xffffffff);
}
void buttonClicked(Button* button) {
if (button->id == _back->id) {
minecraft->leaveGame();
}
}
bool isInGameScreen() { return false; }
private:
std::string _msg;
Button* _back;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__DisconnectionScreen_H__*/

View File

@@ -0,0 +1,555 @@
#include "FurnaceScreen.h"
#include "crafting/PaneCraftingScreen.h"
#include "../Screen.h"
#include "../components/NinePatch.h"
#include "../../Minecraft.h"
#include "../../player/LocalPlayer.h"
#include "../../renderer/Tesselator.h"
#include "../../renderer/entity/ItemRenderer.h"
#include "../../../world/item/Item.h"
#include "../../../world/item/crafting/Recipes.h"
#include "../../../world/item/ItemCategory.h"
#include "../../../world/entity/player/Inventory.h"
#include "../../../world/entity/item/ItemEntity.h"
#include "../../../world/level/Level.h"
#include "../../../world/item/DyePowderItem.h"
#include "../../../world/item/crafting/FurnaceRecipes.h"
#include "../../../world/level/tile/entity/FurnaceTileEntity.h"
#include "../../../locale/I18n.h"
#include "../../../util/StringUtils.h"
#include "../../../world/inventory/FurnaceMenu.h"
#include "../../../network/packet/ContainerSetSlotPacket.h"
#include "../../../network/RakNetInstance.h"
static int heldMs = -1;
static int percent = -1;
static const float MaxHoldMs = 500.0f;
static const int MinChargeMs = 200;
static void setIfNotSet(bool& ref, bool condition) {
ref = (ref || condition);
}
const int descFrameWidth = 100;
const int rgbActive = 0xfff0f0f0;
const int rgbInactive = 0xc0635558;
const int rgbInactiveShadow = 0xc0aaaaaa;
#ifdef __APPLE__
static const float BorderPixels = 4;
#ifdef DEMO_MODE
static const float BlockPixels = 22;
#else
static const float BlockPixels = 22;
#endif
#else
static const float BorderPixels = 4;
static const float BlockPixels = 24;
#endif
static const int ItemSize = (int)(BlockPixels + 2*BorderPixels);
static const int Bx = 10; // Border Frame width
static const int By = 6; // Border Frame height
FurnaceScreen::FurnaceScreen(Player* player, FurnaceTileEntity* furnace)
: super(new FurnaceMenu(furnace)), //@huge @attn
inventoryPane(NULL),
btnFuel(FurnaceTileEntity::SLOT_FUEL),
btnIngredient(FurnaceTileEntity::SLOT_INGREDIENT),
btnResult(FurnaceTileEntity::SLOT_RESULT),
btnClose(4, ""),
bHeader (5, "Furnace"),
guiBackground(NULL),
guiSlot(NULL),
guiSlotMarked(NULL),
guiSlotMarker(NULL),
guiPaneFrame(NULL),
player(player),
furnace(furnace),
selectedSlot(FurnaceTileEntity::SLOT_INGREDIENT),
doRecreatePane(false),
lastBurnTypeId(0),
descWidth(90)
//guiSlotItem(NULL),
//guiSlotItemSelected(NULL)
{
//LOGI("Creating FurnaceScreen with %p, %d\n", furnace, furnace->runningId);
}
FurnaceScreen::~FurnaceScreen() {
clearItems();
delete inventoryPane;
delete guiBackground;
delete guiSlot;
delete guiSlotMarked;
delete guiSlotMarker;
delete guiPaneFrame;
delete menu;
if (furnace->clientSideOnly)
delete furnace;
}
void FurnaceScreen::init() {
super::init();
//printf("-> %d\n", width/2);
ImageDef def;
def.name = "gui/spritesheet.png";
def.x = 0;
def.y = 1;
def.width = def.height = 18;
def.setSrc(IntRectangle(60, 0, 18, 18));
btnClose.setImageDef(def, true);
btnClose.scaleWhenPressed = false;
buttons.push_back(&bHeader);
buttons.push_back(&btnIngredient);
buttons.push_back(&btnFuel);
buttons.push_back(&btnResult);
buttons.push_back(&btnClose);
// GUI - nine patches
NinePatchFactory builder(minecraft->textures, "gui/spritesheet.png");
guiBackground = builder.createSymmetrical(IntRectangle(0, 0, 16, 16), 4, 4);
guiSlot = builder.createSymmetrical(IntRectangle(0, 32, 8, 8), 3, 3);
guiSlotMarked = builder.createSymmetrical(IntRectangle(0, 44, 8, 8), 3, 3);
guiSlotMarker = builder.createSymmetrical(IntRectangle(10, 42, 16, 16), 5, 5);
guiPaneFrame = builder.createSymmetrical(IntRectangle(28, 42, 4, 4), 1, 1)->setExcluded(1 << 4);
recheckRecipes();
}
void FurnaceScreen::setupPositions() {
// Left - Categories
bHeader.x = bHeader.y = 0;
bHeader.width = width;// - bDone.w;
btnClose.width = btnClose.height = 19;
btnClose.x = width - btnClose.width;
btnClose.y = 0;
// Inventory pane
const int maxWidth = width/2 - Bx - Bx;
const int InventoryColumns = maxWidth / ItemSize;
const int realWidth = InventoryColumns * ItemSize;
const int paneWidth = realWidth + Bx + Bx;
const int realBx = (paneWidth - realWidth) / 2;
inventoryPaneRect = IntRectangle(realBx,
#ifdef __APPLE__
26 + By - ((width==240)?1:0), realWidth, ((width==240)?1:0) + height-By-By-28);
#else
26 + By, realWidth, height-By-By-28);
#endif
// Right - Slots, description etc
{
int cx = (inventoryPaneRect.x + inventoryPaneRect.w);
int rightWidth = width - cx;
btnIngredient.width = btnFuel.width = btnResult.width = (int)guiSlot->getWidth();
btnIngredient.height = btnFuel.height = btnResult.height = (int)guiSlot->getHeight();
int space = rightWidth - (2 * btnFuel.width + 40);
int margin = space/2;
int bx0 = cx + margin;
int bx1 = width - margin - btnFuel.width;
btnIngredient.x = btnFuel.x = bx0;
descWidth = (float)Mth::Min(90, width - bx1 + 24 - 4);
int by = 36;// + (height-20) / 6;
btnIngredient.y = by;
btnFuel.y = by + 20 + btnFuel.height;
btnResult.x = bx1;
btnResult.y = (btnIngredient.y + btnFuel.y) / 2;
guiBackground->setSize((float)width, (float)height);
guiSlotMarker->setSize((float)btnFuel.width + 4, (float)btnFuel.height + 4);
recheckRecipes();
setupInventoryPane();
}
}
void FurnaceScreen::tick() {
if (inventoryPane)
inventoryPane->tick();
if (doRecreatePane) {
recheckRecipes();
setupInventoryPane();
doRecreatePane = false;
}
}
void FurnaceScreen::handleRenderPane(Touch::InventoryPane* pane, Tesselator& t, int xm, int ym, float a) {
if (pane) {
int ms, id;
pane->markerIndex = -1;
if (pane->queryHoldTime(&id, &ms)) {
heldMs = ms;
const ItemInstance* item = inventoryItems[id];
int count = (item && !item->isNull())? item->count : 0;
float maxHoldMs = item? 700 + 10 * item->count: MaxHoldMs;
if (count > 1 && canMoveToFurnace(id, item)) {
float share = (heldMs-MinChargeMs) / maxHoldMs;
pane->markerType = 1;//(heldMs >= MinChargeMs)? 1 : 0;
pane->markerIndex = id;
pane->markerShare = Mth::Max(share, 0.0f);
percent = (int)Mth::clamp(100.0f * share, 0.0f, 100.0f);
if (percent >= 100) {
addItem(pane, id);
}
}
}
pane->render(xm, ym, a);
guiPaneFrame->draw(t, (float)(pane->rect.x - 1), (float)(pane->rect.y - 1));
//LOGI("query-iv: %d, %d\n", gridId, heldMs);
}
}
void FurnaceScreen::render(int xm, int ym, float a) {
const int N = 5;
static StopwatchNLast r(N);
//renderBackground();
updateResult(furnace->getItem(FurnaceTileEntity::SLOT_INGREDIENT));
Tesselator& t = Tesselator::instance;
guiBackground->draw(t, 0, 0);
glEnable2(GL_ALPHA_TEST);
// Buttons (Left side + crafting)
super::render(xm, ym, a);
handleRenderPane(inventoryPane, t, xm, ym, a);
t.colorABGR(0xffffffff);
drawSlotItemAt(t, furnace->getItem(btnIngredient.id), btnIngredient.x, btnIngredient.y, btnIngredient.id == selectedSlot);
drawSlotItemAt(t, furnace->getItem(btnFuel.id), btnFuel.x, btnFuel.y, btnFuel.id == selectedSlot);
const ItemInstance* resultSlotItem = furnace->getItem(btnResult.id);
drawSlotItemAt(t, resultSlotItem, btnResult.x, btnResult.y, btnResult.id == selectedSlot);
if (!burnResult.isNull()) {
if (!resultSlotItem || resultSlotItem->isNull()) {
glEnable2(GL_BLEND);
t.beginOverride();
t.colorABGR(0x33ffffff);
t.noColor();
ItemRenderer::renderGuiItem(minecraft->font, minecraft->textures, &burnResult, (float)(btnResult.x + 7), (float)(btnResult.y + 8), true);
t.endOverrideAndDraw();
glDisable2(GL_BLEND);
}
minecraft->font->drawWordWrap(currentItemDesc, (float)btnResult.x - 24, (float)(btnResult.y + btnResult.height + 6), descWidth, rgbActive);
}
minecraft->textures->loadAndBindTexture("gui/spritesheet.png");
int yy = btnResult.y + 8;
int fpx = furnace->getLitProgress(14) + 2;
int xx0 = btnIngredient.x + 8;
blit(xx0, yy, 80, 40, 16, 16, 32, 32);
blit(xx0, yy + 16 - fpx, 112, 40 + 32-fpx-fpx, 16, fpx, 32, fpx+fpx);
int bpx = furnace->getBurnProgress(24);
int xx1 = btnIngredient.x + 40;
blit(xx1, yy, 144, 40, 24, 16, 48, 32);
blit(xx1, yy, 144, 72, bpx, 16, bpx+bpx, 32);
}
void FurnaceScreen::buttonClicked(Button* button) {
int slot = button->id;
if (button == &btnClose) {
minecraft->player->closeContainer();
}
if (slot >= FurnaceTileEntity::SLOT_INGREDIENT
&& slot <= FurnaceTileEntity::SLOT_RESULT) {
// Can't highlight the Result slot
int oldSlot = selectedSlot;
if (slot != FurnaceTileEntity::SLOT_RESULT)
selectedSlot = slot;
if (oldSlot == selectedSlot)
takeAndClearSlot(slot);
}
}
static bool sortCanCraftPredicate(const CItem* a, const CItem* b) {
//if (a->maxBuildCount == 0 && b->maxBuildCount > 0) return false;
//if (b->maxBuildCount == 0 && a->maxBuildCount > 0) return true;
return a->sortText < b->sortText;
}
void FurnaceScreen::recheckRecipes()
{
clearItems();
Stopwatch w;
w.start();
const FurnaceRecipes* recipes = FurnaceRecipes::getInstance();
ItemPack ip;
// Check for fuel, and items to burn
if (minecraft->player && minecraft->player->inventory) {
Inventory* inv = (minecraft->player)->inventory;
for (int i = Inventory::MAX_SELECTION_SIZE; i < inv->getContainerSize(); ++i) {
if (ItemInstance* item = inv->getItem(i)) {
// Fuel material
if (FurnaceTileEntity::isFuel(*item)) {
CItem* ci = new CItem(*item, NULL, "");//item->getName());
//LOGI("Adding fuel: %s\n", item->getName());
listFuel.push_back(ci);
}
// Ingredient/burn material
if (recipes->isFurnaceItem(item->id)) {
CItem* ci = new CItem(*item, NULL, "");//item->getName());
//LOGI("Adding item to burn: %s\n", item->getName());
listIngredient.push_back(ci);
}
//ip.add(ItemPack::getIdForItemInstance(item), item->count);
}
}
}
ip.print();
w.stop();
w.printEvery(1, "> craft ");
updateItems();
//std::stable_sort(_categories[c].begin(), _categories[c].end(), sortCanCraftPredicate);
}
bool FurnaceScreen::addItem(const Touch::InventoryPane* forPane, int itemIndex) {
//LOGI("items.size, index: %d, %d\n", inventoryItems.size(), itemIndex);
const ItemInstance* item = inventoryItems[itemIndex];
if (!item || item->isNull()) return false;
setIfNotSet(doRecreatePane, handleAddItem(selectedSlot, item));
if (doRecreatePane) {
int slot = inventorySlots[itemIndex];
if (player->inventory->getItem(slot)) {
// fix: if we deplete a slot we didn't click on (but had same type),
// we need to NULLify the slot that actually was depleted
for (unsigned int i = 0; i < inventorySlots.size(); ++i) {
slot = inventorySlots[i];
if (!player->inventory->getItem(slot)) {
LOGI("Changed! removing slot %d (was: %d)\n", i, itemIndex);
itemIndex = i;
break;
}
}
}
inventoryItems[itemIndex] = NULL;
}
//LOGI("Pressed button: %d\n", itemIndexInCurrentCategory);
return true;
}
bool FurnaceScreen::isAllowed( int slot )
{ //LOGI("items.size, index: %d, %d\n", inventoryItems.size(), slot);
if (slot >= (int)inventoryItems.size()) return false;
if (!inventoryItems[slot]) return false;
const ItemInstance& item = *inventoryItems[slot];
if (selectedSlot == btnFuel.id)
return (FurnaceTileEntity::getBurnDuration(item) > 0);
else
if (selectedSlot == btnIngredient.id)
return !FurnaceRecipes::getInstance()->getResult(item.id).isNull();
return false;
}
bool FurnaceScreen::renderGameBehind()
{
return false;
}
std::vector<const ItemInstance*> FurnaceScreen::getItems( const Touch::InventoryPane* forPane )
{
return inventoryItems;
}
void FurnaceScreen::clearItems()
{
for (unsigned int i = 0; i < listFuel.size(); ++i) delete listFuel[i];
for (unsigned int i = 0; i < listIngredient.size(); ++i) delete listIngredient[i];
listFuel.clear();
listIngredient.clear();
}
void FurnaceScreen::updateItems() {
inventoryItems.clear();
inventorySlots.clear();
ItemList all(listFuel.begin(), listFuel.end());
all.insert(all.end(), listIngredient.begin(), listIngredient.end());
for (int i = Inventory::MAX_SELECTION_SIZE; i < minecraft->player->inventory->getContainerSize(); ++i) {
ItemInstance* item = minecraft->player->inventory->getItem(i);
if (!item) continue;
//LOGI("ItemInstance (%p) Id/aux/count: %d, %d, %d\n", item, item->id, item->getAuxValue(), item->count);
bool added = false;
for (unsigned int j = 0; j < listFuel.size(); ++j) {
if (ItemInstance::matches(item, &listFuel[j]->item)) {
inventorySlots.push_back(i);
inventoryItems.push_back(item);
added = true;
break;
}
}
if (added) continue;
for (unsigned int j = 0; j < listIngredient.size(); ++j) {
if (ItemInstance::matches(item, &listIngredient[j]->item)) {
inventorySlots.push_back(i);
inventoryItems.push_back(item);
added = true;
break;
}
}
}
}
bool FurnaceScreen::canMoveToFurnace(int inventorySlot, const ItemInstance* item) {
if (!isAllowed(inventorySlot)) return false;
ItemInstance* jitem = furnace->getItem(selectedSlot);
if (!jitem || jitem->isNull()) return true;
if (ItemInstance::isStackable(item, jitem) && jitem->count < jitem->getMaxStackSize())
return true;
return false;
}
void FurnaceScreen::updateResult( const ItemInstance* item )
{
const ItemInstance* result = furnace->getItem(FurnaceTileEntity::SLOT_RESULT);
if (!result->isNull()) {
int id = result->id;
if (id == lastBurnTypeId) return;
currentItemDesc = I18n::getDescriptionString(*result);
lastBurnTypeId = id;
this->burnResult = *result;
} else {
int id = (item? item->id : 0);
if (id == lastBurnTypeId) return;
ItemInstance burnResult = FurnaceRecipes::getInstance()->getResult(id);
if (!burnResult.isNull())
currentItemDesc = I18n::getDescriptionString(burnResult);
else
currentItemDesc = "";
lastBurnTypeId = id;
this->burnResult = burnResult;
}
}
void FurnaceScreen::setupInventoryPane()
{
// IntRectangle(0, 0, 100, 100)
if (inventoryPane) delete inventoryPane;
inventoryPane = new Touch::InventoryPane(this, minecraft, inventoryPaneRect, inventoryPaneRect.w, BorderPixels, inventoryItems.size(), ItemSize, (int)BorderPixels);
inventoryPane->fillMarginX = 0;
inventoryPane->fillMarginY = 0;
guiPaneFrame->setSize((float)inventoryPaneRect.w + 2, (float)inventoryPaneRect.h + 2);
//LOGI("Creating new pane: %d %p\n", inventoryItems.size(), inventoryPane);
}
void FurnaceScreen::drawSlotItemAt( Tesselator& t, const ItemInstance* item, int x, int y, bool selected)
{
float xx = (float)x;
float yy = (float)y;
(selected? guiSlot/*Marked*/ : guiSlot)->draw(t, xx, yy);
if (selected)
guiSlotMarker->draw(t, xx - 2, yy - 2);
if (item && !item->isNull()) {
ItemRenderer::renderGuiItem(minecraft->font, minecraft->textures, item, xx + 7, yy + 8, true);
minecraft->gui.renderSlotText(item, xx + 3, yy + 3, true, true);
}
}
ItemInstance FurnaceScreen::moveOver(const ItemInstance* item, int maxCount) {
int wantedCount = item->count * percent / 100;
if (!wantedCount || heldMs < MinChargeMs)
wantedCount = 1;
wantedCount = Mth::Min(wantedCount, maxCount);
ItemInstance removed(item->id, wantedCount, item->getAuxValue());
int oldSize = minecraft->player->inventory->getNumEmptySlots();
if (minecraft->player->inventory->removeResource(removed)) {
int newSize = minecraft->player->inventory->getNumEmptySlots();
setIfNotSet(doRecreatePane, newSize != oldSize);
return removed;
}
return ItemInstance();
}
void FurnaceScreen::takeAndClearSlot( int slot )
{
//if (selectedSlot == btnBurn.id && !furnace->isSlotEmpty(btnBurn.id))
ItemInstance oldItem = *furnace->getItem(slot);
ItemInstance blank;
furnace->setItem(slot, &blank);
if (minecraft->level->isClientSide) {
ContainerSetSlotPacket p(menu->containerId, slot, blank);
minecraft->raknetInstance->send(p);
}
int oldSize = minecraft->player->inventory->getNumEmptySlots();
if (!minecraft->player->inventory->add(&oldItem))
minecraft->player->drop(new ItemInstance(oldItem), false);
int newSize = minecraft->player->inventory->getNumEmptySlots();
setIfNotSet(doRecreatePane, newSize != oldSize);
}
bool FurnaceScreen::handleAddItem( int slot, const ItemInstance* item )
{
ItemInstance* furnaceItem = furnace->getItem(slot);
int oldSize = minecraft->player->inventory->getNumEmptySlots();
if (item->id == furnaceItem->id) {
// If stackable, stack them! Else deny the addition
const int maxMovedCount = furnaceItem->getMaxStackSize() - furnaceItem->count;
if (maxMovedCount <= 0)
return false;
ItemInstance added = moveOver(item, maxMovedCount);
furnaceItem->count += added.count;
} else {
if (!furnace->isSlotEmpty(slot))
return false;//takeAndClearSlot(slot);
ItemInstance moved = moveOver(item, item->getMaxStackSize());
player->containerMenu->setSlot(slot, &moved);
}
if (minecraft->level->isClientSide) {
ContainerSetSlotPacket p(menu->containerId, slot, *furnaceItem);
minecraft->raknetInstance->send(p);
}
int newSize = minecraft->player->inventory->getNumEmptySlots();
return (newSize != oldSize);
}

View File

@@ -0,0 +1,84 @@
#ifndef _FURNACESCREEN_H__
#define _FURNACESCREEN_H__
#include "BaseContainerScreen.h"
#include "../components/InventoryPane.h"
#include "../components/Button.h"
class Font;
class CItem;
class Textures;
class NinePatchLayer;
class Tesselator;
class FurnaceScreen: public BaseContainerScreen,
public Touch::IInventoryPaneCallback
{
typedef BaseContainerScreen super;
typedef std::vector<CItem*> ItemList;
public:
FurnaceScreen(Player* player, FurnaceTileEntity* furnace);
~FurnaceScreen();
void init();
void setupPositions();
void tick();
void render(int xm, int ym, float a);
bool renderGameBehind();
void buttonClicked(Button* button);
// IInventoryPaneCallback
bool addItem(const Touch::InventoryPane* pane, int itemId);
bool isAllowed( int slot );
std::vector<const ItemInstance*> getItems( const Touch::InventoryPane* forPane );
private:
//void addItem(Recipe* recipe);
void recheckRecipes();
void clearItems();
void updateResult(const ItemInstance* item);
void setupInventoryPane();
void updateItems();
void drawSlotItemAt(Tesselator& t, const ItemInstance* item, int x, int y, bool selected);
ItemInstance moveOver(const ItemInstance* item, int maxCount);
void takeAndClearSlot( int slot );
bool handleAddItem( int slot, const ItemInstance* item );
void handleRenderPane(Touch::InventoryPane* pane, Tesselator& t, int xm, int ym, float a);
bool canMoveToFurnace(int inventorySlot, const ItemInstance* item);
ItemList _items;
std::string currentItemDesc;
ItemInstance burnResult;
float descWidth;
ImageButton btnClose;
BlankButton btnIngredient;
BlankButton btnFuel;
BlankButton btnResult;
Touch::THeader bHeader;
Touch::InventoryPane* inventoryPane;
IntRectangle inventoryPaneRect;
ItemList listFuel;
ItemList listIngredient;
std::vector<int> inventorySlots;
std::vector<const ItemInstance*> inventoryItems;
bool doRecreatePane;
int selectedSlot;
int lastBurnTypeId;
// GUI elements such as 9-Patches
NinePatchLayer* guiBackground;
NinePatchLayer* guiSlot;
NinePatchLayer* guiSlotMarked;
NinePatchLayer* guiSlotMarker;
NinePatchLayer* guiPaneFrame;
Player* player;
FurnaceTileEntity* furnace;
};
#endif /*_FURNACESCREEN_H__*/

View File

@@ -0,0 +1,49 @@
#include "InBedScreen.h"
#include "ScreenChooser.h"
#include "../components/Button.h"
#include "../../Minecraft.h"
#include "../../player/LocalPlayer.h"
#include "../../../platform/time.h"
static const int WAIT_TICKS = 30;
InBedScreen::InBedScreen()
: bWakeUp(0)
{
}
InBedScreen::~InBedScreen() {
delete bWakeUp;
}
void InBedScreen::init() {
if (minecraft->useTouchscreen()) {
bWakeUp = new Touch::TButton(1, "Leave Bed");
} else {
bWakeUp = new Button(1, "Leave Bed");
}
buttons.push_back(bWakeUp);
tabButtons.push_back(bWakeUp);
}
void InBedScreen::setupPositions() {
bWakeUp->width = width / 2;
bWakeUp->height = int(height * 0.2f);
bWakeUp->y = height - int(bWakeUp->height * 1.5);
bWakeUp->x = width/2 - bWakeUp->width/2;
}
void InBedScreen::render( int xm, int ym, float a ) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Screen::render(xm, ym, a);
glDisable(GL_BLEND);
}
void InBedScreen::buttonClicked( Button* button ) {
if (button == bWakeUp) {
minecraft->player->stopSleepInBed(true, true, true);
minecraft->setScreen(NULL);
}
}

View File

@@ -0,0 +1,26 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__InBedScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__InBedScreen_H__
#include "../Screen.h"
class Button;
class InBedScreen: public Screen
{
public:
InBedScreen();
virtual ~InBedScreen();
void init();
void setupPositions();
void render(int xm, int ym, float a);
void buttonClicked(Button* button);
private:
Button* bWakeUp;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__InBedScreen_H__*/

View File

@@ -0,0 +1,322 @@
#include "IngameBlockSelectionScreen.h"
#include "../../renderer/TileRenderer.h"
#include "../../player/LocalPlayer.h"
#include "../../renderer/gles.h"
#include "../../Minecraft.h"
#include "../../sound/SoundEngine.h"
#include "../../../world/entity/player/Inventory.h"
#include "../../../platform/input/Mouse.h"
#include "../Gui.h"
#include "../../renderer/Textures.h"
#include "../../gamemode/GameMode.h"
#include "ArmorScreen.h"
#include "../components/Button.h"
#if defined(__APPLE__)
static const std::string demoVersionString("Not available in the Lite version");
#else
static const std::string demoVersionString("Not available in the demo version");
#endif
IngameBlockSelectionScreen::IngameBlockSelectionScreen()
: selectedItem(0),
_area(0,0,0,0),
_pendingQuit(false),
InventoryRows(1),
InventoryCols(1),
InventorySize(1),
bArmor(1, "Armor")
{
}
void IngameBlockSelectionScreen::init()
{
Inventory* inventory = minecraft->player->inventory;
InventoryCols = minecraft->isCreativeMode()? 13 : 9;
InventorySize = inventory->getContainerSize() - Inventory::MAX_SELECTION_SIZE;
InventoryRows = 1 + (InventorySize - 1) / InventoryCols;
_area = RectangleArea( (float)getSlotPosX(0) - 4,
(float)getSlotPosY(0) - 4,
(float)getSlotPosX(InventoryCols) + 4,
(float)getSlotPosY(InventoryRows) + 4);
ItemInstance* selected = inventory->getSelected();
if (!selected || selected->isNull()) {
selectedItem = 0;
return;
}
for (int i = Inventory::MAX_SELECTION_SIZE; i < InventorySize; i++) {
if (selected == minecraft->player->inventory->getItem(i))
{
selectedItem = i - Inventory::MAX_SELECTION_SIZE;
break;
}
}
if (!isAllowed(selectedItem))
selectedItem = 0;
if (!minecraft->isCreativeMode()) {
bArmor.width = 42;
bArmor.x = 0;
bArmor.y = height - bArmor.height;
buttons.push_back(&bArmor);
}
}
void IngameBlockSelectionScreen::removed()
{
minecraft->gui.inventoryUpdated();
}
void IngameBlockSelectionScreen::renderSlots()
{
//static Stopwatch w;
//w.start();
glColor4f2(1, 1, 1, 1);
blitOffset = -90;
//glEnable2(GL_RESCALE_NORMAL);
//glPushMatrix2();
//glRotatef2(180, 1, 0, 0);
//Lighting::turnOn();
//glPopMatrix2();
minecraft->textures->loadAndBindTexture("gui/gui.png");
for (int r = 0; r < InventoryRows; r++)
{
int x = getSlotPosX(0) - 3;
int y = getSlotPosY(r) - 3;
if (InventoryCols == 9) {
blit(x, y, 0, 0, 182, 22);
} else {
// first 8 slots
blit(x, y, 0, 0, 182-20, 22);
// last k slots
const int k = 5;
const int w = k * 20;
blit(x + 162, y, 182-w, 0, w, 22);
}
}
if (selectedItem >= 0)
{
int x = getSlotPosX(selectedItem % InventoryCols) - 4;// width / 2 - 182 / 2 - 1 + () * 20;
int y = getSlotPosY(selectedItem / InventoryCols) - 4;// height - 22 * 3 - 1 - (selectedItem / InventoryCols) * 22;
blit(x, y, 0, 22, 24, 22);
}
for (int r = 0; r < InventoryRows; r++)
{
int y = getSlotPosY(r);
for (int i = 0; i < InventoryCols; i++) {
int x = getSlotPosX(i);
renderSlot(r * InventoryCols + i + Inventory::MAX_SELECTION_SIZE, x, y, 0);
}
}
//w.stop();
//w.printEvery(1000, "render-blocksel");
//glDisable2(GL_RESCALE_NORMAL);
//Lighting::turnOn();
}
int IngameBlockSelectionScreen::getSlotPosX(int slotX) {
return width / 2 - InventoryCols * 10 + slotX * 20 + 2;
}
int IngameBlockSelectionScreen::getSlotPosY(int slotY) {
//return height - 63 - 22 * (3 - slotY);
int yy = InventoryCols==9? 8 : 3;
return yy + slotY * getSlotHeight();
}
//int IngameBlockSelectionScreen::getLinearSlotId(int x, int y) {
// return
//}
#include "../../../world/item/ItemInstance.h"
#include "../../renderer/entity/ItemRenderer.h"
void IngameBlockSelectionScreen::renderSlot(int slot, int x, int y, float a)
{
ItemInstance* item = minecraft->player->inventory->getItem(slot);
if (!item) return;
ItemRenderer::renderGuiItem(minecraft->font, minecraft->textures, item, (float)x, (float)y, true);
if (minecraft->gameMode->isCreativeType()) return;
if (!isAllowed(slot - Inventory::MAX_SELECTION_SIZE)) return;
glPushMatrix2();
glScalef2(Gui::InvGuiScale + Gui::InvGuiScale, Gui::InvGuiScale + Gui::InvGuiScale, 1);
const float k = 0.5f * Gui::GuiScale;
minecraft->gui.renderSlotText(item, k*x, k*y, true, true);
glPopMatrix2();
}
void IngameBlockSelectionScreen::keyPressed(int eventKey)
{
int selX = selectedItem % InventoryCols;
int selY = selectedItem / InventoryCols;
int tmpSelectedSlot = selectedItem;
Options& o = minecraft->options;
if (eventKey == o.keyLeft.key && selX > 0)
{
tmpSelectedSlot -= 1;
}
else if (eventKey == o.keyRight.key && selX < (InventoryCols - 1))
{
tmpSelectedSlot += 1;
}
else if (eventKey == o.keyDown.key && selY < (InventoryRows - 1))
{
tmpSelectedSlot += InventoryCols;
}
else if (eventKey == o.keyUp.key && selY > 0)
{
tmpSelectedSlot -= InventoryCols;
}
if (isAllowed(tmpSelectedSlot))
selectedItem = tmpSelectedSlot;
if (eventKey == o.keyMenuOk.key)
selectSlotAndClose();
#ifdef RPI
if (eventKey == o.keyMenuCancel.key
|| eventKey == Keyboard::KEY_ESCAPE)
minecraft->setScreen(NULL);
#else
if (eventKey == o.keyMenuCancel.key)
minecraft->setScreen(NULL);
#endif
}
int IngameBlockSelectionScreen::getSelectedSlot(int x, int y)
{
int left = width / 2 - InventoryCols * 10;
int top = -4 + getSlotPosY(0);
if (x >= left && y >= top)
{
int xSlot = (x - left) / 20;
if (xSlot < InventoryCols) {
int row = ((y-top) / getSlotHeight());
return row * InventoryCols + xSlot;
}
}
return -1;
}
void IngameBlockSelectionScreen::mouseClicked(int x, int y, int buttonNum)
{
if (buttonNum == MouseAction::ACTION_LEFT) {
int slot = getSelectedSlot(x, y);
if (isAllowed(slot))
{
selectedItem = slot;
//minecraft->soundEngine->playUI("random.click", 1, 1);
} else {
_pendingQuit = !_area.isInside((float)x, (float)y)
&& !bArmor.isInside(x, y);
}
}
if (!_pendingQuit)
super::mouseClicked(x, y, buttonNum);
}
void IngameBlockSelectionScreen::mouseReleased(int x, int y, int buttonNum)
{
if (buttonNum == MouseAction::ACTION_LEFT) {
int slot = getSelectedSlot(x, y);
if (isAllowed(slot) && slot == selectedItem)
{
selectSlotAndClose();
} else {
if (_pendingQuit && !_area.isInside((float)x, (float)y))
minecraft->setScreen(NULL);
}
}
if (!_pendingQuit)
super::mouseReleased(x, y, buttonNum);
}
void IngameBlockSelectionScreen::selectSlotAndClose()
{
Inventory* inventory = minecraft->player->inventory;
// Flash the selected gui item
//inventory->moveToSelectedSlot(selectedItem + Inventory::MAX_SELECTION_SIZE, true);
inventory->moveToSelectionSlot(0, selectedItem + Inventory::MAX_SELECTION_SIZE, true);
inventory->selectSlot(0);
minecraft->gui.flashSlot(inventory->selected);
minecraft->soundEngine->playUI("random.click", 1, 1);
minecraft->setScreen(NULL);
}
void IngameBlockSelectionScreen::render( int xm, int ym, float a )
{
glDisable2(GL_DEPTH_TEST);
fill(0, 0, width, height, (0x80) << 24);
glEnable2(GL_BLEND);
glDisable2(GL_ALPHA_TEST);
glEnable2(GL_BLEND);
glBlendFunc2(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
renderSlots();
renderDemoOverlay();
glEnable2(GL_ALPHA_TEST);
glDisable2(GL_BLEND);
glEnable2(GL_DEPTH_TEST);
Screen::render(xm, ym, a);
}
void IngameBlockSelectionScreen::renderDemoOverlay() {
#ifdef DEMO_MODE
fill( getSlotPosX(0) - 3, getSlotPosY(3) - 3,
getSlotPosX(InventoryCols) - 3, getSlotPosY(InventoryRows) - 3, 0xa0 << 24);
const int centerX = (getSlotPosX(4) + getSlotPosX(5)) / 2;
const int centerY = (getSlotPosY(3) + getSlotPosY(InventoryRows-1)) / 2 + 5;
drawCenteredString(minecraft->font, demoVersionString, centerX, centerY, 0xffffffff);
#endif /*DEMO_MODE*/
}
bool IngameBlockSelectionScreen::isAllowed(int slot) {
if (slot < 0 || slot >= InventorySize)
return false;
#ifdef DEMO_MODE
return slot < (minecraft->isCreativeMode()? 28 : 27);
#endif /*DEMO_MODE*/
return true;
}
int IngameBlockSelectionScreen::getSlotHeight() {
return InventoryCols==9? 22 : 20;
}
void IngameBlockSelectionScreen::buttonClicked( Button* button )
{
if (button == &bArmor) {
minecraft->setScreen(new ArmorScreen());
}
super::buttonClicked(button);
}

View File

@@ -0,0 +1,56 @@
#ifndef _MINECRAFT_INGAMEBLOCKSELECTIONSCREEN_H_
#define _MINECRAFT_INGAMEBLOCKSELECTIONSCREEN_H_
#include "../Screen.h"
#include "../../player/input/touchscreen/TouchAreaModel.h"
#include "../components/Button.h"
class IngameBlockSelectionScreen : public Screen
{
typedef Screen super;
public:
IngameBlockSelectionScreen();
virtual ~IngameBlockSelectionScreen() {}
virtual void init();
virtual void removed();
void render(int xm, int ym, float a);
protected:
virtual void mouseClicked(int x, int y, int buttonNum);
virtual void mouseReleased(int x, int y, int buttonNum);
virtual void buttonClicked(Button* button);
virtual void keyPressed(int eventKey);
private:
void renderSlots();
void renderSlot(int slot, int x, int y, float a);
void renderDemoOverlay();
int getSelectedSlot(int x, int y);
void selectSlotAndClose();
//int getLinearSlotId(int x, int y);
int getSlotPosX(int slotX);
int getSlotPosY(int slotY);
int getSlotHeight();
bool isAllowed(int slot);
private:
int InventoryCols;
int InventoryRows;
int InventorySize;
int selectedItem;
bool _pendingQuit;
Button bArmor;
RectangleArea _area;
};
#endif

View File

@@ -0,0 +1,107 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__InvalidLicenseScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__InvalidLicenseScreen_H__
#include "../Screen.h"
#include "../components/Button.h"
#include "../../Minecraft.h"
#include "../../../LicenseCodes.h"
class InvalidLicenseScreen: public Screen
{
public:
InvalidLicenseScreen(int id, bool hasBuyButton)
: _id(id),
_hasBuyButton(hasBuyButton),
_baseY(0),
bOk(0),
bBuy(0)
{
}
virtual ~InvalidLicenseScreen() {
delete bOk;
delete bBuy;
}
void init() {
if (minecraft->useTouchscreen()) {
bOk = new Touch::TButton(1, "Ok");
bBuy = new Touch::TButton(2, "Buy");
} else {
bOk = new Button(1, "Ok");
bBuy = new Button(2, "Buy");
}
if (_hasBuyButton)
bOk->msg = "Quit";
if (!LicenseCodes::isOk(_id)) {
char buf[20] = {0};
sprintf(buf, "%d", _id);
desc1 = "License verification failed (error ";
desc1 += buf;
desc1 += ")";
desc2 = "Try again later.";
hint = "You need to be connected to the internet\n";
hint += "once while you start the game.";
}
buttons.push_back(bOk);
tabButtons.push_back(bOk);
if (_hasBuyButton) {
buttons.push_back(bBuy);
tabButtons.push_back(bBuy);
}
}
void setupPositions() {
_baseY = height/5 + 6;
//if (_hasBuyButton)
_baseY -= 24;
bOk->width = bBuy->width = 200;
bOk->x = bBuy->x = (width - bOk->width) / 2;
bBuy->y = _baseY + 84;
bOk->y = bBuy->y + bBuy->height + 4;
if (!_hasBuyButton)
bOk->y -= 24;
}
void tick() {}
//void keyPressed(int eventKey) {}
void render(int xm, int ym, float a) {
renderDirtBackground(0);
drawCenteredString(minecraft->font, desc1, width/2, _baseY, 0xffffff);
drawCenteredString(minecraft->font, desc2, width/2, _baseY + 24, 0xffffff);
drawCenteredString(minecraft->font, hint, width/2, _baseY + 60, 0xffffff);
Screen::render(xm, ym, a);
}
void buttonClicked(Button* button) {
if (button->id == bOk->id) {
minecraft->quit();
}
if (button->id == bBuy->id) {
minecraft->platform()->buyGame();
}
};
private:
int _id;
std::string desc1;
std::string desc2;
std::string hint;
Button* bOk;
Button* bBuy;
bool _hasBuyButton;
int _baseY;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__InvalidLicenseScreen_H__*/

View File

@@ -0,0 +1,167 @@
#include "JoinGameScreen.h"
#include "StartMenuScreen.h"
#include "ProgressScreen.h"
#include "../Font.h"
#include "../../../network/RakNetInstance.h"
JoinGameScreen::JoinGameScreen()
: bJoin( 2, "Join Game"),
bBack( 3, "Back"),
gamesList(NULL)
{
bJoin.active = false;
//gamesList->yInertia = 0.5f;
}
JoinGameScreen::~JoinGameScreen()
{
delete gamesList;
}
void JoinGameScreen::buttonClicked(Button* button)
{
if (button->id == bJoin.id)
{
if (isIndexValid(gamesList->selectedItem))
{
PingedCompatibleServer selectedServer = gamesList->copiedServerList[gamesList->selectedItem];
minecraft->joinMultiplayer(selectedServer);
{
bJoin.active = false;
bBack.active = false;
minecraft->setScreen(new ProgressScreen());
}
}
//minecraft->locateMultiplayer();
//minecraft->setScreen(new JoinGameScreen());
}
if (button->id == bBack.id)
{
minecraft->cancelLocateMultiplayer();
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
}
}
bool JoinGameScreen::handleBackEvent(bool isDown)
{
if (!isDown)
{
minecraft->cancelLocateMultiplayer();
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
}
return true;
}
bool JoinGameScreen::isIndexValid( int index )
{
return gamesList && index >= 0 && index < gamesList->getNumberOfItems();
}
void JoinGameScreen::tick()
{
const ServerList& orgServerList = minecraft->raknetInstance->getServerList();
ServerList serverList;
for (unsigned int i = 0; i < orgServerList.size(); ++i)
if (orgServerList[i].name.GetLength() > 0)
serverList.push_back(orgServerList[i]);
if (serverList.size() != gamesList->copiedServerList.size())
{
// copy the currently selected item
PingedCompatibleServer selectedServer;
bool hasSelection = false;
if (isIndexValid(gamesList->selectedItem))
{
selectedServer = gamesList->copiedServerList[gamesList->selectedItem];
hasSelection = true;
}
gamesList->copiedServerList = serverList;
gamesList->selectItem(-1, false);
// re-select previous item if it still exists
if (hasSelection)
{
for (unsigned int i = 0; i < gamesList->copiedServerList.size(); i++)
{
if (gamesList->copiedServerList[i].address == selectedServer.address)
{
gamesList->selectItem(i, false);
break;
}
}
}
} else {
for (int i = (int)gamesList->copiedServerList.size()-1; i >= 0 ; --i) {
for (int j = 0; j < (int) serverList.size(); ++j)
if (serverList[j].address == gamesList->copiedServerList[i].address)
gamesList->copiedServerList[i].name = serverList[j].name;
}
}
bJoin.active = isIndexValid(gamesList->selectedItem);
}
void JoinGameScreen::init()
{
buttons.push_back(&bJoin);
buttons.push_back(&bBack);
minecraft->raknetInstance->clearServerList();
gamesList = new AvailableGamesList(minecraft, width, height);
#ifdef ANDROID
tabButtons.push_back(&bJoin);
tabButtons.push_back(&bBack);
#endif
}
void JoinGameScreen::setupPositions() {
int yBase = height - 26;
//#ifdef ANDROID
bJoin.y = yBase;
bBack.y = yBase;
bBack.width = bJoin.width = 120;
//#endif
// Center buttons
bJoin.x = width / 2 - 4 - bJoin.width;
bBack.x = width / 2 + 4;
}
void JoinGameScreen::render( int xm, int ym, float a )
{
bool hasNetwork = minecraft->platform()->isNetworkEnabled(true);
#ifdef WIN32
hasNetwork = hasNetwork && !GetAsyncKeyState(VK_TAB);
#endif
renderBackground();
if (hasNetwork) gamesList->render(xm, ym, a);
Screen::render(xm, ym, a);
if (hasNetwork) {
#ifdef RPI
std::string s = "Scanning for Local Network Games...";
#else
std::string s = "Scanning for WiFi Games...";
#endif
drawCenteredString(minecraft->font, s, width / 2, 8, 0xffffffff);
const int textWidth = minecraft->font->width(s);
const int spinnerX = width/2 + textWidth / 2 + 6;
static const char* spinnerTexts[] = {"-", "\\", "|", "/"};
int n = ((int)(5.5f * getTimeS()) % 4);
drawCenteredString(minecraft->font, spinnerTexts[n], spinnerX, 8, 0xffffffff);
} else {
std::string s = "WiFi is disabled";
const int yy = height / 2 - 8;
drawCenteredString(minecraft->font, s, width / 2, yy, 0xffffffff);
}
}
bool JoinGameScreen::isInGameScreen() { return false; }

View File

@@ -0,0 +1,71 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__JoinGameScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__JoinGameScreen_H__
#include "../Screen.h"
#include "../components/Button.h"
#include "../components/SmallButton.h"
#include "../components/ScrolledSelectionList.h"
#include "../../Minecraft.h"
#include "../../../network/RakNetInstance.h"
class JoinGameScreen;
class AvailableGamesList : public ScrolledSelectionList
{
int selectedItem;
ServerList copiedServerList;
friend class JoinGameScreen;
public:
AvailableGamesList(Minecraft* _minecraft, int _width, int _height)
: ScrolledSelectionList(_minecraft, _width, _height, 24, _height - 30, 28)
{
}
protected:
virtual int getNumberOfItems() { return (int)copiedServerList.size(); }
virtual void selectItem(int item, bool doubleClick) { selectedItem = item; }
virtual bool isSelectedItem(int item) { return item == selectedItem; }
virtual void renderBackground() {}
virtual void renderItem(int i, int x, int y, int h, Tesselator& t)
{
const PingedCompatibleServer& s = copiedServerList[i];
unsigned int color = s.isSpecial? 0xff00b0 : 0xffffa0;
drawString(minecraft->font, s.name.C_String(), x, y + 2, color);
drawString(minecraft->font, s.address.ToString(false), x, y + 16, 0xffffa0);
}
};
class JoinGameScreen: public Screen
{
public:
JoinGameScreen();
virtual ~JoinGameScreen();
void init();
void setupPositions();
virtual bool handleBackEvent(bool isDown);
virtual bool isIndexValid(int index);
virtual void tick();
void render(int xm, int ym, float a);
void buttonClicked(Button* button);
bool isInGameScreen();
private:
Button bJoin;
Button bBack;
AvailableGamesList* gamesList;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__JoinGameScreen_H__*/

View File

@@ -0,0 +1,181 @@
#include "OptionsScreen.h"
#include "StartMenuScreen.h"
#include "DialogDefinitions.h"
#include "../../Minecraft.h"
#include "../../../AppPlatform.h"
#include "../components/OptionsPane.h"
#include "../components/ImageButton.h"
#include "../components/OptionsGroup.h"
OptionsScreen::OptionsScreen()
: btnClose(NULL),
bHeader(NULL),
selectedCategory(0) {
}
OptionsScreen::~OptionsScreen() {
if(btnClose != NULL) {
delete btnClose;
btnClose = NULL;
}
if(bHeader != NULL) {
delete bHeader,
bHeader = NULL;
}
for(std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
if(*it != NULL) {
delete *it;
*it = NULL;
}
}
for(std::vector<OptionsPane*>::iterator it = optionPanes.begin(); it != optionPanes.end(); ++it) {
if(*it != NULL) {
delete *it;
*it = NULL;
}
}
categoryButtons.clear();
}
void OptionsScreen::init() {
bHeader = new Touch::THeader(0, "Options");
btnClose = new ImageButton(1, "");
ImageDef def;
def.name = "gui/touchgui.png";
def.width = 34;
def.height = 26;
def.setSrc(IntRectangle(150, 0, (int)def.width, (int)def.height));
btnClose->setImageDef(def, true);
categoryButtons.push_back(new Touch::TButton(2, "Login"));
categoryButtons.push_back(new Touch::TButton(3, "Game"));
categoryButtons.push_back(new Touch::TButton(4, "Controls"));
categoryButtons.push_back(new Touch::TButton(5, "Graphics"));
buttons.push_back(bHeader);
buttons.push_back(btnClose);
for(std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
buttons.push_back(*it);
tabButtons.push_back(*it);
}
generateOptionScreens();
}
void OptionsScreen::setupPositions() {
int buttonHeight = btnClose->height;
btnClose->x = width - btnClose->width;
btnClose->y = 0;
int offsetNum = 1;
for(std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
(*it)->x = 0;
(*it)->y = offsetNum * buttonHeight;
(*it)->selected = false;
offsetNum++;
}
bHeader->x = 0;
bHeader->y = 0;
bHeader->width = width - btnClose->width;
bHeader->height = btnClose->height;
for(std::vector<OptionsPane*>::iterator it = optionPanes.begin(); it != optionPanes.end(); ++it) {
if(categoryButtons.size() > 0 && categoryButtons[0] != NULL) {
(*it)->x = categoryButtons[0]->width;
(*it)->y = bHeader->height;
(*it)->width = width - categoryButtons[0]->width;
(*it)->setupPositions();
}
}
selectCategory(0);
}
void OptionsScreen::render( int xm, int ym, float a ) {
renderBackground();
super::render(xm, ym, a);
int xmm = xm * width / minecraft->width;
int ymm = ym * height / minecraft->height - 1;
if(currentOptionPane != NULL)
currentOptionPane->render(minecraft, xmm, ymm);
}
void OptionsScreen::removed()
{
}
void OptionsScreen::buttonClicked( Button* button ) {
if(button == btnClose) {
minecraft->reloadOptions();
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
} else if(button->id > 1 && button->id < 7) {
// This is a category button
int categoryButton = button->id - categoryButtons[0]->id;
selectCategory(categoryButton);
}
}
void OptionsScreen::selectCategory( int index ) {
int currentIndex = 0;
for(std::vector<Touch::TButton*>::iterator it = categoryButtons.begin(); it != categoryButtons.end(); ++it) {
if(index == currentIndex) {
(*it)->selected = true;
} else {
(*it)->selected = false;
}
currentIndex++;
}
if(index < (int)optionPanes.size())
currentOptionPane = optionPanes[index];
}
void OptionsScreen::generateOptionScreens() {
optionPanes.push_back(new OptionsPane());
optionPanes.push_back(new OptionsPane());
optionPanes.push_back(new OptionsPane());
optionPanes.push_back(new OptionsPane());
// Mojang Pane
optionPanes[0]->createOptionsGroup("options.group.mojang")
//.addOptionItem(&Options::Option::THIRD_PERSON, minecraft);
.addOptionItem(&Options::Option::SENSITIVITY, minecraft);
// int mojangGroup = optionPanes[0]->createOptionsGroup("Mojang");
// static const int arr[] = {5,4,3,15};
// std::vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );
// optionPanes[0]->createStepSlider(minecraft, mojangGroup, "This works?", &Options::Option::DIFFICULTY, vec);
//
// // Game Pane
// int gameGroup = optionPanes[1]->createOptionsGroup("Game");
// optionPanes[1]->createToggle(gameGroup, "Third person camera", &Options::Option::THIRD_PERSON);
// optionPanes[1]->createToggle(gameGroup, "Server visible", &Options::Option::SERVER_VISIBLE);
//
// // Input Pane
// int controlsGroup = optionPanes[2]->createOptionsGroup("Controls");
// optionPanes[2]->createToggle(controlsGroup, "Invert X-axis", &Options::Option::INVERT_MOUSE);
// optionPanes[2]->createToggle(controlsGroup, "Lefty", &Options::Option::LEFT_HANDED);
// optionPanes[2]->createToggle(controlsGroup, "Use touch screen", &Options::Option::USE_TOUCHSCREEN);
// optionPanes[2]->createToggle(controlsGroup, "Split touch controls", &Options::Option::USE_TOUCH_JOYPAD);
// int feedBackGroup = optionPanes[2]->createOptionsGroup("Feedback");
// optionPanes[2]->createToggle(feedBackGroup, "Vibrate on destroy", &Options::Option::DESTROY_VIBRATION);
//
// int graphicsGroup = optionPanes[3]->createOptionsGroup("Graphics");
// optionPanes[3]->createProgressSlider(minecraft, graphicsGroup, "Gui Scale", &Options::Option::PIXELS_PER_MILLIMETER, 3, 4);
// optionPanes[3]->createToggle(graphicsGroup, "Fancy Graphics", &Options::Option::INVERT_MOUSE);
// optionPanes[3]->createToggle(graphicsGroup, "Fancy Skies", &Options::Option::INVERT_MOUSE);
// optionPanes[3]->createToggle(graphicsGroup, "Animated water", &Options::Option::INVERT_MOUSE);
// int experimentalGraphicsGroup = optionPanes[3]->createOptionsGroup("Experimental graphics");
// optionPanes[3]->createToggle(experimentalGraphicsGroup, "Soft shadows", &Options::Option::INVERT_MOUSE);
}
void OptionsScreen::mouseClicked( int x, int y, int buttonNum ) {
if(currentOptionPane != NULL)
currentOptionPane->mouseClicked(minecraft, x, y, buttonNum);
super::mouseClicked(x, y, buttonNum);
}
void OptionsScreen::mouseReleased( int x, int y, int buttonNum ) {
if(currentOptionPane != NULL)
currentOptionPane->mouseReleased(minecraft, x, y, buttonNum);
super::mouseReleased(x, y, buttonNum);
}
void OptionsScreen::tick() {
if(currentOptionPane != NULL)
currentOptionPane->tick(minecraft);
super::tick();
}

View File

@@ -0,0 +1,38 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__OptionsScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__OptionsScreen_H__
#include "../Screen.h"
#include "../components/Button.h"
class ImageButton;
class OptionsPane;
class OptionsScreen: public Screen
{
typedef Screen super;
void init();
void generateOptionScreens();
public:
OptionsScreen();
~OptionsScreen();
void setupPositions();
void buttonClicked( Button* button );
void render(int xm, int ym, float a);
void removed();
void selectCategory(int index);
virtual void mouseClicked( int x, int y, int buttonNum );
virtual void mouseReleased( int x, int y, int buttonNum );
virtual void tick();
private:
Touch::THeader* bHeader;
ImageButton* btnClose;
std::vector<Touch::TButton*> categoryButtons;
std::vector<OptionsPane*> optionPanes;
OptionsPane* currentOptionPane;
int selectedCategory;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__OptionsScreen_H__*/

View File

@@ -0,0 +1,189 @@
#include "PauseScreen.h"
#include "StartMenuScreen.h"
#include "../components/ImageButton.h"
#include "../../Minecraft.h"
#include "../../../util/Mth.h"
#include "../../../network/RakNetInstance.h"
#include "../../../network/ServerSideNetworkHandler.h"
PauseScreen::PauseScreen(bool wasBackPaused)
: saveStep(0),
visibleTime(0),
bContinue(0),
bQuit(0),
bQuitAndSaveLocally(0),
bServerVisibility(0),
// bThirdPerson(0),
wasBackPaused(wasBackPaused),
bSound(&Options::Option::SOUND, 1, 0),
bThirdPerson(&Options::Option::THIRD_PERSON),
bHideGui(&Options::Option::HIDE_GUI)
{
ImageDef def;
def.setSrc(IntRectangle(160, 144, 39, 31));
def.name = "gui/touchgui.png";
IntRectangle& defSrc = *def.getSrc();
def.width = defSrc.w * 0.666667f;
def.height = defSrc.h * 0.666667f;
bSound.setImageDef(def, true);
defSrc.y += defSrc.h;
bThirdPerson.setImageDef(def, true);
bHideGui.setImageDef(def, true);
//void setImageDef(ImageDef& imageDef, bool setButtonSize);
}
PauseScreen::~PauseScreen() {
delete bContinue;
delete bQuit;
delete bQuitAndSaveLocally;
delete bServerVisibility;
// delete bThirdPerson;
}
void PauseScreen::init() {
if (minecraft->useTouchscreen()) {
bContinue = new Touch::TButton(1, "Back to game");
bQuit = new Touch::TButton(2, "Quit to title");
bQuitAndSaveLocally = new Touch::TButton(3, "Quit and copy map");
bServerVisibility = new Touch::TButton(4, "");
// bThirdPerson = new Touch::TButton(5, "Toggle 3:rd person view");
} else {
bContinue = new Button(1, "Back to game");
bQuit = new Button(2, "Quit to title");
bQuitAndSaveLocally = new Button(3, "Quit and copy map");
bServerVisibility = new Button(4, "");
// bThirdPerson = new Button(5, "Toggle 3:rd person view");
}
buttons.push_back(bContinue);
buttons.push_back(bQuit);
bSound.updateImage(&minecraft->options);
bThirdPerson.updateImage(&minecraft->options);
bHideGui.updateImage(&minecraft->options);
buttons.push_back(&bSound);
buttons.push_back(&bThirdPerson);
//buttons.push_back(&bHideGui);
// If Back wasn't pressed, set up additional items (more than Quit to menu
// and Back to game) here
#if !defined(APPLE_DEMO_PROMOTION) && !defined(RPI)
if (true || !wasBackPaused) {
if (minecraft->raknetInstance) {
if (minecraft->raknetInstance->isServer()) {
updateServerVisibilityText();
buttons.push_back(bServerVisibility);
}
else {
#if !defined(DEMO_MODE)
buttons.push_back(bQuitAndSaveLocally);
#endif
}
}
}
#endif
// buttons.push_back(bThirdPerson);
for (unsigned int i = 0; i < buttons.size(); ++i) {
if (buttons[i] == &bSound) continue;
if (buttons[i] == &bThirdPerson) continue;
if (buttons[i] == &bHideGui) continue;
tabButtons.push_back(buttons[i]);
}
}
void PauseScreen::setupPositions() {
saveStep = 0;
int yBase = 16;
bContinue->width = bQuit->width = /*bThirdPerson->w =*/ 160;
bQuitAndSaveLocally->width = bServerVisibility->width = 160;
bContinue->x = (width - bContinue->width) / 2;
bContinue->y = yBase + 32 * 1;
bQuit->x = (width - bQuit->width) / 2;
bQuit->y = yBase + 32 * 2;
#if APPLE_DEMO_PROMOTION
bQuit->y += 16;
#endif
bQuitAndSaveLocally->x = bServerVisibility->x = (width - bQuitAndSaveLocally->width) / 2;
bQuitAndSaveLocally->y = bServerVisibility->y = yBase + 32 * 3;
bSound.y = bThirdPerson.y = 8;
bSound.x = 4;
bThirdPerson.x = bSound.x + 4 + bSound.width;
bHideGui.x = bThirdPerson.x + 4 + bThirdPerson.width;
//bThirdPerson->x = (width - bThirdPerson->w) / 2;
//bThirdPerson->y = yBase + 32 * 4;
}
void PauseScreen::tick() {
super::tick();
visibleTime++;
}
void PauseScreen::render(int xm, int ym, float a) {
renderBackground();
//bool isSaving = !minecraft->level.pauseSave(saveStep++);
//if (isSaving || visibleTime < 20) {
// float col = ((visibleTime % 10) + a) / 10.0f;
// col = Mth::sin(col * Mth::PI * 2) * 0.2f + 0.8f;
// int br = (int) (255 * col);
// drawString(font, "Saving level..", 8, height - 16, br << 16 | br << 8 | br);
//}
drawCenteredString(font, "Game menu", width / 2, 24, 0xffffff);
super::render(xm, ym, a);
}
void PauseScreen::buttonClicked(Button* button) {
if (button->id == bContinue->id) {
minecraft->setScreen(NULL);
//minecraft->grabMouse();
}
if (button->id == bQuit->id) {
minecraft->leaveGame();
}
if (button->id == bQuitAndSaveLocally->id) {
minecraft->leaveGame(true);
}
if (button->id == bServerVisibility->id) {
if (minecraft->raknetInstance && minecraft->netCallback && minecraft->raknetInstance->isServer()) {
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) minecraft->netCallback;
bool allows = !ss->allowsIncomingConnections();
ss->allowIncomingConnections(allows);
updateServerVisibilityText();
}
}
if (button->id == OptionButton::ButtonId) {
((OptionButton*)button)->toggle(&minecraft->options);
}
//if (button->id == bThirdPerson->id) {
// minecraft->options.thirdPersonView = !minecraft->options.thirdPersonView;
//}
}
void PauseScreen::updateServerVisibilityText()
{
if (!minecraft->raknetInstance || !minecraft->raknetInstance->isServer())
return;
ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) minecraft->netCallback;
bServerVisibility->msg = ss->allowsIncomingConnections()?
"Server is visible"
: "Server is invisible";
}

View File

@@ -0,0 +1,43 @@
#ifndef NET_MINECRAFT_CLIENT_GUI__PauseScreen_H__
#define NET_MINECRAFT_CLIENT_GUI__PauseScreen_H__
//package net.minecraft.client.gui;
#include "../Screen.h"
#include "../components/ImageButton.h"
class Button;
class PauseScreen: public Screen
{
typedef Screen super;
public:
PauseScreen(bool wasBackPaused);
~PauseScreen();
void init();
void setupPositions();
void tick();
void render(int xm, int ym, float a);
protected:
void buttonClicked(Button* button);
private:
void updateServerVisibilityText();
int saveStep;
int visibleTime;
bool wasBackPaused;
Button* bContinue;
Button* bQuit;
Button* bQuitAndSaveLocally;
Button* bServerVisibility;
// Button* bThirdPerson;
OptionButton bSound;
OptionButton bThirdPerson;
OptionButton bHideGui;
};
#endif /*NET_MINECRAFT_CLIENT_GUI__PauseScreen_H__*/

View File

@@ -0,0 +1,162 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__PrerenderTilesScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__PrerenderTilesScreen_H__
#include "../Screen.h"
#include "../../renderer/GameRenderer.h"
#include "../../renderer/entity/ItemRenderer.h"
#include "../../../world/item/ItemInstance.h"
#include "../../../world/level/tile/Tile.h"
#include "../../../world/entity/player/Inventory.h"
#include "../../renderer/Tesselator.h"
#include "../../../world/item/crafting/Recipes.h"
#include "../../../world/item/crafting/FurnaceRecipes.h"
#include "../../../world/level/tile/LeafTile.h"
#include "../../renderer/TileRenderer.h"
class PrerenderTilesScreen: public Screen
{
public:
void init() {
Player p(minecraft->level, true);
Inventory _inventory(&p, true);
Inventory* inventory = &_inventory;
// Copy over the inventory items
for (int i = Inventory::MAX_SELECTION_SIZE; i < inventory->getContainerSize(); ++i)
addItem(inventory->getItem(i));
// Fill the inventory with all the recipe items we don't already have: furnace
const FurnaceRecipes::Map& furnaceRecipes = FurnaceRecipes::getInstance()->getRecipes();
for (FurnaceRecipes::Map::const_iterator cit = furnaceRecipes.begin(); cit != furnaceRecipes.end(); ++cit) {
ItemInstance ingredient(cit->first, 1, 0);
addItem(&ingredient);
ItemInstance result = cit->second;
addItem(&result);
}
// Fill the inventory with all the recipe items we don't already have: crafting
const RecipeList& recipes = Recipes::getInstance()->getRecipes();
for (unsigned int i = 0; i < recipes.size(); ++i) {
std::vector<ItemInstance> items;
std::vector<ItemInstance> required = recipes[i]->getItemPack().getItemInstances();
items.push_back(recipes[i]->getResultItem());
items.insert(items.end(), required.begin(), required.end());
for (unsigned int i = 0; i < items.size(); ++i) {
ItemInstance& item = items[i];
addItem(&item);
}
}
// Manually added stuff
// Example: the one that's spawned from tiles when destroyed
int items[] = {
Tile::sapling->id, LeafTile::BIRCH_LEAF,
Tile::sapling->id, LeafTile::EVERGREEN_LEAF,
Tile::sapling->id, LeafTile::NORMAL_LEAF,
Tile::dirt->id, 0,
Tile::reeds->id, 0,
Tile::gravel->id, 0,
Item::apple->id, 0,
Tile::grass_carried->id, 0,
Tile::web->id, 0,
Item::sign->id, 0,
};
for (int i = 0; i < sizeof(items)/sizeof(int); i += 2) {
ItemInstance item(items[i], 1, items[i+1]);
addItem(&item);
}
}
void render( int xm, int ym, float a ) {
static Stopwatch w;
w.start();
glDisable2(GL_DEPTH_TEST);
fill(0, 0, width, height, 0xffff00ff);
//fill(0, 0, width, height, 0xff333333);
glColor4f2(1, 1, 1, 1);
glEnable2(GL_BLEND);
LOGI("--------------------\n");
/*int j = 0;
for (int i = Inventory::MAX_SELECTION_SIZE; i < inventory->getContainerSize(); ++i) {
ItemInstance* item = inventory->getItem(i);
if (!item) continue;
//LOGI("desc: %d - %s. %d\n", i, item->toString().c_str());
int x = j%16 * 16;
int y = j/16 * 16;
//Tesselator::instance.color(0xffffffff);
//minecraft->textures->loadAndBindTexture("gui/gui2.png");
//glColor4f2(0.2f, 0.5f, 0.2f, 1);
//blit(x, y, 4 + 20 * (i%9), 4, 16, 16, 15, 15);
//glColor4f2(1, 1, 1, 1);
if (item->id < 256 && TileRenderer::canRender(Tile::tiles[item->id]->getRenderShape())) {
LOGI("0, %d, %d, %d, 0\n", j, item->id, item->getAuxValue());
ItemRenderer::renderGuiItemCorrect(minecraft->font, minecraft->textures, item, x, y);
} else if (item->getIcon() >= 0) {
LOGI("1, %d, %d, %d, %d\n", j, item->id, item->getAuxValue(), item->getIcon());
}
++j;
}*/
int j = 0;
for(std::vector<ItemInstance>::iterator i = mItems.begin(); i != mItems.end(); ++i) {
ItemInstance* item = &(*i);
//LOGI("desc: %d - %s. %d\n", i, item->toString().c_str());
int x = j%16 * 16;
int y = j/16 * 16;
if (item->id < 256 && TileRenderer::canRender(Tile::tiles[item->id]->getRenderShape())) {
LOGI("0, %d, %d, %d, 0\n", j, item->id, item->getAuxValue());
ItemRenderer::renderGuiItemCorrect(minecraft->font, minecraft->textures, item, x, y);
} else if (item->getIcon() >= 0) {
LOGI("1, %d, %d, %d, %d\n", j, item->id, item->getAuxValue(), item->getIcon());
}
j++;
}
//@todo: blit out something famous here
//glRotatef2(-180, 1, 0, 0);
glEnable2(GL_DEPTH_TEST);
glDisable2(GL_BLEND);
w.stop();
w.printEvery(100, "render-blocksel");
}
void removed(){}
void addItem(ItemInstance* item) {
if(item == NULL)
return;
if (item->getAuxValue() < 0) return;
bool found = false;
for(std::vector<ItemInstance>::iterator i = mItems.begin(); i != mItems.end(); ++i) {
ItemInstance *jitem = &*i;
if(jitem->id != item->id) continue;
if(jitem->isStackedByData() && jitem->getAuxValue() != item->getAuxValue()) continue;
found = true;
break;
}
if (!found) {
LOGI("Adding item: %s\n", item->getDescriptionId().c_str());
mItems.push_back(*item);
}
}
private:
std::vector<ItemInstance> mItems;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__PrerenderTilesScreen_H__*/

View File

@@ -0,0 +1,99 @@
#include "ProgressScreen.h"
#include "DisconnectionScreen.h"
#include "../Gui.h"
#include "../Font.h"
#include "../../Minecraft.h"
#include "../../renderer/Tesselator.h"
#include "../../../SharedConstants.h"
#include "../../renderer/Textures.h"
ProgressScreen::ProgressScreen()
: ticks(0)
{
}
void ProgressScreen::render( int xm, int ym, float a )
{
if (minecraft->isLevelGenerated()) {
minecraft->setScreen(NULL);
return;
}
Tesselator& t = Tesselator::instance;
renderBackground();
minecraft->textures->loadAndBindTexture("gui/background.png");
const float s = 32;
t.begin();
t.color(0x404040);
t.vertexUV(0, (float)height, 0, 0, height / s);
t.vertexUV((float)width, (float)height, 0, width / s, height / s);
t.vertexUV((float)width, 0, 0, width / s, 0);
t.vertexUV(0, 0, 0, 0, 0);
t.draw();
int i = minecraft->progressStagePercentage;
if (i >= 0) {
int w = 100;
int h = 2;
int x = width / 2 - w / 2;
int y = height / 2 + 16;
//printf("%d, %d - %d, %d\n", x, y, x + w, y + h);
glDisable2(GL_TEXTURE_2D);
t.begin();
t.color(0x808080);
t.vertex((float)x, (float)y, 0);
t.vertex((float)x, (float)(y + h), 0);
t.vertex((float)(x + w), (float)(y + h), 0);
t.vertex((float)(x + w), (float)y, 0);
t.color(0x80ff80);
t.vertex((float)x, (float)y, 0);
t.vertex((float)x, (float)(y + h), 0);
t.vertex((float)(x + i), (float)(y + h), 0);
t.vertex((float)(x + i), (float)y, 0);
t.draw();
glEnable2(GL_TEXTURE_2D);
}
glEnable2(GL_BLEND);
const char* title = "Generating world";
minecraft->font->drawShadow(title, (float)((width - minecraft->font->width(title)) / 2), (float)(height / 2 - 4 - 16), 0xffffff);
const char* status = minecraft->getProgressMessage();
const int progressWidth = minecraft->font->width(status);
const int progressLeft = (width - progressWidth) / 2;
const int progressY = height / 2 - 4 + 8;
minecraft->font->drawShadow(status, (float)progressLeft, (float)progressY, 0xffffff);
#if APPLE_DEMO_PROMOTION
drawCenteredString(minecraft->font, "This demonstration version", width/2, progressY + 36, 0xffffff);
drawCenteredString(minecraft->font, "does not allow saving games", width/2, progressY + 46, 0xffffff);
#endif
// If we're locating the server, show our famous spinner!
bool isLocating = (minecraft->getProgressStatusId() == 0);
if (isLocating) {
const int spinnerX = progressLeft + progressWidth + 6;
static const char* spinnerTexts[] = {"-", "\\", "|", "/"};
int n = ((int)(5.5f * getTimeS()) % 4);
drawCenteredString(minecraft->font, spinnerTexts[n], spinnerX, progressY, 0xffffffff);
}
glDisable2(GL_BLEND);
sleepMs(50);
}
bool ProgressScreen::isInGameScreen() { return false; }
void ProgressScreen::tick() {
// After 10 seconds of not connecting -> write an error message and go back
if (++ticks == 10 * SharedConstants::TicksPerSecond && minecraft->getProgressStatusId() == 0) {
minecraft->setScreen( new DisconnectionScreen("Could not connect to server. Try again.") );
}
}

View File

@@ -0,0 +1,19 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__ProgressScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__ProgressScreen_H__
#include "../Screen.h"
class ProgressScreen: public Screen
{
public:
ProgressScreen();
void render(int xm, int ym, float a);
bool isInGameScreen();
void tick();
private:
int ticks;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__ProgressScreen_H__*/

View File

@@ -0,0 +1,55 @@
#include "RenameMPLevelScreen.h"
#include "StartMenuScreen.h"
#include "DialogDefinitions.h"
#include "../Gui.h"
#include "../../Minecraft.h"
#include "../../../AppPlatform.h"
#include "../../../platform/log.h"
#include "../../../world/level/storage/LevelStorageSource.h"
static char ILLEGAL_FILE_CHARACTERS[] = {
'/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':'
};
RenameMPLevelScreen::RenameMPLevelScreen( const std::string& levelId )
: _levelId(levelId)
{
}
void RenameMPLevelScreen::init() {
minecraft->platform()->createUserInput(DialogDefinitions::DIALOG_RENAME_MP_WORLD);
}
void RenameMPLevelScreen::render(int xm, int ym, float a)
{
renderBackground();
#ifdef WIN32
minecraft->getLevelSource()->renameLevel(_levelId, "Save?Level");
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
#else
int status = minecraft->platform()->getUserInputStatus();
if (status > -1) {
if (status == 1) {
std::vector<std::string> v = minecraft->platform()->getUserInput();
if (!v.empty()) {
// Read the level name.
// 1) Trim name 2) Remove all bad chars -) We don't have to getUniqueLevelName, since renameLevel will do that
std::string levelId = v[0];
for (int i = 0; i < sizeof(ILLEGAL_FILE_CHARACTERS) / sizeof(char); ++i)
levelId = Util::stringReplace(levelId, std::string(1, ILLEGAL_FILE_CHARACTERS[i]), "");
if ((int)levelId.length() == 0) {
levelId = "saved_world";
}
minecraft->getLevelSource()->renameLevel(_levelId, levelId);
}
}
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
}
#endif
}

View File

@@ -0,0 +1,18 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__RenameMPLevelScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__RenameMPLevelScreen_H__
#include "../Screen.h"
class RenameMPLevelScreen: public Screen
{
public:
RenameMPLevelScreen(const std::string& levelId);
virtual void init();
virtual void render(int xm, int ym, float a);
private:
std::string _levelId;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__RenameMPLevelScreen_H__*/

View File

@@ -0,0 +1,56 @@
#include "ScreenChooser.h"
#include "StartMenuScreen.h"
#include "SelectWorldScreen.h"
#include "JoinGameScreen.h"
#include "PauseScreen.h"
#include "RenameMPLevelScreen.h"
#include "IngameBlockSelectionScreen.h"
#include "touch/TouchStartMenuScreen.h"
#include "touch/TouchSelectWorldScreen.h"
#include "touch/TouchJoinGameScreen.h"
#include "touch/TouchIngameBlockSelectionScreen.h"
#include "../../Minecraft.h"
Screen* ScreenChooser::createScreen( ScreenId id )
{
Screen* screen = NULL;
if (_mc->useTouchscreen()) {
switch (id) {
case SCREEN_STARTMENU: screen = new Touch::StartMenuScreen(); break;
case SCREEN_SELECTWORLD:screen = new Touch::SelectWorldScreen();break;
case SCREEN_JOINGAME: screen = new Touch::JoinGameScreen(); break;
case SCREEN_PAUSE: screen = new PauseScreen(false); break;
case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break;
case SCREEN_BLOCKSELECTION: screen = new Touch::IngameBlockSelectionScreen(); break;
case SCREEN_NONE:
default:
// Do nothing
break;
}
} else {
switch (id) {
case SCREEN_STARTMENU: screen = new StartMenuScreen(); break;
case SCREEN_SELECTWORLD:screen = new SelectWorldScreen();break;
case SCREEN_JOINGAME: screen = new JoinGameScreen(); break;
case SCREEN_PAUSE: screen = new PauseScreen(false); break;
case SCREEN_PAUSEPREV: screen = new PauseScreen(true); break;
case SCREEN_BLOCKSELECTION: screen = new IngameBlockSelectionScreen(); break;
case SCREEN_NONE:
default:
// Do nothing
break;
}
}
return screen;
}
Screen* ScreenChooser::setScreen(ScreenId id)
{
Screen* screen = createScreen(id);
_mc->setScreen(screen);
return screen;
}

View File

@@ -0,0 +1,30 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__ScreenChooser_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__ScreenChooser_H__
enum ScreenId {
SCREEN_NONE,
SCREEN_STARTMENU,
SCREEN_JOINGAME,
SCREEN_PAUSE,
SCREEN_PAUSEPREV,
SCREEN_SELECTWORLD,
SCREEN_BLOCKSELECTION
};
class Screen;
class Minecraft;
class ScreenChooser
{
public:
ScreenChooser(Minecraft* mc)
: _mc(mc)
{}
Screen* createScreen(ScreenId id);
Screen* setScreen(ScreenId id);
private:
Minecraft* _mc;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__ScreenChooser_H__*/

View File

@@ -0,0 +1,507 @@
#include "SelectWorldScreen.h"
#include "StartMenuScreen.h"
#include "ProgressScreen.h"
#include "DialogDefinitions.h"
#include "../../renderer/Tesselator.h"
#include "../../../AppPlatform.h"
#include "../../../util/StringUtils.h"
#include "../../../util/Mth.h"
#include "../../../platform/input/Mouse.h"
#include "../../../Performance.h"
#include "../../../world/level/LevelSettings.h"
#include <algorithm>
#include <set>
#include "../../renderer/Textures.h"
#include "SimpleChooseLevelScreen.h"
static float Max(float a, float b) {
return a>b? a : b;
}
//
// World Selection List
//
WorldSelectionList::WorldSelectionList( Minecraft* minecraft, int width, int height )
: _height(height),
hasPickedLevel(false),
currentTick(0),
stoppedTick(-1),
mode(0),
RolledSelectionListH(minecraft, width, height, 0, width, 26, height-32, 120)
{
}
int WorldSelectionList::getNumberOfItems() {
return (int)levels.size();
}
void WorldSelectionList::selectItem( int item, bool doubleClick ) {
//LOGI("sel: %d, item %d\n", selectedItem, item);
if (selectedItem < 0 || (selectedItem != item))
return;
if (!hasPickedLevel) {
hasPickedLevel = true;
pickedLevel = levels[item];
}
}
bool WorldSelectionList::isSelectedItem( int item ) {
return item == selectedItem;
}
void WorldSelectionList::renderItem( int i, int x, int y, int h, Tesselator& t ) {
int centerx = x + itemWidth/2;
float a0 = Max(1.1f - std::abs( width / 2 - centerx ) * 0.0055f, 0.2f);
if (a0 > 1) a0 = 1;
int textColor = (int)(255.0f * a0) * 0x010101;
int textColor2 = (int)(140.0f * a0) * 0x010101;
const int TY = y + 42;
const int TX = centerx - itemWidth / 2 + 5;
StringVector v = _descriptions[i];
drawString(minecraft->font, v[0].c_str(), TX, TY + 0, textColor);
drawString(minecraft->font, v[1].c_str(), TX, TY + 10, textColor2);
drawString(minecraft->font, v[2].c_str(), TX, TY + 20, textColor2);
drawString(minecraft->font, v[3].c_str(), TX, TY + 30, textColor2);
minecraft->textures->loadAndBindTexture(_imageNames[i]);
t.color(0.3f, 1.0f, 0.2f);
//float x0 = (float)x;
//float x1 = (float)x + (float)itemWidth;
const float IY = (float)y - 8;
t.begin();
t.color(textColor);
t.vertexUV((float)(centerx-32), IY, blitOffset, 0, 0);
t.vertexUV((float)(centerx-32), IY + 48, blitOffset, 0, 1);
t.vertexUV((float)(centerx+32), IY + 48, blitOffset, 1, 1);
t.vertexUV((float)(centerx+32), IY, blitOffset, 1, 0);
t.draw();
}
void WorldSelectionList::stepLeft() {
if (selectedItem > 0) {
td.start = xo;
td.stop = xo - itemWidth;
td.cur = 0;
td.dur = 8;
mode = 1;
tweenInited();
}
}
void WorldSelectionList::stepRight() {
if (selectedItem >= 0 && selectedItem < getNumberOfItems()-1) {
td.start = xo;
td.stop = xo + itemWidth;
td.cur = 0;
td.dur = 8;
mode = 1;
tweenInited();
}
}
void WorldSelectionList::commit() {
for (unsigned int i = 0; i < levels.size(); ++i) {
LevelSummary& level = levels[i];
std::stringstream ss;
ss << level.name << "/preview.png";
TextureId id = Textures::InvalidId;//minecraft->textures->loadTexture(ss.str(), false);
if (id != Textures::InvalidId) {
_imageNames.push_back( ss.str() );
} else {
_imageNames.push_back("gui/default_world.png");
}
StringVector lines;
lines.push_back(level.name);
lines.push_back(minecraft->platform()->getDateString(level.lastPlayed));
lines.push_back(level.id);
lines.push_back(LevelSettings::gameTypeToString(level.gameType));
_descriptions.push_back(lines);
selectedItem = 0;
}
}
static float quadraticInOut(float t, float dur, float start, float stop) {
const float delta = stop - start;
const float T = (t / dur) * 2.0f;
if (T < 1) return 0.5f*delta*T*T + start;
return -0.5f*delta * ((T-1)*(T-3) - 1) + start;
}
void WorldSelectionList::tick()
{
RolledSelectionListH::tick();
++currentTick;
if (Mouse::isButtonDown(MouseAction::ACTION_LEFT) || dragState == 0)
return;
// Handle the tween (when in "mode 1")
selectedItem = -1;
if (mode == 1) {
if (++td.cur == td.dur) {
mode = 0;
xInertia = 0;
xoo = xo = td.stop;
selectedItem = getItemAtPosition(width/2, height/2);
} else {
tweenInited();
}
return;
}
// It's still going fast, let it run
float speed = Mth::abs(xInertia);
bool slowEnoughToBeBothered = speed < 5.0f;
if (!slowEnoughToBeBothered) {
xInertia = xInertia * .9f;
return;
}
xInertia *= 0.8f;
if (speed < 1 && dragState < 0) {
const int offsetx = (width-itemWidth) / 2;
const float pxo = xo + offsetx;
int index = getItemAtXPositionRaw((int)(pxo - 10*xInertia));
int indexPos = index*itemWidth;
// Pick closest
float diff = (float)indexPos - pxo;
if (diff < -itemWidth/2) {
diff += itemWidth;
index++;
//indexPos += itemWidth;
}
if (Mth::abs(diff) < 1 && speed < 0.1f) {
selectedItem = getItemAtPosition(width/2, height/2);
return;
}
td.start = xo;
td.stop = xo + diff;
td.cur = 0;
td.dur = (float) Mth::Min(7, 1 + (int)(Mth::abs(diff) * 0.25f));
mode = 1;
//LOGI("inited-t %d\n", dragState);
tweenInited();
}
}
float WorldSelectionList::getPos( float alpha )
{
if (mode != 1) return RolledSelectionListH::getPos(alpha);
float x0 = quadraticInOut(td.cur, td.dur, td.start, td.stop);
float x1 = quadraticInOut(td.cur+1, td.dur, td.start, td.stop);
return x0 + (x1-x0)*alpha;
}
bool WorldSelectionList::capXPosition() {
bool capped = RolledSelectionListH::capXPosition();
if (capped) mode = 0;
return capped;
}
void WorldSelectionList::tweenInited() {
float x0 = quadraticInOut(td.cur, td.dur, td.start, td.stop);
float x1 = quadraticInOut(td.cur+1, td.dur, td.start, td.stop);
xInertia = x0-x1; // yes, it's all backwards and messed up..
}
//
// Select World Screen
//
SelectWorldScreen::SelectWorldScreen()
: bDelete (1, "Delete"),
bCreate (2, "Create new"),
bBack (3, "Back"),
bWorldView(4, ""),
worldsList(NULL),
_state(_STATE_DEFAULT),
_hasStartedLevel(false)
{
bDelete.active = false;
}
SelectWorldScreen::~SelectWorldScreen()
{
delete worldsList;
}
void SelectWorldScreen::buttonClicked(Button* button)
{
if (button->id == bCreate.id) {
//minecraft->setScreen( new CreateWorldScreen() );
//minecraft->locateMultiplayer();
//minecraft->setScreen(new JoinGameScreen());
//minecraft->hostMultiplayer();
//minecraft->setScreen(new ProgressScreen());
if (_state == _STATE_DEFAULT && !_hasStartedLevel) {
minecraft->platform()->createUserInput(DialogDefinitions::DIALOG_CREATE_NEW_WORLD);
_state = _STATE_CREATEWORLD;
}
}
if (button->id == bDelete.id) {
if (isIndexValid(worldsList->selectedItem)) {
LevelSummary level = worldsList->levels[worldsList->selectedItem];
LOGI("level: %s, %s\n", level.id.c_str(), level.name.c_str());
minecraft->setScreen( new DeleteWorldScreen(level) );
}
}
if (button->id == bBack.id) {
minecraft->cancelLocateMultiplayer();
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
}
if (button->id == bWorldView.id) {
// Try to "click" the item in the middle
worldsList->selectItem( worldsList->getItemAtPosition(width/2, height/2), false );
}
}
bool SelectWorldScreen::handleBackEvent(bool isDown)
{
if (!isDown)
{
minecraft->cancelLocateMultiplayer();
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
}
return true;
}
bool SelectWorldScreen::isIndexValid( int index )
{
return worldsList && index >= 0 && index < worldsList->getNumberOfItems();
}
static char ILLEGAL_FILE_CHARACTERS[] = {
'/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':'
};
void SelectWorldScreen::tick()
{
if (_state == _STATE_CREATEWORLD) {
#if defined(RPI)
std::string levelId = getUniqueLevelName("world");
LevelSettings settings(getEpochTimeS(), GameType::Creative);
minecraft->selectLevel(levelId, levelId, settings);
minecraft->hostMultiplayer();
minecraft->setScreen(new ProgressScreen());
_hasStartedLevel = true;
#elif defined(WIN32)
std::string name = getUniqueLevelName("perf");
minecraft->setScreen(new SimpleChooseLevelScreen(name));
#else
int status = minecraft->platform()->getUserInputStatus();
if (status > -1) {
if (status == 1) {
StringVector sv = minecraft->platform()->getUserInput();
// Read the level name.
// 1) Trim name 2) Remove all bad chars 3) Append '-' chars 'til the name is unique
std::string levelName = Util::stringTrim(sv[0]);
std::string levelId = levelName;
for (int i = 0; i < sizeof(ILLEGAL_FILE_CHARACTERS) / sizeof(char); ++i)
levelId = Util::stringReplace(levelId, std::string(1, ILLEGAL_FILE_CHARACTERS[i]), "");
if ((int)levelId.length() == 0) {
levelId = "no_name";
}
levelId = getUniqueLevelName(levelId);
// Read the seed
int seed = getEpochTimeS();
if (sv.size() >= 2) {
std::string seedString = Util::stringTrim(sv[1]);
if (seedString.length() > 0) {
int tmpSeed;
// Try to read it as an integer
if (sscanf(seedString.c_str(), "%d", &tmpSeed) > 0) {
seed = tmpSeed;
} // Hash the "seed"
else {
seed = Util::hashCode(seedString);
}
}
}
// Read the game mode
bool isCreative = true;
if (sv.size() >= 3 && sv[2] == "survival")
isCreative = false;
// Start a new level with the given name and seed
LevelSettings settings(seed, isCreative? GameType::Creative : GameType::Survival);
LOGI("Creating a level with id '%s', name '%s' and seed '%d'\n", levelId.c_str(), levelName.c_str(), seed);
minecraft->selectLevel(levelId, levelName, settings);
minecraft->hostMultiplayer();
minecraft->setScreen(new ProgressScreen());
_hasStartedLevel = true;
}
_state = _STATE_DEFAULT;
}
#endif
return;
}
worldsList->tick();
if (worldsList->hasPickedLevel) {
minecraft->selectLevel(worldsList->pickedLevel.id, worldsList->pickedLevel.name, LevelSettings::None());
minecraft->hostMultiplayer();
minecraft->setScreen(new ProgressScreen());
_hasStartedLevel = true;
return;
}
// copy the currently selected item
LevelSummary selectedWorld;
//bool hasSelection = false;
if (isIndexValid(worldsList->selectedItem))
{
selectedWorld = worldsList->levels[worldsList->selectedItem];
//hasSelection = true;
}
bDelete.active = isIndexValid(worldsList->selectedItem);
}
void SelectWorldScreen::init()
{
worldsList = new WorldSelectionList(minecraft, width, height);
loadLevelSource();
worldsList->commit();
buttons.push_back(&bDelete);
buttons.push_back(&bCreate);
buttons.push_back(&bBack);
_mouseHasBeenUp = !Mouse::getButtonState(MouseAction::ACTION_LEFT);
tabButtons.push_back(&bWorldView);
tabButtons.push_back(&bDelete);
tabButtons.push_back(&bCreate);
tabButtons.push_back(&bBack);
}
void SelectWorldScreen::setupPositions() {
int yBase = height - 28;
//#ifdef ANDROID
bCreate.y = yBase;
bBack.y = yBase;
bDelete.y = yBase;
bBack.width = bDelete.width = bCreate.width = 84;
//bDelete.h = bCreate.h = bBack.h = 24;
//#endif
// Center buttons
bDelete.x = width / 2 - 4 - bDelete.width - bDelete.width / 2;
bCreate.x = width / 2 - bCreate.width / 2;
bBack.x = width / 2 + 4 + bCreate.width - bBack.width / 2;
}
void SelectWorldScreen::render( int xm, int ym, float a )
{
//Performance::watches.get("sws-full").start();
//Performance::watches.get("sws-renderbg").start();
renderBackground();
//Performance::watches.get("sws-renderbg").stop();
//Performance::watches.get("sws-worlds").start();
worldsList->setComponentSelected(bWorldView.selected);
if (_mouseHasBeenUp)
worldsList->render(xm, ym, a);
else {
worldsList->render(0, 0, a);
_mouseHasBeenUp = !Mouse::getButtonState(MouseAction::ACTION_LEFT);
}
//Performance::watches.get("sws-worlds").stop();
//Performance::watches.get("sws-screen").start();
Screen::render(xm, ym, a);
//Performance::watches.get("sws-screen").stop();
//Performance::watches.get("sws-string").start();
drawCenteredString(minecraft->font, "Select world", width / 2, 8, 0xffffffff);
//Performance::watches.get("sws-string").stop();
//Performance::watches.get("sws-full").stop();
//Performance::watches.printEvery(128);
}
void SelectWorldScreen::loadLevelSource()
{
LevelStorageSource* levelSource = minecraft->getLevelSource();
levelSource->getLevelList(levels);
std::sort(levels.begin(), levels.end());
for (unsigned int i = 0; i < levels.size(); ++i) {
if (levels[i].id != LevelStorageSource::TempLevelId)
worldsList->levels.push_back( levels[i] );
}
}
std::string SelectWorldScreen::getUniqueLevelName( const std::string& level )
{
std::set<std::string> Set;
for (unsigned int i = 0; i < levels.size(); ++i)
Set.insert(levels[i].id);
std::string s = level;
while ( Set.find(s) != Set.end() )
s += "-";
return s;
}
bool SelectWorldScreen::isInGameScreen() { return true; }
void SelectWorldScreen::keyPressed( int eventKey )
{
if (bWorldView.selected) {
if (eventKey == minecraft->options.keyLeft.key)
worldsList->stepLeft();
if (eventKey == minecraft->options.keyRight.key)
worldsList->stepRight();
}
Screen::keyPressed(eventKey);
}
//
// Delete World Screen
//
DeleteWorldScreen::DeleteWorldScreen(const LevelSummary& level)
: ConfirmScreen(NULL, "Are you sure you want to delete this world?",
"'" + level.name + "' will be lost forever!",
"Delete", "Cancel", 0),
_level(level)
{
tabButtonIndex = 1;
}
void DeleteWorldScreen::postResult( bool isOk )
{
if (isOk) {
LevelStorageSource* storageSource = minecraft->getLevelSource();
storageSource->deleteLevel(_level.id);
}
minecraft->screenChooser.setScreen(SCREEN_SELECTWORLD);
}

View File

@@ -0,0 +1,113 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__SelectWorldScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__SelectWorldScreen_H__
#include "../Screen.h"
#include "../TweenData.h"
#include "../components/Button.h"
#include "../components/SmallButton.h"
#include "../components/RolledSelectionListH.h"
#include "../../Minecraft.h"
#include "../../../world/level/storage/LevelStorageSource.h"
class SelectWorldScreen;
//
// Scrolling World selection list
//
class WorldSelectionList : public RolledSelectionListH
{
public:
WorldSelectionList(Minecraft* _minecraft, int _width, int _height);
virtual void tick();
void stepLeft();
void stepRight();
void commit();
protected:
virtual int getNumberOfItems();
virtual void selectItem(int item, bool doubleClick);
virtual bool isSelectedItem(int item);
virtual void renderBackground() {}
virtual void renderItem(int i, int x, int y, int h, Tesselator& t);
virtual float getPos(float alpha);
virtual void touched() { mode = 0; }
virtual bool capXPosition();
private:
TweenData td;
void tweenInited();
int selectedItem;
int _height;
LevelSummaryList levels;
std::vector<StringVector> _descriptions;
StringVector _imageNames;
bool hasPickedLevel;
LevelSummary pickedLevel;
int stoppedTick;
int currentTick;
float accRatio;
int mode;
friend class SelectWorldScreen;
};
//
// Delete World screen
//
#include "ConfirmScreen.h"
class DeleteWorldScreen: public ConfirmScreen
{
public:
DeleteWorldScreen(const LevelSummary& levelId);
protected:
virtual void postResult(bool isOk);
private:
LevelSummary _level;
};
//
// Select world screen
//
class SelectWorldScreen: public Screen
{
public:
SelectWorldScreen();
virtual ~SelectWorldScreen();
virtual void init();
virtual void setupPositions();
virtual void tick();
virtual bool isIndexValid(int index);
virtual bool handleBackEvent(bool isDown);
virtual void buttonClicked(Button* button);
virtual void keyPressed(int eventKey);
void render(int xm, int ym, float a);
bool isInGameScreen();
private:
void loadLevelSource();
std::string getUniqueLevelName(const std::string& level);
Button bDelete;
Button bCreate;
Button bBack;
Button bWorldView;
WorldSelectionList* worldsList;
LevelSummaryList levels;
bool _mouseHasBeenUp;
bool _hasStartedLevel;
int _state;
static const int _STATE_DEFAULT = 0;
static const int _STATE_CREATEWORLD = 1;
//LevelStorageSource* levels;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__SelectWorldScreen_H__*/

View File

@@ -0,0 +1,97 @@
#include "SimpleChooseLevelScreen.h"
#include "ProgressScreen.h"
#include "ScreenChooser.h"
#include "../components/Button.h"
#include "../../Minecraft.h"
#include "../../../world/level/LevelSettings.h"
#include "../../../platform/time.h"
SimpleChooseLevelScreen::SimpleChooseLevelScreen(const std::string& levelName)
: bCreative(0),
bSurvival(0),
bBack(0),
levelName(levelName),
hasChosen(false)
{
}
SimpleChooseLevelScreen::~SimpleChooseLevelScreen()
{
delete bCreative;
delete bSurvival;
delete bBack;
}
void SimpleChooseLevelScreen::init()
{
if (minecraft->useTouchscreen()) {
bCreative = new Touch::TButton(1, "Creative mode");
bSurvival = new Touch::TButton(2, "Survival mode");
bBack = new Touch::TButton(3, "Back");
} else {
bCreative = new Button(1, "Creative mode");
bSurvival = new Button(2, "Survival mode");
bBack = new Button(3, "Back");
}
buttons.push_back(bCreative);
buttons.push_back(bSurvival);
buttons.push_back(bBack);
tabButtons.push_back(bCreative);
tabButtons.push_back(bSurvival);
tabButtons.push_back(bBack);
}
void SimpleChooseLevelScreen::setupPositions()
{
bCreative->width = bSurvival->width = bBack->width = 120;
bCreative->x = (width - bCreative->width) / 2;
bCreative->y = height/3 - 40;
bSurvival->x = (width - bSurvival->width) / 2;
bSurvival->y = 2*height/3 - 40;
bBack->x = bSurvival->x + bSurvival->width - bBack->width;
bBack->y = height - 40;
}
void SimpleChooseLevelScreen::render( int xm, int ym, float a )
{
renderDirtBackground(0);
glEnable2(GL_BLEND);
drawCenteredString(minecraft->font, "Mobs, health and gather resources", width/2, bSurvival->y + bSurvival->height + 4, 0xffcccccc);
drawCenteredString(minecraft->font, "Unlimited resources and flying", width/2, bCreative->y + bCreative->height + 4, 0xffcccccc);
Screen::render(xm, ym, a);
glDisable2(GL_BLEND);
}
void SimpleChooseLevelScreen::buttonClicked( Button* button )
{
if (button == bBack) {
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
return;
}
if (hasChosen)
return;
int gameType;
if (button == bCreative)
gameType = GameType::Creative;
if (button == bSurvival)
gameType = GameType::Survival;
std::string levelId = getUniqueLevelName(levelName);
LevelSettings settings(getEpochTimeS(), gameType);
minecraft->selectLevel(levelId, levelId, settings);
minecraft->hostMultiplayer();
minecraft->setScreen(new ProgressScreen());
hasChosen = true;
}
bool SimpleChooseLevelScreen::handleBackEvent(bool isDown) {
if (!isDown)
minecraft->screenChooser.setScreen(SCREEN_STARTMENU);
return true;
}

View File

@@ -0,0 +1,32 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__DemoChooseLevelScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__DemoChooseLevelScreen_H__
#include "ChooseLevelScreen.h"
class Button;
class SimpleChooseLevelScreen: public ChooseLevelScreen
{
public:
SimpleChooseLevelScreen(const std::string& levelName);
virtual ~SimpleChooseLevelScreen();
void init();
void setupPositions();
void render(int xm, int ym, float a);
void buttonClicked(Button* button);
bool handleBackEvent(bool isDown);
private:
Button* bCreative;
Button* bSurvival;
Button* bBack;
bool hasChosen;
std::string levelName;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__DemoChooseLevelScreen_H__*/

View File

@@ -0,0 +1,208 @@
#include "StartMenuScreen.h"
#include "SelectWorldScreen.h"
#include "ProgressScreen.h"
#include "JoinGameScreen.h"
#include "OptionsScreen.h"
#include "PauseScreen.h"
#include "InvalidLicenseScreen.h"
#include "PrerenderTilesScreen.h" // test button
//#include "BuyGameScreen.h"
#include "../../../util/Mth.h"
#include "../Font.h"
#include "../components/SmallButton.h"
#include "../components/ScrolledSelectionList.h"
#include "../../Minecraft.h"
#include "../../renderer/Tesselator.h"
#include "../../../AppPlatform.h"
#include "../../../LicenseCodes.h"
#include "SimpleChooseLevelScreen.h"
#include "../../renderer/Textures.h"
#include "../../../SharedConstants.h"
// Some kind of default settings, might be overridden in ::init
StartMenuScreen::StartMenuScreen()
: bHost( 2, 0, 0, 160, 24, "Start Game"),
bJoin( 3, 0, 0, 160, 24, "Join Game"),
bOptions( 4, 0, 0, 78, 22, "Options"),
bBuy( 5, 0, 0, 78, 22, "Buy"),
bTest( 999, 0, 0, 78, 22, "Create")
{
}
StartMenuScreen::~StartMenuScreen()
{
}
void StartMenuScreen::init()
{
buttons.push_back(&bHost);
buttons.push_back(&bJoin);
//buttons.push_back(&bTest);
tabButtons.push_back(&bHost);
tabButtons.push_back(&bJoin);
#ifndef RPI
buttons.push_back(&bOptions);
tabButtons.push_back(&bOptions);
#endif
#ifdef DEMO_MODE
buttons.push_back(&bBuy);
tabButtons.push_back(&bBuy);
#endif
copyright = "\xffMojang AB";//. Do not distribute!";
#ifdef PRE_ANDROID23
std::string versionString = Common::getGameVersionString("j");
#else
std::string versionString = Common::getGameVersionString();
#endif
#ifdef DEMO_MODE
#ifdef __APPLE__
version = versionString + " (Lite)";
#else
version = versionString + " (Demo)";
#endif
#else
#ifdef RPI
version = "v0.1.1 alpha";//(MCPE " + versionString + " compatible)";
#else
version = versionString;
#endif
#endif
bJoin.active = bHost.active = bOptions.active = false;
}
void StartMenuScreen::setupPositions() {
int yBase = height / 2 + 25;
//#ifdef ANDROID
bHost.y = yBase - 28;
#ifdef RPI
bJoin.y = yBase + 4;
#else
bJoin.y = yBase;
#endif
bOptions.y = yBase + 28 + 2;
bTest.y = bBuy.y = bOptions.y;
//#endif
// Center buttons
bHost.x = (width - bHost.width) / 2;
bJoin.x = (width - bJoin.width) / 2;
bOptions.x = (width - bJoin.width) / 2;
bTest.x = bBuy.x = bOptions.x + bOptions.width + 4;
copyrightPosX = width - minecraft->font->width(copyright) - 1;
versionPosX = (width - minecraft->font->width(version)) / 2;// - minecraft->font->width(version) - 2;
}
void StartMenuScreen::tick() {
_updateLicense();
}
void StartMenuScreen::buttonClicked(Button* button) {
if (button->id == bHost.id)
{
#if defined(DEMO_MODE) || defined(APPLE_DEMO_PROMOTION)
minecraft->setScreen( new SimpleChooseLevelScreen("_DemoLevel") );
#else
minecraft->screenChooser.setScreen(SCREEN_SELECTWORLD);
#endif
}
if (button->id == bJoin.id)
{
minecraft->locateMultiplayer();
minecraft->screenChooser.setScreen(SCREEN_JOINGAME);
}
if (button->id == bOptions.id)
{
minecraft->setScreen(new OptionsScreen());
}
if (button->id == bTest.id)
{
//minecraft->setScreen(new PauseScreen());
//minecraft->setScreen(new PrerenderTilesScreen());
}
if (button->id == bBuy.id)
{
minecraft->platform()->buyGame();
//minecraft->setScreen(new BuyGameScreen());
}
}
bool StartMenuScreen::isInGameScreen() { return false; }
void StartMenuScreen::render( int xm, int ym, float a )
{
renderBackground();
#if defined(RPI)
TextureId id = minecraft->textures->loadTexture("gui/pi_title.png");
#else
TextureId id = minecraft->textures->loadTexture("gui/title.png");
#endif
const TextureData* data = minecraft->textures->getTemporaryTextureData(id);
if (data) {
minecraft->textures->bind(id);
const float x = (float)width / 2;
const float y = 4;
//const float scale = Mth::Min(
const float wh = Mth::Min((float)width/2.0f, (float)data->w / 2);
const float scale = 2.0f * wh / (float)data->w;
const float h = scale * (float)data->h;
// Render title text
Tesselator& t = Tesselator::instance;
glColor4f2(1, 1, 1, 1);
t.begin();
t.vertexUV(x-wh, y+h, blitOffset, 0, 1);
t.vertexUV(x+wh, y+h, blitOffset, 1, 1);
t.vertexUV(x+wh, y+0, blitOffset, 1, 0);
t.vertexUV(x-wh, y+0, blitOffset, 0, 0);
t.draw();
}
#if defined(RPI)
if (Textures::isTextureIdValid(minecraft->textures->loadAndBindTexture("gui/logo/raknet_high_72.png")))
blit(0, height - 12, 0, 0, 43, 12, 256, 72+72);
#endif
drawString(font, version, versionPosX, 62, /*50,*/ 0xffcccccc);//0x666666);
drawString(font, copyright, copyrightPosX, height - 10, 0xffffff);
Screen::render(xm, ym, a);
}
void StartMenuScreen::_updateLicense()
{
int id = minecraft->getLicenseId();
if (LicenseCodes::isReady(id))
{
if (LicenseCodes::isOk(id))
bJoin.active = bHost.active = bOptions.active = true;
else
{
bool hasBuyButton = minecraft->platform()->hasBuyButtonWhenInvalidLicense();
minecraft->setScreen(new InvalidLicenseScreen(id, hasBuyButton));
}
} else {
bJoin.active = bHost.active = bOptions.active = false;
}
}
bool StartMenuScreen::handleBackEvent( bool isDown ) {
minecraft->quit();
return true;
}

View File

@@ -0,0 +1,38 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__StartMenuScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__StartMenuScreen_H__
#include "../Screen.h"
#include "../components/Button.h"
class StartMenuScreen: public Screen
{
public:
StartMenuScreen();
virtual ~StartMenuScreen();
void init();
void setupPositions();
void tick();
void render(int xm, int ym, float a);
void buttonClicked(Button* button);
bool handleBackEvent(bool isDown);
bool isInGameScreen();
private:
void _updateLicense();
Button bHost;
Button bJoin;
Button bOptions;
Button bTest;
Button bBuy;
std::string copyright;
int copyrightPosX;
std::string version;
int versionPosX;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__StartMenuScreen_H__*/

View File

@@ -0,0 +1,146 @@
#include "TextEditScreen.h"
#include "../../../world/level/tile/entity/SignTileEntity.h"
#include "../../../AppPlatform.h"
#include "../../Minecraft.h"
#include "../../renderer/tileentity/TileEntityRenderDispatcher.h"
#include "../../renderer/Tesselator.h"
#include "../../renderer/Textures.h"
#include "../../renderer/GameRenderer.h"
#include "../components/Button.h"
#include "../../../network/Packet.h"
#include "../../../network/RakNetInstance.h"
TextEditScreen::TextEditScreen( SignTileEntity* signEntity )
: sign(signEntity), isShowingKeyboard(false), frame(0), line(0), btnClose(1, "") {
}
TextEditScreen::~TextEditScreen() {
}
void TextEditScreen::init() {
super::init();
minecraft->platform()->showKeyboard();
isShowingKeyboard = true;
ImageDef def;
def.name = "gui/spritesheet.png";
def.x = 0;
def.y = 1;
def.width = def.height = 18;
def.setSrc(IntRectangle(60, 0, 18, 18));
btnClose.setImageDef(def, true);
btnClose.scaleWhenPressed = false;
buttons.push_back(&btnClose);
}
void TextEditScreen::setupPositions() {
btnClose.width = btnClose.height = 19;
btnClose.x = width - btnClose.width;
btnClose.y = 0;
}
bool TextEditScreen::handleBackEvent( bool isDown ) {
sign->setChanged();
Packet* signUpdatePacket = sign->getUpdatePacket();
minecraft->raknetInstance->send(signUpdatePacket);
minecraft->platform()->hideKeyboard();
minecraft->setScreen(NULL);
return true;
}
void TextEditScreen::render( int xm, int ym, float a ) {
glDepthMask(GL_FALSE);
renderBackground();
glPushMatrix();
glDepthMask(GL_TRUE);
glDisable(GL_CULL_FACE);
glLoadIdentity();
Tesselator& t = Tesselator::instance;
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrthof(0.0f, (float)minecraft->width, (float)minecraft->height, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
minecraft->textures->loadAndBindTexture("item/sign.png");
glColor4f2(1, 1, 1, 1);
static float minUV[] = {0.03126f, 0.06249f};
static float maxUV[] = {0.39063f, 0.4374f};
float scale = ((minecraft->height / 2) / 32) * 0.9f;
glTranslatef(minecraft->width / 2.0f, 5.0f, 0.0f);
glScalef2(scale,scale,1);
t.begin(GL_QUADS);
t.vertexUV(-32, 0, 0.0f,minUV[0],minUV[1]);
t.vertexUV(32, 0, 0.0f, maxUV[0], minUV[1]);
t.vertexUV(32, 0 + 32, 0.0f, maxUV[0], maxUV[1]);
t.vertexUV(-32, 0 + 32, 0.0f, minUV[0], maxUV[1]);
t.draw();
sign->selectedLine = line;
float textScale = 8.0f / 11.0f;
glTranslatef(0, 2 ,0);
glScalef2(textScale, textScale, 1);
for(int i = 0; i < 4; ++i) {
//drawCenteredString(font, sign->messages[a], 32.0f, 10 * a, 0xFF000000);
std::string msg = sign->messages[i];
if (i == sign->selectedLine && msg.length() < 14) {
std::string s = "> " + msg + " <";
font->draw(s, -(float)font->width(s) / 2.0f, 10.0f * i, 0xFF000000, false);
} else {
font->draw(msg, -(float)font->width(msg) / 2.0f, 10.0f * i, 0xFF000000, false);
}
}
sign->selectedLine = -1;
//font->draw("Hej", minecraft->width / 2, 100, 0xFFFFFFFF, false);
glPopMatrix();
glEnable(GL_CULL_FACE);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
//glEnable(GL_DEPTH_TEST);
super::render(xm, ym, a);
}
void TextEditScreen::lostFocus() {
}
void TextEditScreen::tick() {
frame++;
}
void TextEditScreen::keyPressed( int eventKey ) {
LOGW("Key pressed! [%d]", eventKey);
if(eventKey == Keyboard::KEY_BACKSPACE) {
if(sign->messages[line].length() > 0) {
sign->messages[line].erase(sign->messages[line].size() - 1, 1);
} else {
line--;
if(line < 0) {
line = 3;
}
}
} else if(eventKey == Keyboard::KEY_RETURN) {
line = (line + 1) % 4;
} else {
super::keyPressed(eventKey);
}
}
void TextEditScreen::keyboardNewChar( char inputChar ) {
std::string fullstring = sign->messages[line] + inputChar;
if(fullstring.length() < 16) {
sign->messages[line] = fullstring;
//LOGW("Line text updated: %s\n", fullstring.c_str());
}
}
void TextEditScreen::buttonClicked( Button* button ) {
if(button == &btnClose)
handleBackEvent(true);
}

View File

@@ -0,0 +1,35 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__TextEditScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__TextEditScreen_H__
//package net.minecraft.client.gui;
#include "../Screen.h"
#include <string>
#include "../components/ImageButton.h"
class SignTileEntity;
class Button;
class TextEditScreen: public Screen
{
typedef Screen super;
public:
TextEditScreen(SignTileEntity* signEntity);
~TextEditScreen();
void init();
void tick();
bool handleBackEvent(bool isDown);
void render(int xm, int ym, float a);
virtual void lostFocus();
virtual void keyPressed(int eventKey);
virtual void keyboardNewChar(char inputChar);
void setupPositions();
void buttonClicked(Button* button);
protected:
bool isShowingKeyboard;
SignTileEntity* sign;
int frame;
int line;
private:
ImageButton btnClose;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__TextEditScreen_H__*/

View File

@@ -0,0 +1,177 @@
#if 0
#include "UploadPhotoScreen.h"
#include "../renderer/TileRenderer.h"
#include "../player/LocalPlayer.h"
#include "../../world/entity/player/Inventory.h"
UploadPhotoScreen::UploadPhotoScreen()
:
selectedItem(0)
{
}
void UploadPhotoScreen::init()
{
int currentSelection = minecraft->player->inventory->getSelectedItemId();
for (int i = 0; i < Inventory::INVENTORY_SIZE; i++)
{
if (currentSelection == minecraft->player->inventory->getSelectionSlotItemId(i + Inventory::SELECTION_SIZE))
{
selectedItem = i;
break;
}
}
}
void UploadPhotoScreen::renderSlots()
{
glColor4f2(1, 1, 1, 1);
blitOffset = -90;
minecraft->textures->loadAndBindTexture("gui/gui.png");
for (int r = 0; r < Inventory::INVENTORY_ROWS; r++)
{
blit(width / 2 - 182 / 2, height - 22 * 3 - 22 * r, 0, 0, 182, 22);
}
if (selectedItem >= 0)
{
int x = width / 2 - 182 / 2 - 1 + (selectedItem % Inventory::SELECTION_SIZE) * 20;
int y = height - 22 * 3 - 1 - (selectedItem / Inventory::SELECTION_SIZE) * 22;
blit(x, y, 0, 22, 24, 22);
}
for (int r = 0; r < Inventory::INVENTORY_ROWS; r++)
{
for (int i = 0; i < 9; i++) {
int x = width / 2 - 9 * 10 + i * 20 + 2;
int y = height - 16 - 3 - 22 * 2 - 22 * r;
renderSlot(r * 9 + i + Inventory::SELECTION_SIZE, x, y, 0);
}
}
}
void UploadPhotoScreen::renderSlot(int slot, int x, int y, float a)
{
int itemId = minecraft->player->inventory->getSelectionSlotItemId(slot);
if (itemId < 0) return;
const bool fancy = false;
if (fancy && itemId < 256 && TileRenderer::canRender(Tile::tiles[itemId]->getRenderShape())) {
} else {
if (itemId < 256) {
Tile* tile = Tile::tiles[itemId];
if (tile == NULL) return;
minecraft->textures->loadAndBindTexture("terrain.png");
int textureId = tile->getTexture(2, 0);
blit(x, y, textureId % 16 * 16, textureId / 16 * 16, 16, 16);
}
}
}
void UploadPhotoScreen::keyPressed(int eventKey)
{
int selX = selectedItem % Inventory::SELECTION_SIZE;
int selY = selectedItem / Inventory::SELECTION_SIZE;
Options& o = minecraft->options;
if (eventKey == o.keyLeft.key && selX > 0)
{
selectedItem -= 1;
}
else if (eventKey == o.keyRight.key && selX < (Inventory::SELECTION_SIZE - 1))
{
selectedItem += 1;
}
else if (eventKey == o.keyDown.key && selY > 0)
{
selectedItem -= Inventory::SELECTION_SIZE;
}
else if (eventKey == o.keyUp.key && selY < (Inventory::INVENTORY_ROWS - 1))
{
selectedItem += Inventory::SELECTION_SIZE;
}
if (eventKey == o.keyMenuOk.key)
{
selectSlotAndClose();
}
}
int UploadPhotoScreen::getSelectedSlot(int x, int y)
{
int left = 3 + width / 2 - Inventory::SELECTION_SIZE * 10;
int top = height - 16 - 3 - 22 * 2 - 22 * Inventory::INVENTORY_ROWS;
if (x >= left && y >= top)
{
int xSlot = (x - left) / 20;
if (xSlot < Inventory::SELECTION_SIZE)
{
// rows are rendered upsidedown
return xSlot + Inventory::INVENTORY_SIZE - ((y - top) / 22) * Inventory::SELECTION_SIZE;
}
}
return -1;
}
void UploadPhotoScreen::mouseClicked(int x, int y, int buttonNum) {
if (buttonNum == MouseAction::ACTION_LEFT) {
int slot = getSelectedSlot(x, y);
if (slot >= 0 && slot < Inventory::INVENTORY_SIZE)
{
selectedItem = slot;
//minecraft->soundEngine->playUI("random.click", 1, 1);
}
}
}
void UploadPhotoScreen::mouseReleased(int x, int y, int buttonNum)
{
if (buttonNum == MouseAction::ACTION_LEFT) {
int slot = getSelectedSlot(x, y);
if (slot >= 0 && slot < Inventory::INVENTORY_SIZE && slot == selectedItem)
{
selectSlotAndClose();
}
}
}
void UploadPhotoScreen::selectSlotAndClose()
{
Inventory* inventory = minecraft->player->inventory;
int itemId = inventory->getSelectionSlotItemId(selectedItem + Inventory::SELECTION_SIZE);
int i = 0;
for (; i < Inventory::SELECTION_SIZE - 2; i++)
{
if (itemId == inventory->getSelectionSlotItemId(i))
{
break;
}
}
// update selection list
for (; i >= 1; i--)
{
inventory->setSelectionSlotItemId(i, inventory->getSelectionSlotItemId(i - 1));
}
inventory->setSelectionSlotItemId(0, itemId);
inventory->selectSlot(0);
minecraft->soundEngine->playUI("random.click", 1, 1);
minecraft->setScreen(NULL);
}
#endif

View File

@@ -0,0 +1,36 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS__UploadPhotoScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS__UploadPhotoScreen_H__
#include "Screen.h"
class UploadPhotoScreen : public Screen
{
public:
UploadPhotoScreen();
virtual ~UploadPhotoScreen() {}
virtual void init();
void render(int xm, int ym, float a) {
Screen::render(xm, ym, a);
}
protected:
virtual void mouseClicked(int x, int y, int buttonNum);
virtual void mouseReleased(int x, int y, int buttonNum);
virtual void keyPressed(int eventKey);
private:
int selectedItem;
void renderSlots();
void renderSlot(int slot, int x, int y, float a);
int getSelectedSlot(int x, int y);
void selectSlotAndClose();
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS__UploadPhotoScreen_H__*/

View File

@@ -0,0 +1,32 @@
#include "CraftingFilters.h"
#include "../../../../world/item/ItemInstance.h"
#include "../../../../world/item/Item.h"
#include "../../../../world/level/tile/Tile.h"
#include "../../../../world/level/material/Material.h"
#include "../../../../world/level/tile/StoneSlabTile.h"
namespace CraftingFilters {
bool isStonecutterItem(const ItemInstance& ins) {
Item* const item = ins.getItem();
if (item->id < 0 || item->id >= 256)
return false;
Tile* const tile = Tile::tiles[item->id];
if (!tile)
return false;
// Special stone/sand cases
if ( tile == Tile::lapisBlock
|| tile == Tile::furnace
|| tile == Tile::stonecutterBench)
return false;
if (tile == Tile::stoneSlabHalf && ins.getAuxValue() == StoneSlabTile::WOOD_SLAB)
return false;
// Return everything stone or sand
return (tile->material == Material::stone || tile->material == Material::sand);
}
}

View File

@@ -0,0 +1,10 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS_CRAFT_CraftingFilters_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS_CRAFT_CraftingFilters_H__
class ItemInstance;
namespace CraftingFilters {
bool isStonecutterItem(const ItemInstance& item);
}
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS_CRAFT_CraftingFilters_H__*/

View File

@@ -0,0 +1,555 @@
#include "PaneCraftingScreen.h"
#include "../touch/TouchStartMenuScreen.h"
#include "../../Screen.h"
#include "../../components/NinePatch.h"
#include "../../../Minecraft.h"
#include "../../../player/LocalPlayer.h"
#include "../../../renderer/Tesselator.h"
#include "../../../renderer/entity/ItemRenderer.h"
#include "../../../../world/item/Item.h"
#include "../../../../world/item/crafting/Recipes.h"
#include "../../../../world/item/ItemCategory.h"
#include "../../../../world/entity/player/Inventory.h"
#include "../../../../util/StringUtils.h"
#include "../../../../locale/I18n.h"
#include "../../../../world/entity/item/ItemEntity.h"
#include "../../../../world/level/Level.h"
#include "../../../../world/item/DyePowderItem.h"
#include "../../../../world/item/crafting/Recipe.h"
static NinePatchLayer* guiPaneFrame = NULL;
const float BorderPixels = 6.0f;
const int descFrameWidth = 100;
const int rgbActive = 0xfff0f0f0;
const int rgbInactive = 0xc0635558;
const int rgbInactiveShadow = 0xc0aaaaaa;
class CategoryButton: public ImageButton {
typedef ImageButton super;
public:
CategoryButton(int id, const ImageButton* const* selectedPtr, NinePatchLayer* stateNormal, NinePatchLayer* statePressed)
: super(id, ""),
selectedPtr(selectedPtr),
stateNormal(stateNormal),
statePressed(statePressed)
{}
void renderBg(Minecraft* minecraft, int xm, int ym) {
//fill(x+1, y+1, x+w-1, y+h-1, 0xff999999);
bool hovered = active && (minecraft->useTouchscreen()?
(_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height) : false);
if (hovered || *selectedPtr == this)
statePressed->draw(Tesselator::instance, (float)x, (float)y);
else
stateNormal->draw(Tesselator::instance, (float)x, (float)y);
}
bool isSecondImage(bool hovered) { return false; }
private:
const ImageButton* const* selectedPtr;
NinePatchLayer* stateNormal;
NinePatchLayer* statePressed;
};
PaneCraftingScreen::PaneCraftingScreen(int craftingSize)
: craftingSize(craftingSize),
currentCategory(-1),
currentItem(NULL),
pane(NULL),
btnCraft(1),
btnClose(2, ""),
selectedCategoryButton(NULL),
guiBackground(NULL),
guiSlotCategory(NULL),
guiSlotCategorySelected(NULL),
numCategories(4)
{
for (int i = 0; i < numCategories; ++i) {
categoryBitmasks.push_back(1 << i);
categoryIcons.push_back(i);
}
}
PaneCraftingScreen::~PaneCraftingScreen() {
for (unsigned int i = 0; i < _items.size(); ++i)
delete _items[i];
for (unsigned int i = 0; i < _categoryButtons.size(); ++i)
delete _categoryButtons[i];
clearCategoryItems();
delete pane;
delete guiBackground;
// statics
delete guiSlotCategory;
delete guiSlotCategorySelected;
delete guiPaneFrame;
}
void PaneCraftingScreen::init() {
ImageDef def;
def.name = "gui/spritesheet.png";
def.x = 0;
def.y = 1;
def.width = def.height = 18;
def.setSrc(IntRectangle(60, 0, 18, 18));
btnClose.setImageDef(def, true);
btnClose.scaleWhenPressed = false;
btnCraft.init(minecraft->textures);
buttons.push_back(&btnCraft);
buttons.push_back(&btnClose);
// GUI patches
NinePatchFactory builder(minecraft->textures, "gui/spritesheet.png");
guiBackground = builder.createSymmetrical(IntRectangle(0, 0, 16, 16), 4, 4);
guiPaneFrame = builder.createSymmetrical(IntRectangle(0, 20, 8, 8), 1, 2)->setExcluded(1 << 4);
guiSlotCategory = builder.createSymmetrical(IntRectangle(8, 32, 8, 8), 2, 2);
guiSlotCategorySelected = builder.createSymmetrical(IntRectangle(0, 32, 8, 8), 2, 2);
initCategories();
}
void PaneCraftingScreen::initCategories() {
_categories.resize(numCategories);
// Category buttons
for (int i = 0; i < numCategories; ++i) {
ImageButton* button = new CategoryButton(100 + i, &selectedCategoryButton, guiSlotCategory, guiSlotCategorySelected);
_categoryButtons.push_back( button );
buttons.push_back( button );
}
const RecipeList& all = Recipes::getInstance()->getRecipes();
RecipeList filtered;
filtered.reserve(all.size());
// Apply size filter
for (unsigned int i = 0; i < all.size(); ++i) {
if (craftingSize >= all[i]->getCraftingSize())
filtered.push_back(all[i]);
}
// Filter by subclass impl
filterRecipes(filtered);
// Add items from filtered recipes
for (unsigned int i = 0; i < filtered.size(); ++i)
addItem(filtered[i]);
recheckRecipes();
}
void PaneCraftingScreen::setupPositions() {
// Left - Categories
const int buttonHeight = (height - 16) / (Mth::Max(numCategories, 4));
for (unsigned c = 0; c < _categoryButtons.size(); ++c) {
ImageButton* button = _categoryButtons[c];
button->x = (int)BorderPixels;
button->y = (int)BorderPixels + c * (1 + buttonHeight);
button->width = (int)buttonHeight;
button->height = (int)buttonHeight;
int icon = categoryIcons[c];
ImageDef def;
def.x = 0;
def.width = def.height = (float)buttonHeight;
def.name = "gui/spritesheet.png";
def.setSrc(IntRectangle(32 * (icon/2), 64 + (icon&1) * 32, 32, 32));
button->setImageDef(def, false);
}
// Right - Description
const int craftW = (int)(100 - 2 * BorderPixels - 0);
btnCraft.x = width - descFrameWidth + (descFrameWidth-craftW)/2 - 1;// width - descFrameWidth + (int)BorderPixels + 4;
btnCraft.y = 20;
btnCraft.setSize((float)craftW, 62);
btnClose.width = btnClose.height = 19;
btnClose.x = width - btnClose.width;
btnClose.y = 0;
// Middle - Scrolling pane
paneRect.x = buttonHeight + 2 * (int)BorderPixels;
paneRect.y = (int)BorderPixels + 2;
paneRect.w = width - paneRect.x - descFrameWidth;
paneRect.h = height - 2 * (int)BorderPixels - 4;
guiPaneFrame->setSize((float)paneRect.w + 2, (float)paneRect.h + 4);
guiBackground->setSize((float)width, (float)height);
guiSlotCategory->setSize((float)buttonHeight, (float)buttonHeight);
guiSlotCategorySelected->setSize((float)buttonHeight, (float)buttonHeight);
int oldCategory = currentCategory;
currentCategory = -1;
buttonClicked(_categoryButtons[pane?oldCategory:0]);
}
void PaneCraftingScreen::tick() {
if (pane) pane->tick();
}
void PaneCraftingScreen::render(int xm, int ym, float a) {
const int N = 5;
static StopwatchNLast r(N);
//renderBackground();
Tesselator& t = Tesselator::instance;
guiBackground->draw(t, 0, 0);
glEnable2(GL_ALPHA_TEST);
// Buttons (Left side + crafting)
super::render(xm, ym, a);
// Mid
r.start();
// Blit frame
guiPaneFrame->draw(t, (float)paneRect.x - 1, (float)paneRect.y - 2);
if (pane) pane->render(xm, ym, a);
r.stop();
//r.printEvery(N, "test");
const float slotWidth = (float)btnCraft.width / 2.0f;
const float slotHeight = (float)btnCraft.height / 2.0f;
const float slotBx = (float)btnCraft.x + slotWidth/2 - 8;
const float slotBy = (float)btnCraft.y + slotHeight/2 - 9;
ItemInstance reqItem;
// Right side
if (currentItem) {
t.beginOverride();
for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) {
const float xx = slotBx + slotWidth * (float)(i % 2);
const float yy = slotBy + slotHeight * (float)(i / 2);
CItem::ReqItem& req = currentItem->neededItems[i];
reqItem = req.item;
if (reqItem.getAuxValue() == -1) reqItem.setAuxValue(0);
ItemRenderer::renderGuiItem(NULL, minecraft->textures, &reqItem, xx, yy, 16, 16, true);
}
t.endOverrideAndDraw();
char buf[16];
const float scale = 2.0f / 3.0f;
const float invScale = 1.0f / scale;
t.beginOverride();
t.scale2d(scale, scale);
for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) {
const float xx = 4 + invScale * (slotBx + slotWidth * (float)(i % 2));
const float yy = 23 + invScale * (slotBy + slotHeight * (float)(i / 2));
CItem::ReqItem& req = currentItem->neededItems[i];
int bufIndex = 0;
bufIndex += Gui::itemCountItoa(&buf[bufIndex], req.has);
strcpy(&buf[bufIndex], "/"); bufIndex += 1;
bufIndex += Gui::itemCountItoa(&buf[bufIndex], req.item.count);
buf[bufIndex] = 0;
if (req.enough())
minecraft->font->drawShadow(buf, xx, yy, rgbActive);
else {
minecraft->font->draw(buf, xx+1, yy+1, rgbInactiveShadow);
minecraft->font->draw(buf, xx, yy, rgbInactive);
}
}
t.resetScale();
t.endOverrideAndDraw();
//minecraft->font->drawWordWrap(currentItemDesc, rightBx + 2, (float)btnCraft.y + btnCraft.h + 6, descFrameWidth-4, rgbActive);
minecraft->font->drawWordWrap(currentItemDesc, (float)btnCraft.x, (float)(btnCraft.y + btnCraft.height + 6), (float)btnCraft.width, rgbActive);
}
//glDisable2(GL_ALPHA_TEST);
}
void PaneCraftingScreen::buttonClicked(Button* button) {
if (button == &btnCraft)
craftSelectedItem();
if (button == &btnClose)
minecraft->setScreen(NULL);
// Did we click a category?
if (button->id >= 100 && button->id < 200) {
int categoryId = button->id - 100;
ItemList& cat = _categories[categoryId];
if (!cat.empty()) {
onItemSelected(categoryId, cat[0]);
pane->setSelected(0, true);
}
currentCategory = categoryId;
selectedCategoryButton = (CategoryButton*)button;
}
}
static void randomlyFillItemPack(ItemPack* ip, int numItems) {
int added = 0;
ItemInstance item(0, 1, 0);
while (added < numItems) {
int t = Mth::random(512);
if (!Item::items[t]) continue;
item.id = t;
int id = ItemPack::getIdForItemInstance(&item);
int count = Mth::random(10);
for (int i = 0; i < count; ++i)
ip->add(id);
++added;
}
}
static bool sortCanCraftPredicate(const CItem* a, const CItem* b) {
//if (a->maxBuildCount == 0 && b->maxBuildCount > 0) return false;
//if (b->maxBuildCount == 0 && a->maxBuildCount > 0) return true;
return a->sortText < b->sortText;
}
void PaneCraftingScreen::recheckRecipes() {
ItemPack ip;
if (minecraft->player && minecraft->player->inventory) {
Inventory* inv = (minecraft->player)->inventory;
for (int i = Inventory::MAX_SELECTION_SIZE; i < inv->getContainerSize(); ++i) {
if (ItemInstance* item = inv->getItem(i))
ip.add(ItemPack::getIdForItemInstance(item), item->count);
}
} else {
randomlyFillItemPack(&ip, 50);
}
ip.print();
Stopwatch w;
w.start();
for (unsigned int i = 0; i < _items.size(); ++i) {
CItem* item = _items[i];
item->neededItems.clear();
item->setCanCraft(true);
Recipe* recipe = item->recipe;
item->inventoryCount = ip.getCount(ItemPack::getIdForItemInstance(&item->item));
//item->maxBuildCount = recipe->getMaxCraftCount(ip);
// Override the canCraft thing, since I'm too lazy
// to fix the above (commented out) function
std::vector<ItemInstance> items = recipe->getItemPack().getItemInstances();
for (unsigned int j = 0; j < items.size(); ++j) {
ItemInstance& jtem = items[j];
int has = 0;
if (!Recipe::isAnyAuxValue(&jtem) && (jtem.getAuxValue() == Recipe::ANY_AUX_VALUE)) {
// If the aux value on the item matters, but the recipe says it doesn't,
// use this override (by fetching all items with aux-ids 0-15)
ItemInstance aux(jtem);
for (int i = 0; i < 16; ++i) {
aux.setAuxValue(i);
has += ip.getCount(ItemPack::getIdForItemInstance(&aux));
}
} else {
// Else just use the normal aux-value rules
has = ip.getCount(ItemPack::getIdForItemInstance(&jtem));
}
CItem::ReqItem req(jtem, has);
item->neededItems.push_back(req);
item->setCanCraft(item->canCraft() && req.enough());
}
}
w.stop();
w.printEvery(1, "> craft ");
for (unsigned int c = 0; c < _categories.size(); ++c)
std::stable_sort(_categories[c].begin(), _categories[c].end(), sortCanCraftPredicate);
}
void PaneCraftingScreen::addItem( Recipe* recipe )
{
ItemInstance instance = recipe->getResultItem();
Item* item = instance.getItem();
CItem* ci = new CItem(instance, recipe, instance.getName());//item->getDescriptionId());
if (item->id == Tile::cloth->id)
ci->sortText = "Wool " + ci->text;
if (item->id == Item::dye_powder->id)
ci->sortText = "ZDye " + ci->text;
_items.push_back(ci);
if (item->category < 0)
return;
for (int i = 0; i < (int)categoryBitmasks.size(); ++i) {
int bitmask = categoryBitmasks[i];
if ((bitmask & item->category) != 0)
_categories[i].push_back( ci );
}
}
void PaneCraftingScreen::onItemSelected(const ItemPane* forPane, int itemIndexInCurrentCategory) {
if (currentCategory >= (int)_categories.size()) return;
if (itemIndexInCurrentCategory >= (int)_categories[currentCategory].size()) return;
onItemSelected(currentCategory, _categories[currentCategory][itemIndexInCurrentCategory]);
}
void PaneCraftingScreen::onItemSelected(int buttonIndex, CItem* item) {
currentItem = item;
currentItemDesc = I18n::getDescriptionString(currentItem->item);
if (buttonIndex != currentCategory) {
// Clear item buttons for this category
clearCategoryItems();
// Setup new buttons for the items in this category
const int NumCategoryItems = _categories[buttonIndex].size();
if (pane) delete pane;
pane = new ItemPane(this, minecraft->textures, paneRect, NumCategoryItems, height, minecraft->height);
pane->f = minecraft->font;
currentCategory = buttonIndex;
}
}
void PaneCraftingScreen::clearCategoryItems()
{
for (unsigned int i = 0; i < currentCategoryButtons.size(); ++i) {
delete currentCategoryButtons[i];
}
currentCategoryButtons.clear();
}
void PaneCraftingScreen::keyPressed( int eventKey )
{
if (eventKey == Keyboard::KEY_ESCAPE) {
minecraft->setScreen(NULL);
//minecraft->grabMouse();
} else {
super::keyPressed(eventKey);
}
}
void PaneCraftingScreen::craftSelectedItem()
{
if (!currentItem)
return;
if (!currentItem->canCraft())
return;
ItemInstance resultItem = currentItem->item;
if (minecraft->player) {
// Remove all items required for the recipe and ...
for (unsigned int i = 0; i < currentItem->neededItems.size(); ++i) {
CItem::ReqItem& req = currentItem->neededItems[i];
// If the recipe allows any aux-value as ingredients, first deplete
// aux == 0 from inventory. Since I'm not sure if this always is
// correct, let's only do it for ingredient sandstone for now.
ItemInstance toRemove = req.item;
if (Tile::sandStone->id == req.item.id
&& Recipe::ANY_AUX_VALUE == req.item.getAuxValue()) {
toRemove.setAuxValue(0);
toRemove.count = minecraft->player->inventory->removeResource(toRemove, true);
toRemove.setAuxValue(Recipe::ANY_AUX_VALUE);
}
if (toRemove.count > 0) {
minecraft->player->inventory->removeResource(toRemove);
}
}
// ... add the new one! (in this order, to fill empty slots better)
// if it doesn't fit, throw it on the ground!
if (!minecraft->player->inventory->add(&resultItem)) {
minecraft->player->drop(new ItemInstance(resultItem), false);
}
recheckRecipes();
}
}
bool PaneCraftingScreen::renderGameBehind()
{
return false;
}
bool PaneCraftingScreen::closeOnPlayerHurt() {
return true;
}
void PaneCraftingScreen::filterRecipes(RecipeList& recipes) {
for (int i = recipes.size() - 1; i >= 0; --i) {
if (!filterRecipe(*recipes[i]))
recipes.erase(recipes.begin() + i);
}
}
const std::vector<CItem*>& PaneCraftingScreen::getItems(const ItemPane* forPane)
{
return _categories[currentCategory];
}
void PaneCraftingScreen::setSingleCategoryAndIcon(int categoryBitmask, int categoryIcon) {
assert(!minecraft && "setSingleCategoryAndIcon needs to be called from subclass constructor!\n");
numCategories = 1;
categoryIcons.clear();
categoryIcons.push_back(categoryIcon);
categoryBitmasks.clear();
categoryBitmasks.push_back(categoryBitmask);
}
//
// Craft button
//
CraftButton::CraftButton( int id)
: super(id, ""),
bg(NULL),
bgSelected(NULL),
numItems(0)
{
}
CraftButton::~CraftButton()
{
delete bg;
delete bgSelected;
}
void CraftButton::setSize(float w, float h ) {
this->width = (int)w;
this->height = (int)h;
if (bg && bgSelected) {
bg->setSize(w, h);
bgSelected->setSize(w, h);
}
}
void CraftButton::init( Textures* textures)
{
NinePatchFactory builder(textures, "gui/spritesheet.png");
bg = builder.createSymmetrical(IntRectangle(112, 0, 8, 67), 2, 2);
bgSelected = builder.createSymmetrical(IntRectangle(120, 0, 8, 67), 2, 2);
}
IntRectangle CraftButton::getItemPos( int i )
{
return IntRectangle();
}
void CraftButton::renderBg(Minecraft* minecraft, int xm, int ym) {
if (!bg || !bgSelected)
return;
//fill(x+1, y+1, x+w-1, y+h-1, 0xff999999);
bool hovered = active && (minecraft->useTouchscreen()?
(_currentlyDown && xm >= x && ym >= y && xm < x + width && ym < y + height) : false);
if (hovered || selected)
bgSelected->draw(Tesselator::instance, (float)x, (float)y);
else
bg->draw(Tesselator::instance, (float)x, (float)y);
}

View File

@@ -0,0 +1,106 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS_CRAFT_PaneCraftingScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS_CRAFT_PaneCraftingScreen_H__
#include "../../Screen.h"
#include "../../../../world/item/crafting/Recipes.h"
#include "../../../../world/item/ItemInstance.h"
#include "../../components/ScrollingPane.h"
#include "../../components/ImageButton.h"
#include "../../components/ItemPane.h"
class Font;
class CItem;
class Textures;
class NinePatchLayer;
class CraftButton: public ImageButton
{
typedef ImageButton super;
public:
CraftButton(int id);
~CraftButton();
void init(Textures*);
void setSize(float w, float h);
void setNumItems(int i) { numItems = i; }
IntRectangle getItemPos(int i);
void renderBg(Minecraft* minecraft, int xm, int ym);
private:
NinePatchLayer* bg;
NinePatchLayer* bgSelected;
int numItems;
};
class PaneCraftingScreen: public Screen,
public IItemPaneCallback
{
typedef Screen super;
typedef std::vector<CItem*> ItemList;
public:
PaneCraftingScreen(int craftingSize);
~PaneCraftingScreen();
void init();
void setupPositions();
void tick();
void render(int xm, int ym, float a);
bool renderGameBehind();
bool closeOnPlayerHurt();
void buttonClicked(Button* button);
void keyPressed( int eventKey );
// IItemPaneCallback
void onItemSelected(const ItemPane* forPane, int itemIndexInCurrentCategory);
const std::vector<CItem*>& getItems(const ItemPane* forPane);
protected:
void setSingleCategoryAndIcon(int categoryBitmask, int categoryIcon);
private:
/// Filter out non craftable recipes.
/// The default implementation calls bool filterRecipe(r) for every
/// Recipe r and keeps the ones that returned true.
/// A crafting size filter has already been applied.
virtual void filterRecipes(RecipeList& recipes);
virtual bool filterRecipe(const Recipe& recipe) = 0;
void initCategories();
void addItem(Recipe* recipe);
void recheckRecipes();
void onItemSelected(int buttonIndex, CItem* item);
void clearCategoryItems();
void craftSelectedItem();
std::vector<ImageButton*> _categoryButtons;
ItemList _items;
std::vector<ItemList> _categories;
int currentCategory;
CItem* currentItem;
std::string currentItemDesc;
std::vector<Button*> currentCategoryButtons;
ImageButton btnClose;
CraftButton btnCraft;
int craftingSize;
ItemPane* pane;
IntRectangle paneRect;
//int paneX;
//int paneW;
int numCategories;
std::vector<int> categoryBitmasks;
std::vector<int> categoryIcons;
ImageButton* selectedCategoryButton;
// GUI elements such as 9-Patches
NinePatchLayer* guiBackground;
NinePatchLayer* guiSlotCategory;
NinePatchLayer* guiSlotCategorySelected;
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS_CRAFT_PaneCraftingScreen_H__*/

View File

@@ -0,0 +1,17 @@
#include "StonecutterScreen.h"
#include "CraftingFilters.h"
#include "../../../../world/level/material/Material.h"
#include "../../../../world/item/ItemCategory.h"
StonecutterScreen::StonecutterScreen()
: super(Recipe::SIZE_3X3)
{
setSingleCategoryAndIcon(ItemCategory::Structures, 5);
}
StonecutterScreen::~StonecutterScreen() {
}
bool StonecutterScreen::filterRecipe(const Recipe& r) {
return CraftingFilters::isStonecutterItem(r.getResultItem());
}

View File

@@ -0,0 +1,17 @@
#ifndef NET_MINECRAFT_CLIENT_GUI_SCREENS_CRAFT_StonecutterScreen_H__
#define NET_MINECRAFT_CLIENT_GUI_SCREENS_CRAFT_StonecutterScreen_H__
#include "PaneCraftingScreen.h"
class StonecutterScreen: public PaneCraftingScreen
{
typedef PaneCraftingScreen super;
public:
StonecutterScreen();
~StonecutterScreen();
private:
bool filterRecipe(const Recipe& r);
};
#endif /*NET_MINECRAFT_CLIENT_GUI_SCREENS_CRAFT_StonecutterScreen_H__*/

View File

@@ -0,0 +1,15 @@
#include "WorkbenchScreen.h"
#include "CraftingFilters.h"
#include "../../../../world/level/material/Material.h"
WorkbenchScreen::WorkbenchScreen(int craftingSize)
: super(craftingSize)
{
}
WorkbenchScreen::~WorkbenchScreen() {
}
bool WorkbenchScreen::filterRecipe(const Recipe& r) {
return !CraftingFilters::isStonecutterItem(r.getResultItem());
}

Some files were not shown because too many files have changed in this diff Show More