WIP Android Port (#79)

* WIP Android Port

Android port. Still needs touch controls and mouse turning (if that's even possible on android) and file saving and SoundSystemSL
You control the camera and movement with your controller for now. You can navigate the gui using touch.
Options.cpp,LocalPlayer.cpp,Minecraft.cpp is configured to use controller.
Blocked out some code in ControllerTurnInput.cpp,Controller.cpp that didn't make sense.

* Fix glClear

glClear is supossed to use GL_DEPTH_BUFFER_BIT (thx TheBrokenRail)

* * Fix build.

* * Ignore assets.

* * More stuff

* * Fix more build errors.

* * It finally built

What I needed to do is rebuild the debug keystore because apparently android studio created it with sha1 digest alg which isn't supported by ant

* * Clean up filters.

* * Add cramped mode to the pause screen.

* * Fix a bug with the hotbar

* * In NinecraftApp::handleBack, pause the game if there is no screen.

* * AppPlatform_android: Add placeholder SoundSystem instance till we get SoundSystemSL working

* * Add properly working touch code.

* * Oh, remove some testing things

* * Fix state resetting when going in background and back in foreground
* Fix bug where the sky isn't being regenerated on graphics reset
* Fix bug where the m_currBoundTex isn't reset in Textures::clear potentially leaving a texture with that ID unassigned and corrupted
* Fix bug in CThread where the thread is detached and then also joined.
* Don't log anything if the program isn't in debug mode.

* * Add virtual keyboard support.

The screen instance slides so that the focused text box is kept visible.

* Rename from com.minecraftcpp to com.reminecraftpe

---------

Co-authored-by: iProgramInCpp <iprogramincpp@gmail.com>
This commit is contained in:
f
2023-11-03 11:54:39 +01:00
committed by GitHub
parent f119d89048
commit f83ead9f8d
59 changed files with 5742 additions and 424 deletions

View File

@@ -417,7 +417,7 @@ int Gui::getSlotIdAt(int mouseX, int mouseY)
if (slotX >= 0)
slotX--;
if (slotX > getNumSlots())
if (slotX >= getNumSlots())
slotX = -1;
return slotX;

View File

@@ -15,6 +15,7 @@ class GuiComponent
{
public:
GuiComponent();
virtual ~GuiComponent() {}
void blit(int dstX, int dstY, int srcX, int srcY, int dstWidth, int dstHeight, int srcWidth, int srcHeight);
void drawCenteredString(Font*, const std::string&, int cx, int cy, int color);

View File

@@ -15,6 +15,7 @@ Screen::Screen()
field_10 = false;
m_tabButtonIndex = 0;
m_pClickedButton = 0;
m_yOffset = -1;
}
Screen::~Screen()
@@ -253,6 +254,25 @@ void Screen::mouseClicked(int xPos, int yPos, int d) // d = clicked?
TextInputBox* textInput = m_textInputs[i];
textInput->onClick(xPos, yPos);
}
// if the keyboard is shown:
if (m_pMinecraft->platform()->getKeyboardUpOffset())
{
// if there are none focused at the moment:
bool areAnyFocused = false;
for (int i = 0; i < int(m_textInputs.size()); i++)
{
TextInputBox* textInput = m_textInputs[i];
if (textInput->m_bFocused)
{
areAnyFocused = true;
break;
}
}
if (!areAnyFocused)
m_pMinecraft->platform()->showKeyboard(false);
}
#endif
}
@@ -306,6 +326,59 @@ void Screen::setSize(int width, int height)
init();
}
void Screen::onRender(int mouseX, int mouseY, float f)
{
m_yOffset = getYOffset();
if (m_yOffset != 0) {
// push the entire screen up
glPushMatrix();
glTranslatef(0.0f, -float(m_yOffset), 0.0f);
}
render(mouseX, mouseY, f);
if (m_yOffset != 0)
glPopMatrix();
}
int Screen::getYOffset()
{
int keybOffset = m_pMinecraft->platform()->getKeyboardUpOffset();
if (!keybOffset)
return 0;
int offset = 0;
// look through every text box, see if one's open
// and determine its offset from there
for (int i = 0; i < int(m_textInputs.size()); i++)
{
TextInputBox* pBox = m_textInputs[i];
if (!pBox->m_bFocused)
continue;
int heightLeft = m_height - int(float(keybOffset) * Gui::InvGuiScale);
// we want to keep the center of the text box in the center of the screen
int textCenterY = pBox->m_yPos + pBox->m_height / 2;
int scrnCenterY = heightLeft / 2;
int diff = textCenterY - scrnCenterY;
// Prevent the difference from revealing the outside of the screen.
if (diff > m_height - heightLeft)
diff = m_height - heightLeft;
if (diff < 0)
diff = 0;
offset = diff;
break;
}
return offset;
}
void Screen::updateEvents()
{
if (field_10) return;
@@ -329,9 +402,9 @@ void Screen::mouseEvent()
if (pAction->isButton())
{
if (Mouse::getEventButtonState())
mouseClicked (m_width * pAction->_posX / Minecraft::width, m_height * pAction->_posY / Minecraft::height - 1, Mouse::getEventButton());
mouseClicked (m_width * pAction->_posX / Minecraft::width, m_height * pAction->_posY / Minecraft::height - 1 + getYOffset(), Mouse::getEventButton());
else
mouseReleased(m_width * pAction->_posX / Minecraft::width, m_height * pAction->_posY / Minecraft::height - 1, Mouse::getEventButton());
mouseReleased(m_width * pAction->_posX / Minecraft::width, m_height * pAction->_posY / Minecraft::height - 1 + getYOffset(), Mouse::getEventButton());
}
}
@@ -339,7 +412,9 @@ void Screen::renderBackground(int unk)
{
if (m_pMinecraft->isLevelGenerated())
{
fillGradient(0, 0, m_width, m_height, 0xC0101010, 0xD0101010);
// draw the background offset by the Y offset so that the smaller virtual
// keyboards don't reveal undrawn areas
fillGradient(0, m_yOffset, m_width, m_height, 0xC0101010, 0xD0101010);
}
else
{
@@ -361,11 +436,13 @@ void Screen::renderDirtBackground(int unk)
Tesselator& t = Tesselator::instance;
t.begin();
t.offset(0, m_yOffset, 0);
t.color(0x404040);
t.vertexUV(0.0f, float(m_height), 0, 0, float(unk) + float(m_height) / 32.0f);
t.vertexUV(float(m_width), float(m_height), 0, float(m_width) / 32.0f, float(unk) + float(m_height) / 32.0f);
t.vertexUV(float(m_width), 0, 0, float(m_width) / 32.0f, float(unk) + 0.0f);
t.vertexUV(0.0f, 0, 0, 0, float(unk) + 0.0f);
t.offset(0, 0, 0);
t.draw();
}

View File

@@ -14,6 +14,7 @@
#include "components/TextInputBox.hpp"
class Button;
class TextInputBox;
class Screen : public GuiComponent
{
@@ -24,6 +25,8 @@ public:
void init(Minecraft*, int, int);
void updateTabButtonSelection();
void setSize(int width, int height);
void onRender(int mouseX, int mouseY, float f);
int getYOffset();
virtual void render(int, int, float);
virtual void init();
@@ -62,6 +65,7 @@ public:
#ifndef ORIGINAL_CODE
std::vector<TextInputBox*> m_textInputs;
int m_yOffset;
#endif
};

View File

@@ -15,6 +15,7 @@ class ScrolledSelectionList : public GuiComponent
{
public:
ScrolledSelectionList(Minecraft*, int, int, int, int, int);
virtual ~ScrolledSelectionList() {}
virtual void setRenderSelection(bool);
virtual int getNumberOfItems() = 0;

View File

@@ -10,7 +10,11 @@
#include "client/app/Minecraft.hpp"
#ifndef ORIGINAL_CODE
TextInputBox::TextInputBox(int id, int x, int y, int width, int height, const std::string& placeholder, const std::string& text)
#ifdef __ANDROID__
#define HANDLE_CHARS_SEPARATELY // faked though, see platforms/android/minecraftcpp/minecraftcpp.NativeActivity/main.cpp
#endif
TextInputBox::TextInputBox(Screen* parent, int id, int x, int y, int width, int height, const std::string& placeholder, const std::string& text)
{
m_ID = id;
m_xPos = x;
@@ -25,6 +29,7 @@ TextInputBox::TextInputBox(int id, int x, int y, int width, int height, const st
m_insertHead = 0;
m_lastFlashed = 0;
m_pFont = nullptr;
m_pParent = parent;
}
void TextInputBox::init(Font* pFont)
@@ -185,7 +190,12 @@ void TextInputBox::setFocused(bool b)
m_lastFlashed = getTimeMs();
m_bCursorOn = true;
m_insertHead = int(m_text.size());
m_pParent->m_pMinecraft->platform()->showKeyboard(true);
}
// don't actually hide the keyboard when unfocusing
// - we may be undoing the work of another text box
}
void TextInputBox::onClick(int x, int y)

View File

@@ -9,8 +9,10 @@
#pragma once
#include "../GuiComponent.hpp"
#include "../Screen.hpp"
#include "common/Utils.hpp"
class Screen;
class Minecraft;
// @NOTE: This is NOT original Mojang code.
@@ -20,7 +22,7 @@ class Minecraft;
class TextInputBox : public GuiComponent
{
public:
TextInputBox(int id, int x, int y, int width = 200, int height = 12, const std::string& placeholder = "", const std::string& text = "");
TextInputBox(Screen*, int id, int x, int y, int width = 200, int height = 12, const std::string& placeholder = "", const std::string& text = "");
void init(Font* pFont);
void setEnabled(bool bEnabled);
@@ -46,6 +48,7 @@ public:
int m_insertHead;
int m_lastFlashed;
Font* m_pFont;
Screen* m_pParent;
};
#endif

View File

@@ -10,7 +10,7 @@
// @NOTE: This is unused.
ChatScreen::ChatScreen(bool slash) : m_textChat(1, 0, 0), m_btnSend(2, 0, 0, "Send")
ChatScreen::ChatScreen(bool slash) : m_textChat(this, 1, 0, 0), m_btnSend(2, 0, 0, "Send")
{
if (slash)
m_textChat.m_text = "/";

View File

@@ -9,22 +9,22 @@
#include "ConfirmScreen.hpp"
ConfirmScreen::ConfirmScreen(Screen* pScreen, const std::string& line1, const std::string& line2, int x) :
m_btnOK (0, 0, 0, "Ok"),
m_btnCancel(1, 0, 0, "Cancel"),
m_pScreen(pScreen),
field_40(x),
m_textLine1(line1),
m_textLine2(line2),
m_pScreen(pScreen),
field_40(x)
m_btnOK (0, 0, 0, "Ok"),
m_btnCancel(1, 0, 0, "Cancel")
{
}
ConfirmScreen::ConfirmScreen(Screen* pScreen, const std::string& line1, const std::string& line2, const std::string& ok, const std::string& cancel, int x) :
m_btnOK (0, 0, 0, ok),
m_btnCancel(1, 0, 0, cancel),
m_pScreen(pScreen),
field_40(x),
m_textLine1(line1),
m_textLine2(line2),
m_pScreen(pScreen),
field_40(x)
m_btnOK (0, 0, 0, ok),
m_btnCancel(1, 0, 0, cancel)
{
}

View File

@@ -12,13 +12,15 @@
#include "common/Util.hpp"
CreateWorldScreen::CreateWorldScreen() :
m_textName(1, 0, 0, 0, 0, "", "Unnamed world"),
m_textSeed(2, 0, 0, 0, 0, ""),
m_textName(this, 1, 0, 0, 0, 0, "", "Unnamed world"),
m_textSeed(this, 2, 0, 0, 0, 0, ""),
m_btnBack(3, "Cancel"),
m_btnCreate(4, "Create New World")
{
}
#define CRAMPED() (100 + 32 + 58 > m_height)
void CreateWorldScreen::init()
{
m_textName.m_width = m_textSeed.m_width = 200;
@@ -43,6 +45,19 @@ void CreateWorldScreen::init()
m_buttonTabList.push_back(&m_btnCreate);
m_textName.init(m_pFont);
m_textSeed.init(m_pFont);
// 100 - yPos of textSeed
// 32 - offset + height of "Leave blank for random" text
// 58 - approximately the Y position of the create button
bool crampedMode = CRAMPED();
if (crampedMode)
{
// crush everything down as much as we can
m_textName.m_yPos = 40;
m_textSeed.m_yPos = 80;
m_btnCreate.m_yPos += 10;
m_btnBack.m_yPos += 5;
}
}
static char g_CreateWorldFilterArray[] = { '/','\n','\r','\x09','\0','\xC','`','?','*','\\','<','>','|','"',':' };
@@ -114,7 +129,7 @@ void CreateWorldScreen::render(int mouseX, int mouseY, float f)
renderBackground();
Screen::render(mouseX, mouseY, f);
drawCenteredString(m_pFont, "Create New World", m_width / 2, 30, 0xFFFFFF);
drawCenteredString(m_pFont, "Create New World", m_width / 2, CRAMPED() ? 10 : 30, 0xFFFFFF);
drawString(m_pFont, "World name", m_textName.m_xPos, m_textName.m_yPos - 10, 0xDDDDDD);
drawString(m_pFont, "Seed for the World Generator", m_textSeed.m_xPos, m_textSeed.m_yPos - 10, 0xDDDDDD);
drawString(m_pFont, "Leave blank for a random seed", m_textSeed.m_xPos, m_textSeed.m_yPos + 22, 0x999999);

View File

@@ -12,9 +12,9 @@
#include "common/Util.hpp"
DirectConnectScreen::DirectConnectScreen() :
m_textAddress(1, 0, 0, 0, 0, "Server address"),
m_btnJoin(2, "Connect"),
m_btnQuit(3, "Cancel")
m_textAddress(this, 1, 0, 0, 0, 0, "Server address"),
m_btnQuit(3, "Cancel"),
m_btnJoin(2, "Connect")
{}
void DirectConnectScreen::init()

View File

@@ -11,7 +11,7 @@
#include "network/ServerSideNetworkHandler.hpp"
PauseScreen::PauseScreen() :
field_3C(0),
//field_3C(0),
field_40(0),
m_btnBack(1, "Back to game"),
m_btnQuit(2, "Quit to title"),
@@ -25,27 +25,45 @@ PauseScreen::PauseScreen() :
void PauseScreen::init()
{
bool bAddVisibleButton = m_pMinecraft->m_pRakNetInstance && m_pMinecraft->m_pRakNetInstance->m_bIsHost;
int nButtons = 2;
if (bAddVisibleButton)
nButtons++;
#ifdef ENH_ADD_OPTIONS_PAUSE
nButtons++;
#endif
int currY = 48, inc = 32;
bool cramped = m_height < currY + inc * nButtons + 10; // also add some padding
if (cramped)
inc = 25;
m_btnQuit.m_width = 160;
m_btnBack.m_width = 160;
m_btnVisible.m_width = 160;
m_btnQuitAndCopy.m_width = 160;
m_btnBack.m_yPos = 48;
m_btnQuit.m_yPos = 80;
m_btnBack.m_yPos = currY; currY += inc;
m_btnQuit.m_yPos = currY; currY += inc;
m_btnBack.m_xPos = (m_width - 160) / 2;
m_btnQuit.m_xPos = (m_width - 160) / 2;
m_btnVisible.m_xPos = (m_width - 160) / 2;
m_btnQuitAndCopy.m_xPos = (m_width - 160) / 2;
m_btnVisible.m_yPos = 112;
m_btnQuitAndCopy.m_yPos = 112;
m_btnVisible.m_yPos =
m_btnQuitAndCopy.m_yPos = currY;
#ifdef ENH_ADD_OPTIONS_PAUSE
// TODO: when visible or quit&copy are on, lower this
m_btnOptions.m_width = 160;
m_btnOptions.m_yPos = 112;
m_btnOptions.m_yPos = currY;
m_btnOptions.m_xPos = m_btnBack.m_xPos;
#endif
currY += inc;
// add the buttons to the screen:
m_buttons.push_back(&m_btnBack);
@@ -57,12 +75,12 @@ void PauseScreen::init()
//m_buttons.push_back(&m_btnQuitAndCopy);
if (m_pMinecraft->m_pRakNetInstance && m_pMinecraft->m_pRakNetInstance->m_bIsHost)
if (bAddVisibleButton)
{
updateServerVisibilityText();
m_buttons.push_back(&m_btnVisible);
#ifdef ENH_ADD_OPTIONS_PAUSE
m_btnOptions.m_yPos += 32;
m_btnOptions.m_yPos += inc;
#endif
}

View File

@@ -22,7 +22,7 @@ public:
void updateServerVisibilityText();
private:
int field_3C;
//int field_3C;
int field_40;
Button m_btnBack;
Button m_btnQuit;