298 lines
10 KiB
C++
298 lines
10 KiB
C++
/*
|
|
Copyright 2016-2017 sub1to
|
|
|
|
This file is part of subVersion GTA:O SC External Hack.
|
|
|
|
subVersion GTA:O SC External Hack is free software: you can redistribute
|
|
it and/or modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
subVersion GTA:O SC External Hack is distributed in the hope that it
|
|
will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
|
the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with subVersion GTA:O SC External Hack. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
|
|
D3D9Render::D3D9Render() :
|
|
m_nFont(0)
|
|
{
|
|
|
|
}
|
|
D3D9Render::~D3D9Render()
|
|
{
|
|
this->releaseFont();
|
|
m_pVertexBuffer->Release(); //close and release vertex buffer
|
|
m_pD3dDev->Release(); // close and release the 3D device
|
|
m_pD3d->Release(); // close and release Direct3D
|
|
}
|
|
|
|
bool D3D9Render::init(HWND hWnd)
|
|
{
|
|
m_pD3d = Direct3DCreate9(D3D_SDK_VERSION); //create d3d9 interface
|
|
|
|
ZeroMemory(&m_d3dParam, sizeof(m_d3dParam)); //clear the struct
|
|
|
|
m_d3dParam.Windowed = true;
|
|
m_d3dParam.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
m_d3dParam.hDeviceWindow = hWnd;
|
|
m_d3dParam.BackBufferHeight = m_screen.h;
|
|
m_d3dParam.BackBufferWidth = m_screen.w;
|
|
m_d3dParam.MultiSampleQuality = D3DMULTISAMPLE_NONE;
|
|
m_d3dParam.BackBufferFormat = D3DFMT_A8R8G8B8;
|
|
|
|
m_pD3d->CreateDevice( D3DADAPTER_DEFAULT,
|
|
D3DDEVTYPE_HAL,
|
|
hWnd,
|
|
D3DCREATE_HARDWARE_VERTEXPROCESSING,
|
|
&m_d3dParam,
|
|
&m_pD3dDev);
|
|
|
|
//create vertex buffer
|
|
m_pD3dDev->CreateVertexBuffer( 4 * sizeof(Vertex),
|
|
0,
|
|
VERTEX_FORMAT,
|
|
D3DPOOL_DEFAULT, //managed = video ram; D3DPOOL_DEFAULT = auto
|
|
&m_pVertexBuffer, //vertex buffer interface
|
|
NULL);
|
|
|
|
this->createFont("Verdana", 14, true, false);
|
|
this->createFont("Verdana", 14, false, false);
|
|
this->createFont("Verdana", 18, true, false);
|
|
|
|
m_pD3dDev->SetFVF(VERTEX_FORMAT);// select which vertex format to use
|
|
|
|
return true;
|
|
}
|
|
|
|
static std::string floatToString(float val) {
|
|
auto res = std::to_string(val);
|
|
const std::string format("$1");
|
|
std::regex r("(\\d*)\\.0{6}|");
|
|
std::regex r2("(\\d*\\.{1}0*[^0]+)0*");
|
|
res = std::regex_replace(res, r2, format);
|
|
res = std::regex_replace(res, r, format);
|
|
return res;
|
|
}
|
|
|
|
bool D3D9Render::render()
|
|
{
|
|
m_pD3dDev->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0,0,0,0), 1.f, 0);
|
|
m_pD3dDev->BeginScene();
|
|
|
|
if(g_pSettings->isMenuActive() && g_pMemMan->getWindow() == GetForegroundWindow())
|
|
{
|
|
//Draw header
|
|
this->drawBoxBorder(0, 0, LAYOUT_ELEMENT_WIDTH, LAYOUT_ELEMENT_HEIGHT, LAYOUT_BORDER_SIZE, LAYOUT_COLOR_BACKGROUND, LAYOUT_COLOR_BORDER);
|
|
this->drawText(m_szWindowTitle, 0, 0, LAYOUT_ELEMENT_WIDTH, LAYOUT_ELEMENT_HEIGHT, 2, LAYOUT_COLOR_TEXT, DT_CENTER | DT_VCENTER);
|
|
|
|
if (this->m_bMBShowing)
|
|
{
|
|
this->drawBoxBorder(LAYOUT_ELEMENT_WIDTH + 10, 0, LAYOUT_MB_WIDTH, LAYOUT_ELEMENT_HEIGHT, LAYOUT_BORDER_SIZE, LAYOUT_COLOR_BACKGROUND, LAYOUT_COLOR_BORDER);
|
|
this->drawText(this->m_sTitle, LAYOUT_ELEMENT_WIDTH + 10, 0, LAYOUT_MB_WIDTH, LAYOUT_ELEMENT_HEIGHT, 2, LAYOUT_COLOR_TEXT, DT_CENTER | DT_VCENTER);
|
|
this->drawBoxBorder(LAYOUT_ELEMENT_WIDTH + 10, LAYOUT_ELEMENT_HEIGHT, LAYOUT_MB_WIDTH, LAYOUT_MB_HEIGHT, LAYOUT_BORDER_SIZE, LAYOUT_COLOR_BACKGROUND, LAYOUT_COLOR_BORDER);
|
|
this->drawText(this->m_sDetail, LAYOUT_ELEMENT_WIDTH + 10, LAYOUT_ELEMENT_HEIGHT, LAYOUT_MB_WIDTH , LAYOUT_MB_HEIGHT, 0, LAYOUT_COLOR_TEXT, DT_CENTER | DT_VCENTER);
|
|
}
|
|
|
|
//prevent race conditions
|
|
while(!g_pSettings->lockFeatureCur())
|
|
Sleep(1);
|
|
|
|
//draw tabs
|
|
for(int i = 0; i < g_pSettings->getFeatureCategoryCount(); i++)
|
|
{
|
|
featCat* tab = g_pSettings->getFeatureCategory(i);
|
|
int x = (LAYOUT_ELEMENT_WIDTH / g_pSettings->getFeatureCategoryCount()) * i,
|
|
y = LAYOUT_ELEMENT_HEIGHT * 1,
|
|
w = LAYOUT_ELEMENT_WIDTH / g_pSettings->getFeatureCategoryCount(),
|
|
h = LAYOUT_ELEMENT_HEIGHT;
|
|
|
|
this->drawBoxBorder( x, y, w, h, LAYOUT_BORDER_SIZE,
|
|
(i == g_pSettings->getActiveCat()) ? LAYOUT_COLOR_ACTIVE_BG : LAYOUT_COLOR_BACKGROUND,
|
|
(i == g_pSettings->getActiveCat()) ? LAYOUT_COLOR_ACTIVE_BORDER : LAYOUT_COLOR_BORDER);
|
|
this->drawText(tab->m_szName, x, y, w - 1, h, 0, LAYOUT_COLOR_TEXT, DT_CENTER | DT_VCENTER);
|
|
}
|
|
//draw features
|
|
int n = g_pSettings->getFeatureCurCount(),
|
|
active = g_pSettings->getActiveFeature();
|
|
|
|
this->drawBoxBorder( 0, //draw bg for all features
|
|
LAYOUT_ELEMENT_HEIGHT * 2,
|
|
LAYOUT_ELEMENT_WIDTH,
|
|
(n > MAX_MENU_FEATURES_DISPLAYED) ? MAX_MENU_FEATURES_DISPLAYED * LAYOUT_ELEMENT_HEIGHT : LAYOUT_ELEMENT_HEIGHT * n,
|
|
LAYOUT_BORDER_SIZE,
|
|
LAYOUT_COLOR_BACKGROUND,
|
|
LAYOUT_COLOR_BORDER);
|
|
|
|
for(int i = 0, j = g_pSettings->getDisplayOffset(); i < n && i < MAX_MENU_FEATURES_DISPLAYED; i++, j++)
|
|
{
|
|
feat* feature = g_pSettings->getFeatureCur(j);
|
|
|
|
int x = 8,
|
|
y = LAYOUT_ELEMENT_HEIGHT * (i + 2);
|
|
|
|
//selected box
|
|
if(j == active)
|
|
this->drawBoxBorder( x - 6,
|
|
y + 2,
|
|
LAYOUT_ELEMENT_WIDTH - (LAYOUT_BORDER_SIZE * 2),
|
|
LAYOUT_ELEMENT_HEIGHT - (LAYOUT_BORDER_SIZE * 2),
|
|
LAYOUT_BORDER_SIZE,
|
|
LAYOUT_COLOR_ACTIVE_BG,
|
|
LAYOUT_COLOR_SELECTED);
|
|
|
|
//checkbox
|
|
if(feature->m_type == feat_toggle || feature->m_type == feat_slider)
|
|
{
|
|
this->drawBoxBorder( x - 2,
|
|
y + 5,
|
|
LAYOUT_ELEMENT_HEIGHT - (LAYOUT_BORDER_SIZE * 5),
|
|
LAYOUT_ELEMENT_HEIGHT - (LAYOUT_BORDER_SIZE * 5),
|
|
LAYOUT_BORDER_SIZE,
|
|
(feature->m_bOn == true) ? LAYOUT_COLOR_SELECTED : LAYOUT_COLOR_BACKGROUND,
|
|
(feature->m_bOn == true) ? LAYOUT_COLOR_ACTIVE_BORDER : LAYOUT_COLOR_BORDER);
|
|
x += (LAYOUT_ELEMENT_HEIGHT - (LAYOUT_BORDER_SIZE * 3));
|
|
}
|
|
this->drawText(feature->m_szName, x, y, 0, LAYOUT_ELEMENT_HEIGHT, 1, LAYOUT_COLOR_TEXT, DT_VCENTER);
|
|
|
|
//slider
|
|
if(feature->m_type == feat_slider)
|
|
{
|
|
featSlider* slider = static_cast<featSlider*>(feature);
|
|
int x = (int) (LAYOUT_ELEMENT_WIDTH * .5f),
|
|
y = (LAYOUT_ELEMENT_HEIGHT * (i + 2)) + 5,
|
|
w = (int) ((LAYOUT_ELEMENT_WIDTH * .5f) - (LAYOUT_BORDER_SIZE * 2)),
|
|
h = LAYOUT_ELEMENT_HEIGHT - (LAYOUT_BORDER_SIZE * 5);
|
|
float mod = (slider->m_fValue - slider->m_fMin) / (slider->m_fMax - slider->m_fMin);
|
|
this->drawBoxBorder(x, y, w, h, LAYOUT_BORDER_SIZE, LAYOUT_COLOR_SLIDER_BG, LAYOUT_COLOR_BORDER);
|
|
this->drawBoxBorder(x + (int) (mod * (w - h)), y, h, h, LAYOUT_BORDER_SIZE, LAYOUT_COLOR_SLIDER_BTN, LAYOUT_COLOR_BORDER);
|
|
//this->drawText(floatToString(slider->m_fValue), x, y, w - 1, h, 0, LAYOUT_COLOR_VALUE_TEXT, DT_CENTER | DT_VCENTER);
|
|
}
|
|
}
|
|
|
|
//draw scrollbar
|
|
int max = n - MAX_MENU_FEATURES_DISPLAYED; //number of features that are not displayed
|
|
if(max > 0)
|
|
{
|
|
int space = LAYOUT_ELEMENT_HEIGHT * (MAX_MENU_FEATURES_DISPLAYED + 2),
|
|
height = (space / max <= space / 2) ? space / max : space / 2;
|
|
space -= height;
|
|
float mod = (g_pSettings->getDisplayOffset() / (float) max);
|
|
this->drawBoxBorder(LAYOUT_ELEMENT_WIDTH + LAYOUT_BORDER_SIZE , (int) (space * mod), LAYOUT_SCROLLBAR_WIDTH, height, LAYOUT_BORDER_SIZE, LAYOUT_COLOR_BACKGROUND, LAYOUT_COLOR_BORDER);
|
|
}
|
|
|
|
g_pSettings->unlockFeatureCur();
|
|
}
|
|
|
|
m_pD3dDev->EndScene();
|
|
m_pD3dDev->Present(nullptr, nullptr, nullptr, nullptr);
|
|
return true;
|
|
}
|
|
|
|
bool D3D9Render::createFont(char *name, int size, bool bold, bool italic)
|
|
{
|
|
if(m_nFont >= FONT_BUFFER_SIZE)
|
|
return false;
|
|
D3DXCreateFont(m_pD3dDev, size, 0, (bold) ? FW_BOLD : FW_NORMAL, 0, (italic) ? 1 : 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH, name, &m_pFont[m_nFont]);
|
|
m_nFont++;
|
|
return true;
|
|
}
|
|
|
|
void D3D9Render::releaseFont()
|
|
{
|
|
for(int i = 0; i < m_nFont; i++)
|
|
if(m_pFont[i] != nullptr)
|
|
m_pFont[i]->Release();
|
|
m_nFont = 0;
|
|
return;
|
|
}
|
|
|
|
bool D3D9Render::getViewport()
|
|
{
|
|
RECT rectWnd;
|
|
GetWindowRect(g_pMemMan->getWindow(), &rectWnd);
|
|
m_screen.w = LAYOUT_ELEMENT_WIDTH * 2 + LAYOUT_SCROLLBAR_WIDTH + LAYOUT_BORDER_SIZE;
|
|
m_screen.h = LAYOUT_ELEMENT_HEIGHT * (MAX_MENU_FEATURES_DISPLAYED + 2); //300
|
|
m_screen.x = rectWnd.left + LAYOUT_PADDING_LEFT;
|
|
m_screen.y = rectWnd.top + LAYOUT_PADDING_TOP;
|
|
return 1;
|
|
}
|
|
|
|
void D3D9Render::showMessageBox(std::wstring title,std::wstring detail)
|
|
{
|
|
this->m_sTitle = title;
|
|
this->m_sDetail = detail;
|
|
std::thread t([this] {
|
|
m_bMBShowing = true;
|
|
Sleep(3000);
|
|
m_bMBShowing = false;
|
|
});
|
|
t.detach();
|
|
}
|
|
|
|
void D3D9Render::drawBox(int x, int y, int w, int h, D3DCOLOR color)
|
|
{
|
|
/*Vertex vertex[] =
|
|
{
|
|
{(float) x, (float) y + h, 1.0f, 1.0f, color},
|
|
{(float) x, (float) y, 1.0f, 1.0f, color},
|
|
{(float) x + w, (float) y + h, 1.0f, 1.0f, color},
|
|
{(float) x + w, (float) y, 1.0f, 1.0f, color}
|
|
};
|
|
void* pvBuffer; //pointer to the buffer
|
|
m_pVertexBuffer->Lock(0, 0, (void**) &pvBuffer, 0);
|
|
memcpy(pvBuffer, vertex, sizeof(vertex));
|
|
m_pVertexBuffer->Unlock();
|
|
|
|
// select the vertex buffer to display
|
|
m_pD3dDev->SetStreamSource(0, m_pVertexBuffer, 0, sizeof(Vertex));
|
|
|
|
// copy the vertex buffer to the back buffer
|
|
m_pD3dDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);*/
|
|
|
|
D3DRECT rect {x, y, x + w, y + h};
|
|
m_pD3dDev->Clear(1, &rect, D3DCLEAR_TARGET, color, 1.f, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
void D3D9Render::drawBoxInline(int x, int y, int w, int h, int size, D3DCOLOR color)
|
|
{
|
|
this->drawBox(x, y, w, size, color); //top
|
|
this->drawBox(x + w - size, y, size, h, color); //right
|
|
this->drawBox(x, y + h - size, w, size, color); //bottom
|
|
this->drawBox(x, y, size, h, color); //left
|
|
return;
|
|
}
|
|
|
|
void D3D9Render::drawBoxBorder(int x, int y, int w, int h, int borderSize, D3DCOLOR color, D3DCOLOR borderColor)
|
|
{
|
|
this->drawBox(x, y, w, h, borderColor);
|
|
this->drawBox(x + borderSize, y + borderSize, w - (borderSize * 2), h - (borderSize * 2), color);
|
|
}
|
|
|
|
void D3D9Render::drawText(std::wstring str, int x, int y, int font, D3DCOLOR color)
|
|
{
|
|
LPCWSTR pszStr = str.c_str();
|
|
RECT pos;
|
|
pos.left = x;
|
|
pos.top = y;
|
|
m_pFont[font]->DrawTextW(nullptr, pszStr, (int) lstrlenW(pszStr), &pos, DT_NOCLIP, color);
|
|
}
|
|
|
|
//void drawText (std::string str, float x, float y, float w, float h, int font, D3DCOLOR color, DWORD flags = NULL)
|
|
void D3D9Render::drawText(std::wstring str, int x, int y, int w, int h, int font, D3DCOLOR color, DWORD flags)
|
|
{
|
|
LPCWSTR pszStr = str.c_str();
|
|
RECT pos;
|
|
pos.left = x;
|
|
pos.right = x + w;
|
|
pos.top = y;
|
|
pos.bottom = y + h;
|
|
m_pFont[font]->DrawTextW(nullptr, pszStr, (int) lstrlenW(pszStr), &pos, flags | DT_NOCLIP, color);
|
|
} |