Files
mcpe/source/client/player/input/UnifiedTurnBuild.cpp
2023-12-02 21:04:21 +03:00

243 lines
5.4 KiB
C++

/********************************************************************
Minecraft: Pocket Edition - Decompilation Project
Copyright (C) 2023 iProgramInCpp
The following code is licensed under the BSD 1 clause license.
SPDX-License-Identifier: BSD-1-Clause
********************************************************************/
#include "UnifiedTurnBuild.hpp"
#include "Multitouch.hpp"
#include "common/Utils.hpp"
#include "world/entity/Player.hpp"
UnifiedTurnBuild::UnifiedTurnBuild(int a, int width, int height, float d, float e, IInputHolder* pHolder) :
field_C(a),
field_10(0),
m_screenArea(-1, -1, 0, 0),
field_40(-1, -1, 0, 0),
field_58(-1, -1, 0, 0),
m_pInputHolder(pHolder),
field_78(0.0f),
field_7C(0.0f),
m_bWasTouched(false),
field_BC(0.0f),
field_C0(d),
field_C4(e),
m_pPlayer(nullptr),
field_D8(0)
{
m_includeExcludeArea.field_4 = false;
UnifiedTurnBuild::setScreenSize(width, height);
field_B8 = getTimeS();
field_CC = field_B8;
field_D0 = 0;
field_24 = 0;
field_D4 = false;
}
void UnifiedTurnBuild::setScreenSize(int width, int height)
{
m_screenArea = RectangleArea(0.0f, 0.0f, float(width), float(height));
field_40.right += 10.0f + 0.05f * (field_40.right - field_40.left);
field_40.top -= 10.0f + 0.05f * (field_40.bottom - field_40.top);
m_includeExcludeArea.clear();
m_includeExcludeArea.include(&m_screenArea);
m_includeExcludeArea.exclude(&field_40);
m_includeExcludeArea.exclude(&field_58);
m_touchAreaModel.clear();
m_touchAreaModel.addArea(100, &m_includeExcludeArea);
}
TurnDelta UnifiedTurnBuild::getTurnDelta()
{
float timeS = getTimeS();
float m1 = 0.0f, m2 = 0.0f;
float xd = 0.0f, yd = 0.0f;
bool touched = false;
const int* activePtrs;
int activePtrCount = Multitouch::getActivePointerIds(&activePtrs);
for (int i = 0; i < activePtrCount; i++)
{
int finger = activePtrs[i];
int x = Multitouch::getX(finger);
int y = Multitouch::getY(finger);
if (m_touchAreaModel.getPointerId(x, y, finger) == 100)
{
touched = true;
m1 = float(x) * 0.5f;
m2 = float(y) * -0.5f;
break;
}
}
if (touched && !m_bWasTouched) // if this is the first frame we were touched
{
field_B8 = timeS;
field_BC = 0.0f;
bool b2 = m_pPlayer && getSpeedSquared(m_pPlayer) > 0.01f;
field_D8 = 1;
field_D4 = !b2;
field_24 = 0;
}
else if (m_bWasTouched && !touched) // if that was the last frame we were touched
{
field_24 = 0;
field_D8 = 0;
}
if (field_C == 2 && (m_bWasTouched || touched))
{
// note: return value dropped
(void) getDeltaTime();
if (!m_bWasTouched)
{
field_78 = m1;
field_7C = m2;
}
if (touched)
{
xd = field_C4 * linearTransform(m1 - field_78, 0.0f, 1.0f, false);
yd = field_C4 * linearTransform(m2 - field_7C, 0.0f, 1.0f, false);
float c3 = abs(xd) * abs(yd);
if (field_C0 < c3)
c3 = yd = xd = 0.0f;
field_BC += c3;
if (field_D8 == 1 && field_BC >= 20.0f)
field_D8 = 2;
if (field_D8 == 1 && timeS - field_B8 >= 0.4f)
{
bool check = m_pPlayer && getSpeedSquared(m_pPlayer) > 0.01f;
if (field_BC > 20.0f || check)
field_D8 = 2;
else
field_D8 = 3;
}
if (field_D8 == 1)
{
xd = yd = 0.0f;
}
field_78 = m1;
field_7C = m2;
}
}
if (field_D4)
{
// Yes, again, this is what IDA gave me. It was either a switch that the compiler
// for some reason forgot to optimize into a jump table, or was actually an if chain.
// I believe it's the latter though because the build I'm reversing (0.1.1j) is unoptimized)
if (field_D8 == 1)
m_pInputHolder->m_feedbackAlpha = m_smoothFloat.getNewDeltaValue((timeS - field_B8) / 0.4f, 0.05f);
else if (field_D8 == 3)
m_pInputHolder->m_feedbackAlpha = m_smoothFloat.getNewDeltaValue(1.0f, 0.25f);
else if (field_D8 == 2)
m_pInputHolder->m_feedbackAlpha = m_smoothFloat.getNewDeltaValue(-0.05f, 0.5f);
else if (field_D8 == 0)
m_pInputHolder->m_feedbackAlpha = m_smoothFloat.getNewDeltaValue(-0.05f, 0.5f);
}
else
{
m_pInputHolder->m_feedbackAlpha = -0.05f;
}
m_bWasTouched = touched;
return TurnDelta(xd, -yd);
}
bool UnifiedTurnBuild::smoothTurning()
{
return true;
}
bool UnifiedTurnBuild::tickBuild(Player* pPlayer, BuildActionIntention* pIntention)
{
m_pPlayer = pPlayer;
if (field_D8 == 3)
{
if (field_24 != 1)
{
*pIntention = BuildActionIntention(INTENT_FIRST_REMOVE);
field_24 = 1;
}
else
{
*pIntention = BuildActionIntention(INTENT_HELD);
}
return true;
}
Multitouch::rewind();
float timeS = getTimeS();
field_10 = 0;
bool wroteIntention = false;
while (Multitouch::next())
{
MouseAction* pEvent = Multitouch::getEvent();
if (pEvent->_buttonType)
{
int finger = m_touchAreaModel.getPointerId(pEvent->_posX, pEvent->_posY, pEvent->_fingerId);
if (finger == 100)
{
if (field_BC > 20.0f || pEvent->_buttonState || wroteIntention)
{
if (pEvent->_buttonState)
{
field_CC = timeS;
field_D0 = 0;
field_D8 = 1;
}
}
else
{
float delta = timeS - field_CC;
if (field_D8 <= 1 && delta >= 0.0f && delta < 0.25f)
{
*pIntention = BuildActionIntention(INTENT_CLICKED);
wroteIntention = true;
}
field_D8 = 0;
}
}
}
}
return wroteIntention;
}
bool UnifiedTurnBuild::isInsideArea(float x, float y)
{
return m_includeExcludeArea.isInside(x, y);
}
float UnifiedTurnBuild::getSpeedSquared(Entity* pEnt)
{
return (pEnt->m_pos - pEnt->field_3C).lengthSqr();
}