layout: restructure into src/ tests/ android/ scripts/ tools/

- extension/src/{port,platform,codepage} -> src/; native_render -> src/host
  (+ dxt, shaders/); libgr2 -> src/gr2; extension/third_party -> third_party
- extension/tests -> tests/port, libgr2/tests -> tests/gr2
- android-native -> android (build.sh, push-client.sh moved in)
- script -> scripts; tools/40250 -> tools/server; oracle -> tools/granny-oracle;
  perf tools -> tools/perf
- all build trees under build/ (native, release, android, port-gate)
- xrender:: CMake aliases -> mt::; port-map ledger impl paths rewritten

No code changes. ctest 15/15, port_gate macos+android PASS, port_map check 0 errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
shenlei
2026-09-29 19:08:19 +09:00
co-authored by Claude Opus 5.5
parent 70710477cf
commit a46093104c
2817 changed files with 13728 additions and 13744 deletions
+72
View File
@@ -0,0 +1,72 @@
#pragma once
// CPU-memory vertex/index buffers behind the D3D8 buffer handles. 40250 fills its buffers through
// Lock/Unlock (CGrannyModel::__LoadVertices, CGrannyModelInstance deform) and the renderer later reads
// them back, so the platform keeps the bytes in memory instead of creating device objects.
#include "EterLib/StdAfx.h"
#include <cstdint>
#include <atomic>
#include <vector>
inline std::atomic<std::uint64_t> mt_next_cpu_buffer_id{1};
struct MtCpuVertexBuffer : IDirect3DVertexBuffer8
{
const std::uint64_t id = mt_next_cpu_buffer_id.fetch_add(1, std::memory_order_relaxed);
std::uint64_t revision = 0;
std::vector<uint8_t> bytes;
DWORD fvf = 0;
HRESULT Lock(UINT offset, UINT size, BYTE** data, DWORD) override
{
if (size_t(offset) + size > bytes.size())
return E_FAIL;
*data = bytes.data() + offset;
return S_OK;
}
HRESULT Unlock() override { ++revision; return S_OK; }
};
struct MtCpuIndexBuffer : IDirect3DIndexBuffer8
{
const std::uint64_t id = mt_next_cpu_buffer_id.fetch_add(1, std::memory_order_relaxed);
std::uint64_t revision = 0;
std::vector<uint8_t> bytes;
D3DFORMAT format = D3DFMT_INDEX16;
HRESULT Lock(UINT offset, UINT size, BYTE** data, DWORD) override
{
if (size_t(offset) + size > bytes.size())
return E_FAIL;
*data = bytes.data() + offset;
return S_OK;
}
HRESULT Unlock() override { ++revision; return S_OK; }
};
// D3DXGetFVFVertexSize.
inline unsigned mt_fvf_vertex_size(DWORD fvf)
{
unsigned size = 0;
switch (fvf & D3DFVF_POSITION_MASK)
{
case D3DFVF_XYZ: size += 12; break;
case D3DFVF_XYZRHW: size += 16; break;
case D3DFVF_XYZB1: size += 16; break;
case D3DFVF_XYZB2: size += 20; break;
case D3DFVF_XYZB3: size += 24; break;
case D3DFVF_XYZB4: size += 28; break;
case D3DFVF_XYZB5: size += 32; break;
}
if (fvf & D3DFVF_NORMAL) size += 12;
if (fvf & D3DFVF_PSIZE) size += 4;
if (fvf & D3DFVF_DIFFUSE) size += 4;
if (fvf & D3DFVF_SPECULAR) size += 4;
const unsigned texCount = (fvf & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
for (unsigned i = 0; i < texCount; ++i)
{
static const unsigned coordSize[4] = { 8, 12, 16, 4 };
size += coordSize[(fvf >> (16 + i * 2)) & 3];
}
return size;
}
+64
View File
@@ -0,0 +1,64 @@
// Platform skeleton for EterLib/DibBar.h (40250 EterLib/DibBar.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/DibBar.h"
#include "../PlatformStub.h"
CDibBar::CDibBar()
{
MT_PLATFORM_STUB();
}
CDibBar::~CDibBar()
{
MT_PLATFORM_STUB();
}
auto CDibBar::Create(HDC, DWORD, DWORD) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CDibBar::Invalidate() -> void
{
MT_PLATFORM_STUB();
}
auto CDibBar::SetClipRect(const RECT &) -> void
{
MT_PLATFORM_STUB();
}
auto CDibBar::ClearBar() -> void
{
MT_PLATFORM_STUB();
}
auto CDibBar::Render(int, int) -> void
{
MT_PLATFORM_STUB();
}
auto CDibBar::__NearTextureSize(DWORD) -> DWORD
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<DWORD>();
}
auto CDibBar::__DivideTextureSize(DWORD, DWORD, DWORD *, DWORD *, DWORD *) -> void
{
MT_PLATFORM_STUB();
}
auto CDibBar::__BuildTextureBlock(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD) -> CBlockTexture *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<CBlockTexture *>();
}
auto CDibBar::__BuildTextureBlockList(DWORD, DWORD, DWORD) -> void
{
MT_PLATFORM_STUB();
}
+72
View File
@@ -0,0 +1,72 @@
// Platform skeleton for EterLib/FileLoaderThread.h (40250 EterLib/FileLoaderThread.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/FileLoaderThread.h"
#include "../PlatformStub.h"
CFileLoaderThread::CFileLoaderThread()
{
MT_PLATFORM_STUB();
}
CFileLoaderThread::~CFileLoaderThread()
{
MT_PLATFORM_STUB();
}
auto CFileLoaderThread::Create(void *) -> int
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<int>();
}
auto CFileLoaderThread::Request(std::string &) -> void
{
MT_PLATFORM_STUB();
}
auto CFileLoaderThread::Fetch(TData **) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CFileLoaderThread::Shutdown() -> void
{
MT_PLATFORM_STUB();
}
auto CFileLoaderThread::EntryPoint(void *) -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto CFileLoaderThread::Run(void *) -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto CFileLoaderThread::Setup() -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto CFileLoaderThread::Execute(void *) -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto CFileLoaderThread::Destroy() -> void
{
MT_PLATFORM_STUB();
}
auto CFileLoaderThread::Process() -> void
{
MT_PLATFORM_STUB();
}
+62
View File
@@ -0,0 +1,62 @@
// Platform skeleton for EterLib/GrpColor.h (40250 EterLib/GrpColor.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpColor.h"
#include "../PlatformStub.h"
CGraphicColor::CGraphicColor(const CGraphicColor &)
{
MT_PLATFORM_STUB();
}
CGraphicColor::CGraphicColor(float, float, float, float)
{
MT_PLATFORM_STUB();
}
CGraphicColor::CGraphicColor(DWORD)
{
MT_PLATFORM_STUB();
}
CGraphicColor::CGraphicColor()
{
MT_PLATFORM_STUB();
}
CGraphicColor::~CGraphicColor()
{
MT_PLATFORM_STUB();
}
auto CGraphicColor::Clear() -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicColor::Set(float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicColor::Set(const CGraphicColor &) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicColor::Set(DWORD) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicColor::Blend(float, const CGraphicColor &, const CGraphicColor &) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicColor::GetPackValue() const -> DWORD
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<DWORD>();
}
+48
View File
@@ -0,0 +1,48 @@
// Platform skeleton for EterLib/GrpColorInstance.h (40250 EterLib/GrpColorInstance.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpColorInstance.h"
#include "../PlatformStub.h"
CGraphicColorInstance::CGraphicColorInstance()
{
MT_PLATFORM_STUB();
}
CGraphicColorInstance::~CGraphicColorInstance()
{
MT_PLATFORM_STUB();
}
auto CGraphicColorInstance::Clear() -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicColorInstance::SetColorReference(const CGraphicColor &) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicColorInstance::BlendColorReference(DWORD, const CGraphicColor &) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicColorInstance::Update() -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicColorInstance::GetCurrentColorReference() const -> const CGraphicColor &
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<const CGraphicColor &>();
}
auto CGraphicColorInstance::GetCurrentTime() -> DWORD
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<DWORD>();
}
+115
View File
@@ -0,0 +1,115 @@
// 40250 EterLib/GrpDIB.cpp, verbatim. The GDI calls are the FreeType-backed platform/Win32Gdi.cpp.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpDIB.h"
CGraphicDib::CGraphicDib()
{
Initialize();
}
CGraphicDib::~CGraphicDib()
{
Destroy();
}
void CGraphicDib::Initialize()
{
m_hDC=NULL;
m_hBmp=NULL;
m_pvBuf=NULL;
m_width=0;
m_height=0;
}
void CGraphicDib::Destroy()
{
if (m_hBmp) DeleteObject(m_hBmp);
if (m_hDC) DeleteDC(m_hDC);
Initialize();
}
bool CGraphicDib::Create(HDC hDC, int width, int height)
{
Destroy();
m_width = width;
m_height = height;
ZeroMemory(&m_bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
m_bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
m_bmi.bmiHeader.biWidth = m_width;
m_bmi.bmiHeader.biHeight = -m_height;
m_bmi.bmiHeader.biPlanes = 1;
m_bmi.bmiHeader.biBitCount = 32;
m_bmi.bmiHeader.biCompression = BI_RGB;
m_hDC=CreateCompatibleDC(hDC);
if (!m_hDC)
{
assert(!"CGraphicDib::Create CreateCompatibleDC Error");
return false;
}
m_hBmp=CreateDIBSection(m_hDC, &m_bmi, DIB_RGB_COLORS, &m_pvBuf, NULL, 0);
if (!m_hBmp)
{
assert(!"CGraphicDib::Create CreateDIBSection Error");
return false;
}
SelectObject(m_hDC, m_hBmp);
::SetTextColor(m_hDC, RGB(255, 255, 255));
return true;
}
HDC CGraphicDib::GetDCHandle()
{
return m_hDC;
}
void CGraphicDib::SetBkMode(int iBkMode)
{
::SetBkMode(m_hDC, iBkMode);
}
void CGraphicDib::TextOut(int ix, int iy, const char * c_szText)
{
::SetBkColor(m_hDC, 0);
::TextOut(m_hDC, ix, iy, c_szText, strlen(c_szText));
}
void CGraphicDib::Put(HDC hDC, int x, int y)
{
SetDIBitsToDevice(
hDC,
x,
y,
m_width,
m_height,
0,
0,
0,
m_height,
m_pvBuf,
&m_bmi,
DIB_RGB_COLORS
);
}
void* CGraphicDib::GetPointer()
{
return m_pvBuf;
}
int CGraphicDib::GetWidth()
{
return m_width;
}
int CGraphicDib::GetHeight()
{
return m_height;
}
+165
View File
@@ -0,0 +1,165 @@
// Platform skeleton for EterLib/GrpDetector.h (40250 EterLib/GrpDetector.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpDetector.h"
#include "../PlatformStub.h"
auto D3D_SModeInfo::GetString(std::string *) -> void
{
MT_PLATFORM_STUB();
}
auto D3D_CAdapterDisplayModeList::Build(IDirect3D8 &, D3DFORMAT, UINT) -> void
{
MT_PLATFORM_STUB();
}
auto D3D_CAdapterDisplayModeList::GetDisplayModeNum() -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto D3D_CAdapterDisplayModeList::GetPixelFormatNum() -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto D3D_CAdapterDisplayModeList::GetDisplayModer(UINT) -> const D3DDISPLAYMODE &
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<const D3DDISPLAYMODE &>();
}
auto D3D_CAdapterDisplayModeList::GetPixelFormatr(UINT) -> const D3DFORMAT &
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<const D3DFORMAT &>();
}
auto D3D_CDeviceInfo::Build(IDirect3D8 &, UINT, UINT, D3D_CAdapterDisplayModeList &, PFNCONFIRMDEVICE) -> BOOL
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<BOOL>();
}
auto D3D_CDeviceInfo::Find(UINT, UINT, UINT, BOOL, UINT *) -> BOOL
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<BOOL>();
}
auto D3D_CDeviceInfo::GetD3DModeInfoNum() -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto D3D_CDeviceInfo::GetString(std::string *) -> void
{
MT_PLATFORM_STUB();
}
auto D3D_CDeviceInfo::FindDepthStencilFormat(IDirect3D8 &, UINT, D3DDEVTYPE, D3DFORMAT, D3DFORMAT *) -> BOOL
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<BOOL>();
}
auto D3D_CDeviceInfo::GetD3DModeInfor(UINT) -> D3D_SModeInfo &
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3D_SModeInfo &>();
}
auto D3D_CDeviceInfo::GetD3DModeInfop(UINT) -> D3D_SModeInfo *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3D_SModeInfo *>();
}
decltype(D3D_CDeviceInfo::msc_aszD3DDevDesc) D3D_CDeviceInfo::msc_aszD3DDevDesc{};
decltype(D3D_CDeviceInfo::msc_aeD3DDevType) D3D_CDeviceInfo::msc_aeD3DDevType{};
auto D3D_CAdapterInfo::Find(UINT, UINT, UINT, BOOL, UINT *, UINT *) -> BOOL
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<BOOL>();
}
auto D3D_CAdapterInfo::Build(IDirect3D8 &, UINT, PFNCONFIRMDEVICE) -> BOOL
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<BOOL>();
}
auto D3D_CAdapterInfo::GetString(std::string *) -> void
{
MT_PLATFORM_STUB();
}
auto D3D_CAdapterInfo::GetDesktopD3DDisplayModer() -> D3DDISPLAYMODE &
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3DDISPLAYMODE &>();
}
auto D3D_CAdapterInfo::GetDesktopD3DDisplayModep() -> D3DDISPLAYMODE *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3DDISPLAYMODE *>();
}
auto D3D_CAdapterInfo::GetD3DDeviceInfop(UINT) -> D3D_CDeviceInfo *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3D_CDeviceInfo *>();
}
auto D3D_CAdapterInfo::GetD3DModeInfop(UINT, UINT) -> D3D_SModeInfo *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3D_SModeInfo *>();
}
D3D_CDisplayModeAutoDetector::D3D_CDisplayModeAutoDetector()
{
MT_PLATFORM_STUB();
}
D3D_CDisplayModeAutoDetector::~D3D_CDisplayModeAutoDetector()
{
MT_PLATFORM_STUB();
}
auto D3D_CDisplayModeAutoDetector::Find(UINT, UINT, UINT, BOOL, UINT *, UINT *, UINT *) -> BOOL
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<BOOL>();
}
auto D3D_CDisplayModeAutoDetector::Build(IDirect3D8 &, PFNCONFIRMDEVICE) -> BOOL
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<BOOL>();
}
auto D3D_CDisplayModeAutoDetector::GetD3DAdapterInfop(UINT) -> D3D_CAdapterInfo *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3D_CAdapterInfo *>();
}
auto D3D_CDisplayModeAutoDetector::GetD3DModeInfop(UINT, UINT, UINT) -> D3D_SModeInfo *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3D_SModeInfo *>();
}
auto D3D_CDisplayModeAutoDetector::GetString(std::string *) -> void
{
MT_PLATFORM_STUB();
}
+363
View File
@@ -0,0 +1,363 @@
// 40250 EterLib/GrpDevice.cpp over the platform's recording device (RecordingDevice.h): there is no
// Direct3D object, adapter detection or window; Create makes the device, CStateManager, the matrix
// stack and the default buffers as 40250 does. The remaining MT_PLATFORM_STUB() bodies (device reset,
// web-browser mode, driver warnings) have no platform counterpart yet.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpDevice.h"
#include "EterLib/StateManager.h"
#include "EterBase/Stl.h"
#include "CpuBuffer.h"
#include "RecordingDevice.h"
#include <cstring>
#include "../PlatformStub.h"
bool GRAPHICS_CAPS_CAN_NOT_DRAW_LINE = false;
bool GRAPHICS_CAPS_CAN_NOT_DRAW_SHADOW = false;
bool GRAPHICS_CAPS_HALF_SIZE_IMAGE = false;
bool GRAPHICS_CAPS_CAN_NOT_TEXTURE_ADDRESS_BORDER = false;
bool GRAPHICS_CAPS_SOFTWARE_TILING = false;
CGraphicDevice::CGraphicDevice()
: m_uBackBufferCount(0)
{
__Initialize();
}
CGraphicDevice::~CGraphicDevice()
{
Destroy();
}
void CGraphicDevice::InitBackBufferCount(UINT uBackBufferCount)
{
m_uBackBufferCount=uBackBufferCount;
}
void CGraphicDevice::Destroy()
{
__DestroyPDTVertexBufferList();
__DestroyDefaultIndexBufferList();
// PORT: no DC, vertex shader objects or D3DX meshes; the stream "shaders" are FVF codes.
ms_ptVS = 0;
ms_pntVS = 0;
ms_pnt2VS = 0;
safe_release(ms_lpd3dMatStack);
safe_release(ms_lpd3dDevice);
if (m_pStateManager)
{
delete m_pStateManager;
m_pStateManager = NULL;
}
__Initialize();
}
int CGraphicDevice::Create(HWND hWnd, int iHres, int iVres, bool Windowed, int /*iBit*/, int iReflashRate)
{
int iRet = CREATE_OK;
Destroy();
ms_iWidth = iHres;
ms_iHeight = iVres;
// PORT: in place of Direct3DCreate8, the display-mode detection and CreateDevice: the recording
// device renders through Godot, which supports DXT and has no refresh-rate or T&L failures.
ms_hWnd = hWnd;
ms_lpd3dDevice = MtCreateRecordingDevice(iHres, iVres);
ms_dwD3DBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING;
ms_d3dPresentParameter.BackBufferWidth = iHres;
ms_d3dPresentParameter.BackBufferHeight = iVres;
ms_d3dPresentParameter.Windowed = Windowed;
if (FAILED((ms_hLastResult = ms_lpd3dDevice->GetDeviceCaps(&ms_d3dCaps))))
{
Tracenf("IDirect3DDevice.GetDeviceCaps - ERROR %d", ms_hLastResult);
return CREATE_GET_DEVICE_CAPS2;
}
ms_lpd3dDevice->GetViewport(&ms_Viewport);
m_pStateManager = new CStateManager(ms_lpd3dDevice);
D3DXCreateMatrixStack(0, &ms_lpd3dMatStack);
ms_lpd3dMatStack->LoadIdentity();
ms_ptVS = CreatePTStreamVertexShader();
ms_pntVS = CreatePNTStreamVertexShader();
ms_pnt2VS = CreatePNT2StreamVertexShader();
D3DXMatrixIdentity(&ms_matIdentity);
D3DXMatrixIdentity(&ms_matView);
D3DXMatrixIdentity(&ms_matProj);
D3DXMatrixIdentity(&ms_matInverseView);
D3DXMatrixIdentity(&ms_matInverseViewYAxis);
D3DXMatrixIdentity(&ms_matWorld);
D3DXMatrixIdentity(&ms_matWorldView);
D3DXMatrixIdentity(&ms_matScreen0);
D3DXMatrixIdentity(&ms_matScreen1);
D3DXMatrixIdentity(&ms_matScreen2);
ms_matScreen0._11 = 1;
ms_matScreen0._22 = -1;
ms_matScreen1._41 = 1;
ms_matScreen1._42 = 1;
ms_matScreen2._11 = (float) iHres / 2;
ms_matScreen2._22 = (float) iVres / 2;
// PORT: no D3DXCreateSphere/D3DXCreateCylinder (debug collision rendering) and no Clear.
if (!__CreateDefaultIndexBufferList())
return false;
if (!__CreatePDTVertexBufferList())
return false;
DWORD dwTexMemSize = GetAvailableTextureMemory();
if (dwTexMemSize < 64 * 1024 * 1024)
ms_isLowTextureMemory = true;
else
ms_isLowTextureMemory = false;
if (dwTexMemSize > 100 * 1024 * 1024)
ms_isHighTextureMemory = true;
else
ms_isHighTextureMemory = false;
if (ms_d3dCaps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
GRAPHICS_CAPS_CAN_NOT_TEXTURE_ADDRESS_BORDER=false;
else
GRAPHICS_CAPS_CAN_NOT_TEXTURE_ADDRESS_BORDER=true;
// PORT: the SIS/3dfx driver checks have no adapter identifier to test.
return (iRet);
}
auto CGraphicDevice::GetDeviceState() -> EDeviceState
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<EDeviceState>();
}
auto CGraphicDevice::Reset() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CGraphicDevice::EnableWebBrowserMode(const RECT &) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicDevice::DisableWebBrowserMode() -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicDevice::MoveWebBrowserRect(const RECT &) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicDevice::ResizeBackBuffer(UINT uWidth, UINT uHeight) -> bool
{
ms_iWidth = uWidth;
ms_iHeight = uHeight;
ms_d3dPresentParameter.BackBufferWidth = uWidth;
ms_d3dPresentParameter.BackBufferHeight = uHeight;
return true;
}
auto CGraphicDevice::RegisterWarningString(UINT, const char *) -> void
{
MT_PLATFORM_STUB();
}
void CGraphicDevice::__Initialize()
{
ms_iD3DAdapterInfo=D3DADAPTER_DEFAULT;
ms_iD3DDevInfo=D3DADAPTER_DEFAULT;
ms_iD3DModeInfo=D3DADAPTER_DEFAULT;
ms_lpd3d = NULL;
ms_lpd3dDevice = NULL;
ms_lpd3dMatStack = NULL;
ms_dwWavingEndTime = 0;
ms_dwFlashingEndTime = 0;
m_pStateManager = NULL;
__InitializeDefaultIndexBufferList();
__InitializePDTVertexBufferList();
}
auto CGraphicDevice::__IsInDriverBlackList(D3D_CAdapterInfo &) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CGraphicDevice::__WarningMessage(HWND, UINT) -> void
{
MT_PLATFORM_STUB();
}
void CGraphicDevice::__InitializeDefaultIndexBufferList()
{
for (UINT i=0; i<DEFAULT_IB_NUM; ++i)
ms_alpd3dDefIB[i]=NULL;
}
void CGraphicDevice::__DestroyDefaultIndexBufferList()
{
for (UINT i=0; i<DEFAULT_IB_NUM; ++i)
if (ms_alpd3dDefIB[i])
{
delete ms_alpd3dDefIB[i]; // PORT: CPU buffer, no Release
ms_alpd3dDefIB[i]=NULL;
}
}
bool CGraphicDevice::__CreateDefaultIndexBufferList()
{
static const WORD c_awLineIndices[2] = { 0, 1, };
static const WORD c_awLineTriIndices[6] = { 0, 1, 0, 2, 1, 2, };
static const WORD c_awLineRectIndices[8] = { 0, 1, 0, 2, 1, 3, 2, 3,};
static const WORD c_awLineCubeIndices[24] = {
0, 1, 0, 2, 1, 3, 2, 3,
0, 4, 1, 5, 2, 6, 3, 7,
4, 5, 4, 6, 5, 7, 6, 7,
};
static const WORD c_awFillTriIndices[3]= { 0, 1, 2, };
static const WORD c_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, };
static const WORD c_awFillCubeIndices[36] = {
0, 1, 2, 1, 3, 2,
2, 0, 6, 0, 4, 6,
0, 1, 4, 1, 5, 4,
1, 3, 5, 3, 7, 5,
3, 2, 7, 2, 6, 7,
4, 5, 6, 5, 7, 6,
};
if (!__CreateDefaultIndexBuffer(DEFAULT_IB_LINE, 2, c_awLineIndices))
return false;
if (!__CreateDefaultIndexBuffer(DEFAULT_IB_LINE_TRI, 6, c_awLineTriIndices))
return false;
if (!__CreateDefaultIndexBuffer(DEFAULT_IB_LINE_RECT, 8, c_awLineRectIndices))
return false;
if (!__CreateDefaultIndexBuffer(DEFAULT_IB_LINE_CUBE, 24, c_awLineCubeIndices))
return false;
if (!__CreateDefaultIndexBuffer(DEFAULT_IB_FILL_TRI, 3, c_awFillTriIndices))
return false;
if (!__CreateDefaultIndexBuffer(DEFAULT_IB_FILL_RECT, 6, c_awFillRectIndices))
return false;
if (!__CreateDefaultIndexBuffer(DEFAULT_IB_FILL_CUBE, 36, c_awFillCubeIndices))
return false;
return true;
}
bool CGraphicDevice::__CreateDefaultIndexBuffer(UINT eDefIB, UINT uIdxCount, const WORD* c_awIndices)
{
assert(ms_alpd3dDefIB[eDefIB]==NULL);
// PORT: a CPU buffer in place of CreateIndexBuffer (CpuBuffer.h).
MtCpuIndexBuffer* pIB = new MtCpuIndexBuffer;
pIB->bytes.resize(sizeof(WORD)*uIdxCount);
pIB->format = D3DFMT_INDEX16;
ms_alpd3dDefIB[eDefIB] = pIB;
WORD* dstIndices;
if (FAILED(
ms_alpd3dDefIB[eDefIB]->Lock(0, 0, (BYTE**)&dstIndices, 0)
)) return false;
memcpy(dstIndices, c_awIndices, sizeof(WORD)*uIdxCount);
ms_alpd3dDefIB[eDefIB]->Unlock();
return true;
}
void CGraphicDevice::__InitializePDTVertexBufferList()
{
for (UINT i=0; i<PDT_VERTEXBUFFER_NUM; ++i)
ms_alpd3dPDTVB[i]=NULL;
}
void CGraphicDevice::__DestroyPDTVertexBufferList()
{
for (UINT i=0; i<PDT_VERTEXBUFFER_NUM; ++i)
{
if (ms_alpd3dPDTVB[i])
{
delete ms_alpd3dPDTVB[i]; // PORT: CPU buffer, no Release
ms_alpd3dPDTVB[i]=NULL;
}
}
}
bool CGraphicDevice::__CreatePDTVertexBufferList()
{
for (UINT i=0; i<PDT_VERTEXBUFFER_NUM; ++i)
{
// PORT: a CPU buffer in place of CreateVertexBuffer (CpuBuffer.h).
MtCpuVertexBuffer* pVB = new MtCpuVertexBuffer;
pVB->bytes.resize(sizeof(TPDTVertex)*PDT_VERTEX_NUM);
pVB->fvf = D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1;
ms_alpd3dPDTVB[i] = pVB;
}
return true;
}
// PORT: the stream vertex shaders are declarations for the fixed-function pipeline; the recording
// device decodes vertices by FVF, so each returns the FVF matching its declaration. PT keeps its
// texture coordinates in stream 1, which the device does not record: stream 0 is position only.
DWORD CGraphicDevice::CreatePTStreamVertexShader()
{
assert(ms_lpd3dDevice != NULL);
return D3DFVF_XYZ;
}
DWORD CGraphicDevice::CreatePNTStreamVertexShader()
{
assert(ms_lpd3dDevice != NULL);
return D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1;
}
DWORD CGraphicDevice::CreatePNT2StreamVertexShader()
{
assert(ms_lpd3dDevice != NULL);
return D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX2;
}
auto CGraphicDevice::CreateDoublePNTStreamVertexShader() -> DWORD
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<DWORD>();
}
// 40250 GrpDevice.cpp:298-306; s_MaxTextureWidth/Height come from D3DCAPS8 in __CheckD3DCaps.
// PORT: 4096 is the texture size every Godot renderer on the target GPUs supports.
static DWORD s_MaxTextureWidth = 4096, s_MaxTextureHeight = 4096;
DWORD GetMaxTextureWidth()
{
return s_MaxTextureWidth;
}
DWORD GetMaxTextureHeight()
{
return s_MaxTextureHeight;
}
@@ -0,0 +1,185 @@
// Platform skeleton for EterLib/GrpExpandedImageInstance.h (40250 EterLib/GrpExpandedImageInstance.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpExpandedImageInstance.h"
#include "../PlatformStub.h"
#include "EterBase/CRC32.h"
#include "UIRenderCommands.h"
#include <cmath>
auto CGraphicExpandedImageInstance::Type() -> DWORD
{
static DWORD type = GetCRC32("CGraphicExpandedImageInstance", sizeof("CGraphicExpandedImageInstance") - 1);
return type;
}
CGraphicExpandedImageInstance::CGraphicExpandedImageInstance()
{
Initialize();
}
CGraphicExpandedImageInstance::~CGraphicExpandedImageInstance()
{
Destroy();
}
auto CGraphicExpandedImageInstance::Destroy() -> void
{
CGraphicImageInstance::Destroy();
Initialize();
}
auto CGraphicExpandedImageInstance::SetDepth(float depth) -> void
{
m_fDepth = depth;
}
auto CGraphicExpandedImageInstance::SetOrigin() -> void
{
m_v2Origin = D3DXVECTOR2(GetWidth() * 0.5f, GetHeight() * 0.5f);
}
auto CGraphicExpandedImageInstance::SetOrigin(float x, float y) -> void
{
m_v2Origin = D3DXVECTOR2(x, y);
}
auto CGraphicExpandedImageInstance::SetRotation(float rotation) -> void
{
m_fRotation = rotation;
}
auto CGraphicExpandedImageInstance::SetScale(float x, float y) -> void
{
m_v2Scale = D3DXVECTOR2(x, y);
}
// In 40250, the arguments are fractions of the image size (uiToolTip gauges, SetPercentage).
auto CGraphicExpandedImageInstance::SetRenderingRect(float fLeft, float fTop, float fRight, float fBottom) -> void
{
if (IsEmpty())
return;
float fWidth = float(GetWidth());
float fHeight = float(GetHeight());
m_RenderingRect.left = fWidth * fLeft;
m_RenderingRect.top = fHeight * fTop;
m_RenderingRect.right = fWidth * fRight;
m_RenderingRect.bottom = fHeight * fBottom;
}
auto CGraphicExpandedImageInstance::SetRenderingMode(int mode) -> void
{
m_iRenderingMode = mode;
}
auto CGraphicExpandedImageInstance::Initialize() -> void
{
m_fDepth = 0;
m_v2Origin = D3DXVECTOR2(0, 0);
m_v2Scale = D3DXVECTOR2(1, 1);
m_fRotation = 0;
m_RenderingRect = {0, 0, 0, 0};
m_iRenderingMode = RENDERING_MODE_NORMAL;
}
// 40250 GrpExpandedImageInstance.cpp:29-142. The vertex and texture-coordinate arithmetic is
// verbatim; the D3D stream/blend-state calls become one UIRenderCommand with the four vertices.
auto CGraphicExpandedImageInstance::OnRender() -> void
{
CGraphicImage * pImage = m_roImage.GetPointer();
CGraphicTexture * pTexture = pImage->GetTexturePointer();
if (pTexture->GetWidth() <= 0 || pTexture->GetHeight() <= 0)
return;
const RECT& c_rRect = pImage->GetRectReference();
float texReverseWidth = 1.0f / float(pTexture->GetWidth());
float texReverseHeight = 1.0f / float(pTexture->GetHeight());
float su = (c_rRect.left - m_RenderingRect.left) * texReverseWidth;
float sv = (c_rRect.top - m_RenderingRect.top) * texReverseHeight;
float eu = (c_rRect.left + m_RenderingRect.right + (c_rRect.right-c_rRect.left)) * texReverseWidth;
float ev = (c_rRect.top + m_RenderingRect.bottom + (c_rRect.bottom-c_rRect.top)) * texReverseHeight;
float x[4], y[4];
for (int i = 0; i < 4; ++i)
{
x[i] = m_v2Position.x-0.5f;
y[i] = m_v2Position.y-0.5f;
}
if (0.0f == m_fRotation)
{
float fimgWidth = float(pImage->GetWidth()) * m_v2Scale.x;
float fimgHeight = float(pImage->GetHeight()) * m_v2Scale.y;
x[0] -= m_RenderingRect.left;
y[0] -= m_RenderingRect.top;
x[1] += fimgWidth + m_RenderingRect.right;
y[1] -= m_RenderingRect.top;
x[2] -= m_RenderingRect.left;
y[2] += fimgHeight + m_RenderingRect.bottom;
x[3] += fimgWidth + m_RenderingRect.right;
y[3] += fimgHeight + m_RenderingRect.bottom;
// PORT: 40250 flips D3DRS_CULLMODE for a mirrored scale; the Godot canvas has no culling.
}
else
{
float fimgHalfWidth = float(pImage->GetWidth())/2.0f * m_v2Scale.x;
float fimgHalfHeight = float(pImage->GetHeight())/2.0f * m_v2Scale.y;
for (int i = 0; i < 4; ++i)
{
x[i] += m_v2Origin.x;
y[i] += m_v2Origin.y;
}
float fRadian = D3DXToRadian(m_fRotation);
x[0] += (-fimgHalfWidth*cosf(fRadian)) - (-fimgHalfHeight*sinf(fRadian));
y[0] += (-fimgHalfWidth*sinf(fRadian)) + (-fimgHalfHeight*cosf(fRadian));
x[1] += (+fimgHalfWidth*cosf(fRadian)) - (-fimgHalfHeight*sinf(fRadian));
y[1] += (+fimgHalfWidth*sinf(fRadian)) + (-fimgHalfHeight*cosf(fRadian));
x[2] += (-fimgHalfWidth*cosf(fRadian)) - (+fimgHalfHeight*sinf(fRadian));
y[2] += (-fimgHalfWidth*sinf(fRadian)) + (+fimgHalfHeight*cosf(fRadian));
x[3] += (+fimgHalfWidth*cosf(fRadian)) - (+fimgHalfHeight*sinf(fRadian));
y[3] += (+fimgHalfWidth*sinf(fRadian)) + (+fimgHalfHeight*cosf(fRadian));
}
UIRenderAddImage(pTexture, x, y, su, sv, eu, ev, UIRenderColor(m_DiffuseColor), m_iRenderingMode);
}
auto CGraphicExpandedImageInstance::OnSetImagePointer() -> void
{
if (!IsEmpty()) SetOrigin();
}
auto CGraphicExpandedImageInstance::OnIsType(DWORD type) -> BOOL
{
return type == Type() || CGraphicImageInstance::OnIsType(type);
}
auto CGraphicExpandedImageInstance::CreateSystem(UINT) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicExpandedImageInstance::DestroySystem() -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicExpandedImageInstance::New() -> CGraphicExpandedImageInstance *
{
return new CGraphicExpandedImageInstance();
}
auto CGraphicExpandedImageInstance::Delete(CGraphicExpandedImageInstance *instance) -> void
{
if (!instance) return;
instance->Destroy();
delete instance;
}
decltype(CGraphicExpandedImageInstance::ms_kPool) CGraphicExpandedImageInstance::ms_kPool{};
+386
View File
@@ -0,0 +1,386 @@
// 40250 EterLib/GrpFontTexture.cpp, verbatim over the GDI emulation in platform/Win32Gdi.cpp. The
// A4R4G4B4 page textures are CGraphicImageTexture memory textures the Godot canvas samples.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpText.h"
#include "EterBase/Stl.h"
#include "EterLib/Util.h"
#include "UIRenderCommands.h"
#include <unordered_map>
// PORT: HiDPI glyph pages (UISetFontOversample). With a scale s > 1 the page DIB and texture are
// s times larger and each glyph is drawn with an s-times font into the s-scaled cell, while the
// 40250 metrics (width, height, advance), the packing and therefore the page UVs stay the logical
// 1x values: text layout is unchanged, only the texels get finer.
namespace {
int g_font_oversample = 1;
bool g_font_oversample_latched = false;
// The 1x HFONT a CGraphicFontTexture measures with -> its s-times twin that draws.
std::unordered_map<HFONT, HFONT> g_oversampled_fonts;
int FontOversample()
{
g_font_oversample_latched = true;
return g_font_oversample;
}
} // namespace
void UISetFontOversample(int scale)
{
if (g_font_oversample_latched)
return;
g_font_oversample = scale < 1 ? 1 : (scale > 4 ? 4 : scale);
}
int UIFontOversample()
{
return g_font_oversample;
}
CGraphicFontTexture::CGraphicFontTexture()
{
Initialize();
}
CGraphicFontTexture::~CGraphicFontTexture()
{
Destroy();
}
void CGraphicFontTexture::Initialize()
{
CGraphicTexture::Initialize();
m_hFontOld = NULL;
m_hFont = NULL;
m_isDirty = false;
m_bItalic = false;
}
bool CGraphicFontTexture::IsEmpty() const
{
return m_fontMap.size() == 0;
}
void CGraphicFontTexture::Destroy()
{
HDC hDC = m_dib.GetDCHandle();
if (hDC)
SelectObject(hDC, m_hFontOld);
m_dib.Destroy();
m_lpd3dTexture = NULL;
CGraphicTexture::Destroy();
stl_wipe(m_pFontTextureVector);
m_charInfoMap.clear();
if (m_fontMap.size())
{
TFontMap::iterator i = m_fontMap.begin();
while(i != m_fontMap.end())
{
TFontMap::mapped_type hFont = i->second;
auto hi = g_oversampled_fonts.find(hFont);
if (hi != g_oversampled_fonts.end())
{
DeleteObject((HGDIOBJ)hi->second);
g_oversampled_fonts.erase(hi);
}
DeleteObject((HGDIOBJ)i->second);
++i;
}
m_fontMap.clear();
}
Initialize();
}
bool CGraphicFontTexture::CreateDeviceObjects()
{
return true;
}
void CGraphicFontTexture::DestroyDeviceObjects()
{
}
bool CGraphicFontTexture::Create(const char* c_szFontName, int fontSize, bool bItalic)
{
Destroy();
strncpy(m_fontName, c_szFontName, sizeof(m_fontName)-1);
m_fontSize = fontSize;
m_bItalic = bItalic;
m_x = 0;
m_y = 0;
m_step = 0;
DWORD width = 256,height = 256;
if (GetMaxTextureWidth() > 512)
width = 512;
if (GetMaxTextureHeight() > 512)
height = 512;
const int s = FontOversample();
if (!m_dib.Create(ms_hDC, width * s, height * s))
return false;
HDC hDC = m_dib.GetDCHandle();
m_hFont = GetFont(GetDefaultCodePage());
m_hFontOld=(HFONT)SelectObject(hDC, m_hFont);
SetTextColor(hDC, RGB(255, 255, 255));
SetBkColor(hDC, 0);
if (!AppendTexture())
return false;
return true;
}
HFONT CGraphicFontTexture::GetFont(WORD codePage)
{
HFONT hFont = NULL;
TFontMap::iterator i = m_fontMap.find(codePage);
if(i != m_fontMap.end())
{
hFont = i->second;
}
else
{
LOGFONT logFont;
memset(&logFont, 0, sizeof(LOGFONT));
logFont.lfHeight = m_fontSize;
logFont.lfEscapement = 0;
logFont.lfOrientation = 0;
logFont.lfWeight = FW_NORMAL;
logFont.lfItalic = (BYTE) m_bItalic;
logFont.lfUnderline = FALSE;
logFont.lfStrikeOut = FALSE;
logFont.lfCharSet = GetCharsetFromCodePage(codePage);
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logFont.lfQuality = ANTIALIASED_QUALITY;
logFont.lfPitchAndFamily = DEFAULT_PITCH;
//Tracenf("font: %s", GetFontFaceFromCodePage(codePage));
strcpy(logFont.lfFaceName, m_fontName); //GetFontFaceFromCodePage(codePage));
//strcpy(logFont.lfFaceName, GetFontFaceFromCodePage(codePage));
hFont = CreateFontIndirect(&logFont);
m_fontMap.insert(TFontMap::value_type(codePage, hFont));
if (const int s = FontOversample(); s > 1 && hFont)
{
logFont.lfHeight = m_fontSize * s;
if (HFONT hHiFont = CreateFontIndirect(&logFont))
g_oversampled_fonts[hFont] = hHiFont;
}
}
return hFont;
}
bool CGraphicFontTexture::AppendTexture()
{
CGraphicImageTexture * pNewTexture = new CGraphicImageTexture;
if (!pNewTexture->Create(m_dib.GetWidth(), m_dib.GetHeight(), D3DFMT_A4R4G4B4))
{
delete pNewTexture;
return false;
}
m_pFontTextureVector.push_back(pNewTexture);
return true;
}
bool CGraphicFontTexture::UpdateTexture()
{
if(!m_isDirty)
return true;
m_isDirty = false;
CGraphicImageTexture * pFontTexture = m_pFontTextureVector.back();
if (!pFontTexture)
return false;
WORD* pwDst;
int pitch;
if (!pFontTexture->Lock(&pitch, (void**)&pwDst))
return false;
pitch /= 2;
int width = m_dib.GetWidth();
int height = m_dib.GetHeight();
DWORD * pdwSrc = (DWORD*)m_dib.GetPointer();
for (int y = 0; y < height; ++y, pwDst += pitch, pdwSrc += width)
for (int x = 0; x < width; ++x)
pwDst[x]=pdwSrc[x];
pFontTexture->Unlock();
return true;
}
CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::GetCharacterInfomation(WORD codePage, wchar_t keyValue)
{
TCharacterKey code(codePage, keyValue);
TCharacterInfomationMap::iterator f = m_charInfoMap.find(code);
if (m_charInfoMap.end() == f)
{
return UpdateCharacterInfomation(code);
}
else
{
return &f->second;
}
}
CGraphicFontTexture::TCharacterInfomation* CGraphicFontTexture::UpdateCharacterInfomation(TCharacterKey code)
{
HDC hDC = m_dib.GetDCHandle();
HFONT hFont = GetFont(code.first);
SelectObject(hDC, hFont);
wchar_t keyValue = code.second;
if (keyValue == 0x08)
keyValue = L' '; // 탭은 공백으로 바꾼다 (아랍 출력시 탭 사용: NAME:\tTEXT -> TEXT\t:NAME 로 전환됨 )
ABCFLOAT stABC;
SIZE size;
if (!GetTextExtentPoint32W(hDC, &keyValue, 1, &size) || !GetCharABCWidthsFloatW(hDC, keyValue, keyValue, &stABC))
return NULL;
size.cx = stABC.abcfB;
if( stABC.abcfA > 0.0f )
size.cx += ceilf(stABC.abcfA);
if( stABC.abcfC > 0.0f )
size.cx += ceilf(stABC.abcfC);
size.cx++;
LONG lAdvance = ceilf( stABC.abcfA + stABC.abcfB + stABC.abcfC );
const int s = FontOversample();
int width = m_dib.GetWidth() / s;
int height = m_dib.GetHeight() / s;
if (m_x + size.cx >= (width - 1))
{
m_y += (m_step + 1);
m_step = 0;
m_x = 0;
if (m_y + size.cy >= (height - 1))
{
if (!UpdateTexture())
{
return NULL;
}
if (!AppendTexture())
return NULL;
m_y = 0;
}
}
auto hi = s > 1 ? g_oversampled_fonts.find(hFont) : g_oversampled_fonts.end();
if (hi != g_oversampled_fonts.end())
{
// Draw with the s-times font into the s-scaled cell and keep its anti-aliasing as
// A4R4G4B4 white with coverage alpha (1x keeps 40250's bilevel threshold below).
SelectObject(hDC, hi->second);
TextOutW(hDC, m_x * s, m_y * s, &keyValue, 1);
SelectObject(hDC, hFont);
const int nDIBWidth = m_dib.GetWidth();
DWORD* pdwRow = (DWORD*)m_dib.GetPointer() + nDIBWidth * (m_y * s) + m_x * s;
for (int y = 0; y < size.cy * s; ++y, pdwRow += nDIBWidth)
for (int x = 0; x < size.cx * s; ++x)
{
const DWORD alpha = ((pdwRow[x] & 0xff) * 15 + 127) / 255;
pdwRow[x] = alpha ? ((alpha << 12) | 0x0fff) : 0;
}
}
else
{
TextOutW(hDC, m_x, m_y, &keyValue, 1);
int nChrX;
int nChrY;
int nChrWidth = size.cx;
int nChrHeight = size.cy;
int nDIBWidth = m_dib.GetWidth();
DWORD*pdwDIBData=(DWORD*)m_dib.GetPointer();
DWORD*pdwDIBBase=pdwDIBData+nDIBWidth*m_y+m_x;
DWORD*pdwDIBRow;
pdwDIBRow=pdwDIBBase;
for (nChrY=0; nChrY<nChrHeight; ++nChrY, pdwDIBRow+=nDIBWidth)
{
for (nChrX=0; nChrX<nChrWidth; ++nChrX)
{
pdwDIBRow[nChrX]=(pdwDIBRow[nChrX]&0xff) ? 0xffff : 0;
}
}
}
float rhwidth = 1.0f / float(width);
float rhheight = 1.0f / float(height);
TCharacterInfomation& rNewCharInfo = m_charInfoMap[code];
rNewCharInfo.index = static_cast<short>(m_pFontTextureVector.size() - 1);
rNewCharInfo.width = size.cx;
rNewCharInfo.height = size.cy;
rNewCharInfo.left = float(m_x) * rhwidth;
rNewCharInfo.top = float(m_y) * rhheight;
rNewCharInfo.right = float(m_x+size.cx) * rhwidth;
rNewCharInfo.bottom = float(m_y+size.cy) * rhheight;
rNewCharInfo.advance = (float) lAdvance;
m_x += size.cx;
if (m_step < size.cy)
m_step = size.cy;
m_isDirty = true;
return &rNewCharInfo;
}
bool CGraphicFontTexture::CheckTextureIndex(DWORD dwTexture)
{
if (dwTexture >= m_pFontTextureVector.size())
return false;
return true;
}
void CGraphicFontTexture::SelectTexture(DWORD dwTexture)
{
assert(CheckTextureIndex(dwTexture));
m_lpd3dTexture = m_pFontTextureVector[dwTexture]->GetD3DTexture();
}
+82
View File
@@ -0,0 +1,82 @@
// Platform skeleton for EterLib/GrpImage.h (40250 EterLib/GrpImage.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpImage.h"
#include "../PlatformStub.h"
auto CGraphicImage::Type() -> TType
{
static TType type = StringToType("CGraphicImage");
return type;
}
CGraphicImage::CGraphicImage(const char * c_szFileName, DWORD dwFilter) : CResource(c_szFileName), m_dwFilter(dwFilter) // initializers as in 40250
{
m_rect = {0, 0, 0, 0};
}
CGraphicImage::~CGraphicImage()
{
MT_PLATFORM_STUB();
}
auto CGraphicImage::CreateDeviceObjects() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CGraphicImage::DestroyDeviceObjects() -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicImage::GetWidth() const -> int
{
return m_rect.right - m_rect.left;
}
auto CGraphicImage::GetHeight() const -> int
{
return m_rect.bottom - m_rect.top;
}
auto CGraphicImage::GetRectReference() const -> const RECT &
{
return m_rect;
}
auto CGraphicImage::GetTextureReference() const -> const CGraphicTexture &
{
return m_imageTexture;
}
auto CGraphicImage::GetTexturePointer() -> CGraphicTexture *
{
return &m_imageTexture;
}
auto CGraphicImage::OnLoad(int size, const void *data) -> bool
{
m_imageTexture.SetFileName(GetFileName());
if (!m_imageTexture.CreateFromMemoryFile(size, data, D3DFMT_UNKNOWN, m_dwFilter)) return false;
m_rect = {0, 0, m_imageTexture.GetWidth(), m_imageTexture.GetHeight()};
return true;
}
auto CGraphicImage::OnClear() -> void
{
m_imageTexture.Destroy();
m_rect = {0, 0, 0, 0};
}
auto CGraphicImage::OnIsEmpty() const -> bool
{
return m_imageTexture.IsEmpty();
}
auto CGraphicImage::OnIsType(TType type) -> bool
{
return type == Type() || CResource::OnIsType(type);
}
+167
View File
@@ -0,0 +1,167 @@
// Platform skeleton for EterLib/GrpImageInstance.h (40250 EterLib/GrpImageInstance.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpImageInstance.h"
#include "../PlatformStub.h"
#include "UIRenderCommands.h"
#include "EterBase/CRC32.h"
auto CGraphicImageInstance::Type() -> DWORD
{
static DWORD type = GetCRC32("CGraphicImageInstance", sizeof("CGraphicImageInstance") - 1);
return type;
}
auto CGraphicImageInstance::IsType(DWORD type) -> BOOL
{
return OnIsType(type);
}
CGraphicImageInstance::CGraphicImageInstance()
{
m_DiffuseColor = D3DXCOLOR(1, 1, 1, 1);
m_v2Position = D3DXVECTOR2(0, 0);
}
CGraphicImageInstance::~CGraphicImageInstance()
{
Destroy();
}
// 40250 Destroy(): drop the image reference, then Initialize() (white, at the origin).
auto CGraphicImageInstance::Destroy() -> void
{
m_roImage.Clear();
m_DiffuseColor = D3DXCOLOR(1, 1, 1, 1);
m_v2Position = D3DXVECTOR2(0, 0);
}
auto CGraphicImageInstance::Render() -> void
{
if (!IsEmpty()) OnRender();
}
auto CGraphicImageInstance::SetDiffuseColor(float r, float g, float b, float a) -> void
{
m_DiffuseColor = D3DXCOLOR(r, g, b, a);
}
auto CGraphicImageInstance::SetPosition(float x, float y) -> void
{
m_v2Position = D3DXVECTOR2(x, y);
}
auto CGraphicImageInstance::SetImagePointer(CGraphicImage *image) -> void
{
m_roImage.SetPointer(image);
OnSetImagePointer();
}
auto CGraphicImageInstance::ReloadImagePointer(CGraphicImage *) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicImageInstance::IsEmpty() const -> bool
{
return m_roImage.IsNull() || m_roImage->IsEmpty();
}
auto CGraphicImageInstance::GetWidth() -> int
{
return IsEmpty() ? 0 : m_roImage->GetWidth();
}
auto CGraphicImageInstance::GetHeight() -> int
{
return IsEmpty() ? 0 : m_roImage->GetHeight();
}
auto CGraphicImageInstance::GetTexturePointer() -> CGraphicTexture *
{
CGraphicImage* pkImage = m_roImage.GetPointer();
return pkImage ? pkImage->GetTexturePointer() : NULL;
}
auto CGraphicImageInstance::GetTextureReference() const -> const CGraphicTexture &
{
return m_roImage->GetTextureReference();
}
auto CGraphicImageInstance::GetGraphicImagePointer() -> CGraphicImage *
{
return m_roImage.GetPointer();
}
auto CGraphicImageInstance::operator==(const CGraphicImageInstance &) const -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CGraphicImageInstance::Initialize() -> void
{
MT_PLATFORM_STUB();
}
// 40250 GrpImageInstance.cpp:44-96: the image's rect inside its texture (a .sub shares its parent's)
// becomes the texture coordinates of one quad.
auto CGraphicImageInstance::OnRender() -> void
{
CGraphicImage * pImage = m_roImage.GetPointer();
CGraphicTexture * pTexture = pImage->GetTexturePointer();
if (pTexture->GetWidth() <= 0 || pTexture->GetHeight() <= 0)
return;
float fimgWidth = pImage->GetWidth();
float fimgHeight = pImage->GetHeight();
const RECT& c_rRect = pImage->GetRectReference();
float texReverseWidth = 1.0f / float(pTexture->GetWidth());
float texReverseHeight = 1.0f / float(pTexture->GetHeight());
float su = c_rRect.left * texReverseWidth;
float sv = c_rRect.top * texReverseHeight;
float eu = (c_rRect.left + (c_rRect.right-c_rRect.left)) * texReverseWidth;
float ev = (c_rRect.top + (c_rRect.bottom-c_rRect.top)) * texReverseHeight;
const float x[4] = {m_v2Position.x-0.5f, m_v2Position.x + fimgWidth-0.5f,
m_v2Position.x-0.5f, m_v2Position.x + fimgWidth-0.5f};
const float y[4] = {m_v2Position.y-0.5f, m_v2Position.y-0.5f,
m_v2Position.y + fimgHeight-0.5f, m_v2Position.y + fimgHeight-0.5f};
UIRenderAddImage(pTexture, x, y, su, sv, eu, ev, UIRenderColor(m_DiffuseColor));
}
auto CGraphicImageInstance::OnSetImagePointer() -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicImageInstance::OnIsType(DWORD type) -> BOOL
{
return type == Type();
}
auto CGraphicImageInstance::CreateSystem(UINT) -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicImageInstance::DestroySystem() -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicImageInstance::New() -> CGraphicImageInstance *
{
return new CGraphicImageInstance();
}
auto CGraphicImageInstance::Delete(CGraphicImageInstance *instance) -> void
{
if (!instance) return;
instance->Destroy();
delete instance;
}
decltype(CGraphicImageInstance::ms_kPool) CGraphicImageInstance::ms_kPool{};
+338
View File
@@ -0,0 +1,338 @@
// Platform skeleton for EterLib/GrpImageTexture.h (40250 EterLib/GrpImageTexture.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpImageTexture.h"
#include "../PlatformStub.h"
#include "UIRenderCommands.h"
#include <cstring>
#include <map>
#include <mutex>
#include <set>
namespace {
unsigned little16(const unsigned char* data) { return data[0] | (unsigned(data[1]) << 8); }
unsigned little32(const unsigned char* data) { return little16(data) | (little16(data + 2) << 16); }
unsigned big16(const unsigned char* data) { return (unsigned(data[0]) << 8) | data[1]; }
unsigned big32(const unsigned char* data) { return (unsigned(data[0]) << 24) | (unsigned(data[1]) << 16) | (unsigned(data[2]) << 8) | data[3]; }
// Walks the JPEG markers to the first SOFn (the frame header holds the size), as D3DX does when it
// sniffs a .jpg; login/loading backgrounds (serverlist.jpg, loading/*.jpg) are JPEGs.
bool jpeg_size(const unsigned char* data, unsigned size, unsigned* width, unsigned* height)
{
if (size < 4 || data[0] != 0xFF || data[1] != 0xD8) return false;
unsigned pos = 2;
while (pos + 4 <= size) {
if (data[pos] != 0xFF) return false;
const unsigned char marker = data[pos + 1];
if (marker == 0xFF) { ++pos; continue; }
if (marker == 0xD8 || marker == 0x01 || (marker >= 0xD0 && marker <= 0xD7)) { pos += 2; continue; }
const unsigned length = big16(data + pos + 2);
if (length < 2) return false;
const bool sof = marker >= 0xC0 && marker <= 0xCF && marker != 0xC4 && marker != 0xC8 && marker != 0xCC;
if (sof) {
if (pos + 9 > size) return false;
*height = big16(data + pos + 5);
*width = big16(data + pos + 7);
return true;
}
pos += 2 + length;
}
return false;
}
// PORT: the IDirect3DTexture8 behind a CGraphicImageTexture::Create texture. Lock hands out the
// pixels in the texture's own format (40250 writes A4R4G4B4 words into the font pages); Unlock
// converts them to ARGB32 for the canvas and bumps the revision in the texture's name.
struct MemoryTexture : IDirect3DTexture8
{
unsigned id = 0;
int width = 0;
int height = 0;
D3DFORMAT format = D3DFMT_UNKNOWN;
std::vector<unsigned char> native;
std::vector<std::uint32_t> argb;
std::uint32_t revision = 0;
};
std::mutex g_memory_mutex;
std::map<unsigned, MemoryTexture*> g_memory;
unsigned g_memory_next_id = 1;
int bytes_per_pixel(D3DFORMAT format)
{
switch (format) {
case D3DFMT_A4R4G4B4: case D3DFMT_R5G6B5: case D3DFMT_A1R5G5B5: case D3DFMT_X1R5G5B5: case D3DFMT_X4R4G4B4:
return 2;
default:
return 4;
}
}
std::uint32_t expand(unsigned value, int bits)
{
return bits == 4 ? value * 0x11 : bits == 5 ? (value << 3) | (value >> 2) : bits == 6 ? (value << 2) | (value >> 4) : value;
}
std::uint32_t native_to_argb(D3DFORMAT format, const unsigned char* p)
{
const unsigned w = p[0] | (unsigned(p[1]) << 8);
switch (format) {
case D3DFMT_A4R4G4B4:
return (expand(w >> 12, 4) << 24) | (expand((w >> 8) & 15, 4) << 16) | (expand((w >> 4) & 15, 4) << 8) | expand(w & 15, 4);
case D3DFMT_X4R4G4B4:
return 0xFF000000u | (expand((w >> 8) & 15, 4) << 16) | (expand((w >> 4) & 15, 4) << 8) | expand(w & 15, 4);
case D3DFMT_R5G6B5:
return 0xFF000000u | (expand(w >> 11, 5) << 16) | (expand((w >> 5) & 63, 6) << 8) | expand(w & 31, 5);
case D3DFMT_A1R5G5B5: case D3DFMT_X1R5G5B5:
return ((format == D3DFMT_X1R5G5B5 || (w & 0x8000)) ? 0xFF000000u : 0) | (expand((w >> 10) & 31, 5) << 16) |
(expand((w >> 5) & 31, 5) << 8) | expand(w & 31, 5);
case D3DFMT_X8R8G8B8:
return 0xFF000000u | (p[2] << 16) | (p[1] << 8) | p[0];
default:
return (std::uint32_t(p[3]) << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
}
}
MemoryTexture* live_memory_texture(const IDirect3DTexture8* texture)
{
for (const auto& entry : g_memory)
if (entry.second == texture) return entry.second;
return nullptr;
}
// PORT: the IDirect3DTexture8 behind a file texture (CreateFromMemoryFile). The canvas and the 3D
// renderer decode the file themselves; the handle only carries the pack path so a texture bound
// through STATEMANAGER.SetTexture(stage, GetD3DTexture()) can be named.
struct FileTexture : IDirect3DTexture8
{
std::string name;
};
std::set<const FileTexture*> g_file_textures; // guarded by g_memory_mutex
IDirect3DTexture8* new_file_texture(const std::string& name)
{
auto* file = new FileTexture();
file->name = name;
std::lock_guard<std::mutex> lock(g_memory_mutex);
g_file_textures.insert(file);
return file;
}
}
void UIRenderReleaseMemoryTexture(IDirect3DTexture8* texture)
{
std::lock_guard<std::mutex> lock(g_memory_mutex);
if (MemoryTexture* memory = live_memory_texture(texture)) {
g_memory.erase(memory->id);
delete memory;
} else if (g_file_textures.erase(static_cast<const FileTexture*>(texture))) {
delete static_cast<FileTexture*>(texture);
}
}
std::string UIRenderTextureNameFromHandle(const IDirect3DBaseTexture8* handle)
{
if (!handle) return {};
const auto* texture = static_cast<const IDirect3DTexture8*>(handle);
{
std::lock_guard<std::mutex> lock(g_memory_mutex);
if (const MemoryTexture* memory = live_memory_texture(texture))
return "mem:" + std::to_string(memory->id) + "@" + std::to_string(memory->revision);
const auto* file = static_cast<const FileTexture*>(texture);
if (g_file_textures.count(file))
return file->name;
}
return MtCpuTextureNameFromHandle(handle);
}
bool UIRenderMemoryTexture(const std::string& name, UIMemoryTexture* out)
{
if (name.compare(0, 4, "mem:") != 0 || !out) return false;
if (name.compare(0, 8, "mem:cpu_") == 0)
return MtCpuMemoryTexture(name, out);
const unsigned id = unsigned(std::strtoul(name.c_str() + 4, nullptr, 10));
std::lock_guard<std::mutex> lock(g_memory_mutex);
auto it = g_memory.find(id);
if (it == g_memory.end()) return false;
out->width = it->second->width;
out->height = it->second->height;
out->revision = it->second->revision;
out->argb = it->second->argb;
return true;
}
CGraphicImageTexture::CGraphicImageTexture()
{
Initialize();
}
CGraphicImageTexture::~CGraphicImageTexture()
{
Destroy();
}
auto CGraphicImageTexture::Destroy() -> void
{
CGraphicTexture::Destroy();
Initialize();
}
auto CGraphicImageTexture::Create(UINT width, UINT height, D3DFORMAT d3dFmt, DWORD dwFilter) -> bool
{
Destroy();
m_width = width;
m_height = height;
m_d3dFmt = d3dFmt;
m_dwFilter = dwFilter;
return CreateDeviceObjects();
}
auto CGraphicImageTexture::CreateDeviceObjects() -> bool
{
if (m_stFileName.empty())
{
// PORT: ms_lpd3dDevice->CreateTexture(m_width, m_height, 1, 0, m_d3dFmt, D3DPOOL_MANAGED) becomes a
// memory texture the canvas fetches by name.
if (m_width <= 0 || m_height <= 0)
return false;
auto* memory = new MemoryTexture();
memory->width = m_width;
memory->height = m_height;
memory->format = m_d3dFmt;
memory->native.assign(size_t(m_width) * size_t(m_height) * size_t(bytes_per_pixel(m_d3dFmt)), 0);
memory->argb.assign(size_t(m_width) * size_t(m_height), 0);
{
std::lock_guard<std::mutex> lock(g_memory_mutex);
memory->id = g_memory_next_id++;
g_memory[memory->id] = memory;
}
m_lpd3dTexture = memory;
}
else
{
// PORT: file textures are decoded by the canvas from the pack path; only their size is read here
// (CreateFromMemoryFile), so there is no device object to recreate.
return !m_bEmpty;
}
m_bEmpty = false;
return true;
}
auto CGraphicImageTexture::CreateFromTexturePointer(const CGraphicTexture *source) -> void
{
if (!source) { Destroy(); return; }
m_width = source->GetWidth();
m_height = source->GetHeight();
m_bEmpty = source->IsEmpty();
// 40250 shares the source's D3D texture; the canvas names textures by pack path instead.
if (const auto* image = dynamic_cast<const CGraphicImageTexture*>(source))
m_stFileName = image->m_stFileName;
// PORT: 40250 AddRefs the source's texture; this handle is not reference counted, so the copy gets
// its own named handle.
DestroyDeviceObjects();
if (!m_bEmpty && !m_stFileName.empty())
m_lpd3dTexture = new_file_texture(m_stFileName);
}
auto CGraphicImageTexture::CreateFromDiskFile(const char *, D3DFORMAT, DWORD) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CGraphicImageTexture::CreateFromMemoryFile(UINT size, const void *bytes, D3DFORMAT, DWORD) -> bool
{
if (!bytes) return false;
const auto* data = static_cast<const unsigned char*>(bytes);
unsigned width = 0, height = 0;
if (size >= 20 && std::memcmp(data, "DDS ", 4) == 0) {
height = little32(data + 12); width = little32(data + 16);
} else if (size >= 24 && std::memcmp(data, "\x89PNG\r\n\x1a\n", 8) == 0) {
width = big32(data + 16); height = big32(data + 20);
} else if (jpeg_size(data, size, &width, &height)) {
} else if (size >= 26 && data[0] == 'B' && data[1] == 'M') {
width = little32(data + 18);
const int bmp_height = static_cast<int>(little32(data + 22)); // negative: top-down rows
height = static_cast<unsigned>(bmp_height < 0 ? -bmp_height : bmp_height);
} else if (size >= 18 && (data[2] == 2 || data[2] == 10 || data[2] == 3)) {
width = little16(data + 12); height = little16(data + 14);
}
if (!width || !height || width > 16384 || height > 16384) return false;
m_width = static_cast<int>(width); m_height = static_cast<int>(height);
m_bEmpty = false;
DestroyDeviceObjects();
m_lpd3dTexture = new_file_texture(m_stFileName);
return true;
}
auto CGraphicImageTexture::CreateDDSTexture(CDXTCImage &, const BYTE *) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CGraphicImageTexture::SetFileName(const char *name) -> void
{
m_stFileName = name ? name : "";
}
// PORT: where 40250 binds pTexture->GetD3DTexture(), the canvas gets the pack path of the file the
// texture was decoded from (m_stFileName is protected, hence the derived accessor), or the name of the
// memory texture bound to it (a CGraphicFontTexture after SelectTexture).
std::string UIRenderTextureName(const CGraphicTexture* texture)
{
if (!texture) return {};
if (texture->GetD3DTexture()) {
std::lock_guard<std::mutex> lock(g_memory_mutex);
if (const MemoryTexture* memory = live_memory_texture(texture->GetD3DTexture()))
return "mem:" + std::to_string(memory->id) + "@" + std::to_string(memory->revision);
}
struct Access : CGraphicImageTexture {
static const std::string& name(const CGraphicImageTexture* t) { return t->*(&Access::m_stFileName); }
};
const auto* image = dynamic_cast<const CGraphicImageTexture*>(texture);
return image ? Access::name(image) : std::string();
}
// PORT: LockRect/UnlockRect on the memory texture (one level; the lock is on the whole surface).
auto CGraphicImageTexture::Lock(int* pRetPitch, void** ppRetPixels, int) -> bool
{
std::lock_guard<std::mutex> lock(g_memory_mutex);
MemoryTexture* memory = live_memory_texture(m_lpd3dTexture);
if (!memory)
return false;
*pRetPitch = memory->width * bytes_per_pixel(memory->format);
*ppRetPixels = memory->native.data();
return true;
}
auto CGraphicImageTexture::Unlock(int) -> void
{
std::lock_guard<std::mutex> lock(g_memory_mutex);
MemoryTexture* memory = live_memory_texture(m_lpd3dTexture);
assert(memory != NULL);
if (!memory)
return;
const int bpp = bytes_per_pixel(memory->format);
for (size_t i = 0; i < memory->argb.size(); ++i)
memory->argb[i] = native_to_argb(memory->format, memory->native.data() + i * size_t(bpp));
++memory->revision;
}
auto CGraphicImageTexture::Initialize() -> void
{
CGraphicTexture::Initialize();
m_stFileName = "";
m_d3dFmt=D3DFMT_UNKNOWN;
m_dwFilter=0;
}
+130
View File
@@ -0,0 +1,130 @@
// 40250 EterLib/GrpIndexBuffer.cpp over CPU memory (CpuBuffer.h).
#include "EterLib/StdAfx.h"
#include "EterLib/GrpIndexBuffer.h"
#include "EterLib/StateManager.h"
#include "CpuBuffer.h"
namespace {
BYTE* index_bytes(LPDIRECT3DINDEXBUFFER8 buffer)
{
return static_cast<MtCpuIndexBuffer*>(buffer)->bytes.data();
}
}
LPDIRECT3DINDEXBUFFER8 CGraphicIndexBuffer::GetD3DIndexBuffer() const
{
assert(m_lpd3dIdxBuf!=NULL);
return m_lpd3dIdxBuf;
}
void CGraphicIndexBuffer::SetIndices(int startIndex) const
{
STATEMANAGER.SetIndices(m_lpd3dIdxBuf, startIndex);
}
bool CGraphicIndexBuffer::Lock(void** pretIndices) const
{
assert(m_lpd3dIdxBuf!=NULL);
*pretIndices = index_bytes(m_lpd3dIdxBuf);
return true;
}
void CGraphicIndexBuffer::Unlock() const
{
assert(m_lpd3dIdxBuf!=NULL);
static_cast<MtCpuIndexBuffer*>(m_lpd3dIdxBuf)->revision++;
}
bool CGraphicIndexBuffer::Lock(void** pretIndices)
{
assert(m_lpd3dIdxBuf!=NULL);
*pretIndices = index_bytes(m_lpd3dIdxBuf);
return true;
}
void CGraphicIndexBuffer::Unlock()
{
assert(m_lpd3dIdxBuf!=NULL);
static_cast<MtCpuIndexBuffer*>(m_lpd3dIdxBuf)->revision++;
}
bool CGraphicIndexBuffer::Copy(int bufSize, const void* srcIndices)
{
assert(m_lpd3dIdxBuf!=NULL);
memcpy(index_bytes(m_lpd3dIdxBuf), srcIndices, bufSize);
static_cast<MtCpuIndexBuffer*>(m_lpd3dIdxBuf)->revision++;
return true;
}
bool CGraphicIndexBuffer::Create(int faceCount, TFace* faces)
{
int idxCount = faceCount * 3;
m_iidxCount = idxCount;
if (!Create(idxCount, D3DFMT_INDEX16))
return false;
WORD* dstIndices = reinterpret_cast<WORD*>(index_bytes(m_lpd3dIdxBuf));
for (int i = 0; i<faceCount; ++i, dstIndices+=3)
{
TFace * curFace=faces+i;
dstIndices[0]=curFace->indices[0];
dstIndices[1]=curFace->indices[1];
dstIndices[2]=curFace->indices[2];
}
static_cast<MtCpuIndexBuffer*>(m_lpd3dIdxBuf)->revision++;
return true;
}
bool CGraphicIndexBuffer::CreateDeviceObjects()
{
MtCpuIndexBuffer* buffer = new MtCpuIndexBuffer;
buffer->bytes.assign(m_dwBufferSize, 0);
buffer->format = m_d3dFmt;
m_lpd3dIdxBuf = buffer;
return true;
}
void CGraphicIndexBuffer::DestroyDeviceObjects()
{
delete static_cast<MtCpuIndexBuffer*>(m_lpd3dIdxBuf);
m_lpd3dIdxBuf = NULL;
}
bool CGraphicIndexBuffer::Create(int idxCount, D3DFORMAT d3dFmt)
{
Destroy();
m_iidxCount = idxCount;
m_dwBufferSize = sizeof(WORD) * idxCount;
m_d3dFmt = d3dFmt;
return CreateDeviceObjects();
}
void CGraphicIndexBuffer::Destroy()
{
DestroyDeviceObjects();
}
void CGraphicIndexBuffer::Initialize()
{
m_lpd3dIdxBuf=NULL;
m_iidxCount=0;
m_dwBufferSize=0;
}
CGraphicIndexBuffer::CGraphicIndexBuffer()
{
Initialize();
}
CGraphicIndexBuffer::~CGraphicIndexBuffer()
{
Destroy();
}
+45
View File
@@ -0,0 +1,45 @@
// Platform skeleton for EterLib/GrpMath.h (40250 EterLib/GrpMath.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpMath.h"
#include "../PlatformStub.h"
auto CrossProduct2D(float, float, float, float) -> float
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<float>();
}
auto IsInTriangle2D(float, float, float, float, float, float, float, float) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto D3DXVec3Rotation(D3DXVECTOR3 *, const D3DXVECTOR3 *, const D3DXQUATERNION *) -> D3DXVECTOR3 *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3DXVECTOR3 *>();
}
auto D3DXVec3Translation(D3DXVECTOR3 *, const D3DXVECTOR3 *, const D3DXVECTOR3 *) -> D3DXVECTOR3 *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<D3DXVECTOR3 *>();
}
auto GetRotationFromMatrix(D3DXVECTOR3 *, const D3DXMATRIX *) -> void
{
MT_PLATFORM_STUB();
}
auto GetPivotAndRotationFromMatrix(D3DXMATRIX *, D3DXVECTOR3 *, D3DXVECTOR3 *) -> void
{
MT_PLATFORM_STUB();
}
auto ExtractMovement(D3DXMATRIX *, D3DXMATRIX *) -> void
{
MT_PLATFORM_STUB();
}
+435
View File
@@ -0,0 +1,435 @@
// Platform skeleton for EterLib/GrpScreen.h (40250 EterLib/GrpScreen.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpScreen.h"
#include "EterLib/StateManager.h"
#include "EterLib/Camera.h"
#include "../PlatformStub.h"
#include "UIRenderCommands.h"
#include <algorithm>
// 40250 GrpScreen.cpp:838
CScreen::CScreen()
{
}
CScreen::~CScreen()
{
}
auto CScreen::ClearDepthBuffer() -> void
{
if (ms_lpd3dDevice)
ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_ZBUFFER, ms_clearColor, ms_clearDepth, ms_clearStencil);
}
auto CScreen::Clear() -> void
{
if (ms_lpd3dDevice)
ms_lpd3dDevice->Clear(0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, ms_clearColor, ms_clearDepth, ms_clearStencil);
}
// 40250 GrpScreen.cpp:691. CPythonApplication::Process brackets the frame's render with Begin/End; only
// inside the scene does CStateManager hand transforms to the recording device.
bool CScreen::Begin()
{
assert(ms_lpd3dDevice != NULL);
ResetFaceCount();
if (!STATEMANAGER.BeginScene())
{
Tracenf("BeginScene FAILED\n");
return false;
}
return true;
}
// 40250 GrpScreen.cpp:705
void CScreen::End()
{
STATEMANAGER.EndScene();
}
auto CScreen::Show(HWND) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::Show(RECT *) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::Show(RECT *, HWND) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderLine2d(float sx, float sy, float ex, float ey, float) -> void
{
UIRenderAdd({UIRenderCommand::Line, sx, sy, ex, ey, ms_diffuseColor});
}
auto CScreen::RenderBox2d(float sx, float sy, float ex, float ey, float) -> void
{
// 40250's four line pairs, including its one-pixel extension of the bottom edge.
UIRenderAdd({UIRenderCommand::Line, sx, sy, ex, sy, ms_diffuseColor});
UIRenderAdd({UIRenderCommand::Line, sx, sy, sx, ey, ms_diffuseColor});
UIRenderAdd({UIRenderCommand::Line, ex, sy, ex, ey, ms_diffuseColor});
UIRenderAdd({UIRenderCommand::Line, sx, ey, ex + 1.0f, ey, ms_diffuseColor});
}
auto CScreen::RenderBar2d(float sx, float sy, float ex, float ey, float) -> void
{
UIRenderAdd({UIRenderCommand::Bar, sx, sy, ex, ey, ms_diffuseColor});
}
auto CScreen::RenderGradationBar2d(float sx, float sy, float ex, float ey, DWORD start, DWORD end, float) -> void
{
if (sx == ex || sy == ey)
return;
UIRenderCommand command{UIRenderCommand::GradientBar, sx, sy, ex, ey, start};
command.end_argb = end;
UIRenderAdd(std::move(command));
}
auto CScreen::RenderCircle2d(float, float, float, float, int) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderCircle3d(float, float, float, float, int) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderLine3d(float, float, float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderBox3d(float, float, float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderBar3d(float, float, float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderBar3d(const D3DXVECTOR3 *) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderGradationBar3d(float, float, float, float, float, float, DWORD, DWORD) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderLineCube(float, float, float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderCube(float, float, float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderCube(float, float, float, float, float, float, D3DXMATRIX) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderTextureBox(float, float, float, float, float, float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderBillboard(D3DXVECTOR3 *, D3DXCOLOR &) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::DrawMinorGrid(float, float, float, float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::DrawGrid(float, float, float, float, float, float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderD3DXMesh(LPD3DXMESH, const D3DXMATRIX *, float, float, float, float, D3DFILLMODE) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderSphere(const D3DXMATRIX *, float, float, float, float, D3DFILLMODE) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::RenderCylinder(const D3DXMATRIX *, float, float, float, float, float, D3DFILLMODE) -> void
{
MT_PLATFORM_STUB();
}
// 40250 GrpScreen.cpp
void CScreen::SetColorOperation()
{
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
}
// 40250 GrpScreen.cpp
void CScreen::SetDiffuseOperation()
{
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
}
// 40250 GrpScreen.cpp
void CScreen::SetBlendOperation()
{
STATEMANAGER.SetTexture(0, NULL);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
}
auto CScreen::SetOneColorOperation(D3DXCOLOR &) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::SetAddColorOperation(D3DXCOLOR &) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::SetDiffuseColor(DWORD color) -> void
{
ms_diffuseColor = color;
}
auto CScreen::SetDiffuseColor(float r, float g, float b, float a) -> void
{
auto channel = [](float value) -> DWORD {
return static_cast<DWORD>(std::clamp(value, 0.0f, 1.0f) * 255.0f + 0.5f);
};
ms_diffuseColor = (channel(a) << 24) | (channel(r) << 16) | (channel(g) << 8) | channel(b);
}
auto CScreen::SetClearColor(float, float, float, float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::SetClearDepth(float) -> void
{
MT_PLATFORM_STUB();
}
auto CScreen::SetClearStencil(DWORD) -> void
{
MT_PLATFORM_STUB();
}
// 40250 GrpScreen.cpp:487, verbatim: the pick ray through the cursor.
void CScreen::SetCursorPosition(int x, int y, int hres, int vres)
{
D3DXVECTOR3 v;
v.x = -(((2.0f * x) / hres) - 1) / ms_matProj._11;
v.y = (((2.0f * y) / vres) - 1) / ms_matProj._22;
v.z = 1.0f;
D3DXMATRIX matViewInverse=ms_matInverseView;
//D3DXMatrixInverse(&matViewInverse, NULL, &ms_matView);
ms_vtPickRayDir.x = v.x * matViewInverse._11 +
v.y * matViewInverse._21 +
v.z * matViewInverse._31;
ms_vtPickRayDir.y = v.x * matViewInverse._12 +
v.y * matViewInverse._22 +
v.z * matViewInverse._32;
ms_vtPickRayDir.z = v.x * matViewInverse._13 +
v.y * matViewInverse._23 +
v.z * matViewInverse._33;
ms_vtPickRayOrig.x = matViewInverse._41;
ms_vtPickRayOrig.y = matViewInverse._42;
ms_vtPickRayOrig.z = matViewInverse._43;
ms_Ray.SetStartPoint(ms_vtPickRayOrig);
ms_Ray.SetDirection(-ms_vtPickRayDir, 51200.0f);
}
auto CScreen::GetCursorPosition(float * px, float * py, float * pz) -> bool
{
if (!GetCursorXYPosition(px, py)) return false;
if (!GetCursorZPosition(pz)) return false;
return true;
}
auto CScreen::GetCursorXYPosition(float * px, float * py) -> bool
{
D3DXVECTOR3 v3Eye = CCameraManager::Instance().GetCurrentCamera()->GetEye();
TPosition posVertices[4];
posVertices[0] = TPosition(v3Eye.x - 90000000.0f, v3Eye.y + 90000000.0f, 0.0f);
posVertices[1] = TPosition(v3Eye.x - 90000000.0f, v3Eye.y - 90000000.0f, 0.0f);
posVertices[2] = TPosition(v3Eye.x + 90000000.0f, v3Eye.y + 90000000.0f, 0.0f);
posVertices[3] = TPosition(v3Eye.x + 90000000.0f, v3Eye.y - 90000000.0f, 0.0f);
static const WORD sc_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, };
float u, v, t;
for (int i = 0; i < 2; ++i)
{
if (IntersectTriangle(ms_vtPickRayOrig, ms_vtPickRayDir,
posVertices[sc_awFillRectIndices[i * 3]],
posVertices[sc_awFillRectIndices[i * 3 + 1]],
posVertices[sc_awFillRectIndices[i * 3 + 2]],
&u, &v, &t))
{
*px = u;
*py = v;
return true;
}
}
return false;
}
auto CScreen::GetCursorZPosition(float * pz) -> bool
{
D3DXVECTOR3 v3Eye = CCameraManager::Instance().GetCurrentCamera()->GetEye();
TPosition posVertices[4];
posVertices[0] = TPosition(v3Eye.x - 90000000.0f, 0.0f, v3Eye.z + 90000000.0f);
posVertices[1] = TPosition(v3Eye.x - 90000000.0f, 0.0f, v3Eye.z - 90000000.0f);
posVertices[2] = TPosition(v3Eye.x + 90000000.0f, 0.0f, v3Eye.z + 90000000.0f);
posVertices[3] = TPosition(v3Eye.x + 90000000.0f, 0.0f, v3Eye.z - 90000000.0f);
static const WORD sc_awFillRectIndices[6] = { 0, 2, 1, 2, 3, 1, };
float u, v, t;
for (int i = 0; i < 2; ++i)
{
if (IntersectTriangle(ms_vtPickRayOrig, ms_vtPickRayDir,
posVertices[sc_awFillRectIndices[i * 3]],
posVertices[sc_awFillRectIndices[i * 3 + 1]],
posVertices[sc_awFillRectIndices[i * 3 + 2]],
&u, &v, &t))
{
*pz = t;
return true;
}
}
return false;
}
auto CScreen::GetPickingPosition(float t, float * x, float * y, float * z) -> void
{
*x = ms_vtPickRayOrig.x + ms_vtPickRayDir.x * t;
*y = ms_vtPickRayOrig.y + ms_vtPickRayDir.y * t;
*z = ms_vtPickRayOrig.z + ms_vtPickRayDir.z * t;
}
// 40250 GrpScreen.cpp:749-779.
void CScreen::ProjectPosition(float x, float y, float z, float * pfX, float * pfY)
{
D3DXVECTOR3 Input(x, y, z);
D3DXVECTOR3 Output;
D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matIdentity);
*pfX = Output.x;
*pfY = Output.y;
}
void CScreen::ProjectPosition(float x, float y, float z, float * pfX, float * pfY, float * pfZ)
{
D3DXVECTOR3 Input(x, y, z);
D3DXVECTOR3 Output;
D3DXVec3Project(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matIdentity);
*pfX = Output.x;
*pfY = Output.y;
*pfZ = Output.z;
}
void CScreen::UnprojectPosition(float x, float y, float z, float * pfX, float * pfY, float * pfZ)
{
D3DXVECTOR3 Input(x, y, z);
D3DXVECTOR3 Output;
D3DXVec3Unproject(&Output, &Input, &ms_Viewport, &ms_matProj, &ms_matView, &ms_matIdentity);
*pfX = Output.x;
*pfY = Output.y;
*pfZ = Output.z;
}
auto CScreen::IsLostDevice() -> BOOL
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<BOOL>();
}
auto CScreen::RestoreDevice() -> BOOL
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<BOOL>();
}
auto CScreen::BuildViewFrustum() -> void
{
CCamera* pkCamera = CCameraManager::Instance().GetCurrentCamera();
if (!pkCamera)
return;
const D3DXVECTOR3& c_rv3Eye = pkCamera->GetEye();
const D3DXVECTOR3& c_rv3View = pkCamera->GetView();
auto vv = ms_matView * ms_matProj;
ms_frustum.BuildViewFrustum2(
vv,
ms_fNearY,
ms_fFarY,
ms_fFieldOfView,
ms_fAspect,
c_rv3Eye, c_rv3View);
}
auto CScreen::Identity() -> void
{
STATEMANAGER.SetTransform(D3DTS_WORLD, &ms_matIdentity);
}
decltype(CScreen::ms_diffuseColor) CScreen::ms_diffuseColor = 0xffffffff;
decltype(CScreen::ms_clearColor) CScreen::ms_clearColor{};
decltype(CScreen::ms_clearStencil) CScreen::ms_clearStencil{};
decltype(CScreen::ms_clearDepth) CScreen::ms_clearDepth = 1.0f;
decltype(CScreen::ms_frustum) CScreen::ms_frustum{};
+100
View File
@@ -0,0 +1,100 @@
#include "EterLib/StdAfx.h"
#include "EterLib/GrpSubImage.h"
#include "EterLib/ResourceManager.h"
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <map>
#include <sstream>
#include <string>
char CGraphicSubImage::m_SearchPath[256] = "D:/Ymir Work/UI/";
auto CGraphicSubImage::Type() -> TType
{
static TType type = StringToType("CGraphicSubImage");
return type;
}
CGraphicSubImage::CGraphicSubImage(const char* name) : CGraphicImage(name) {}
CGraphicSubImage::~CGraphicSubImage() { m_roImage.Clear(); }
bool CGraphicSubImage::CreateDeviceObjects()
{
if (m_roImage.IsNull()) return false;
m_imageTexture.CreateFromTexturePointer(m_roImage->GetTexturePointer());
return true;
}
void CGraphicSubImage::SetImagePointer(CGraphicImage* image)
{
m_roImage.SetPointer(image);
CreateDeviceObjects();
}
bool CGraphicSubImage::SetImageFileName(const char* name)
{
CResource* resource = CResourceManager::Instance().GetResourcePointer(name);
if (!resource || !resource->IsType(CGraphicImage::Type())) return false;
SetImagePointer(static_cast<CGraphicImage*>(resource));
return true;
}
void CGraphicSubImage::SetRectPosition(int left, int top, int right, int bottom)
{
m_rect = {left, top, right, bottom};
}
void CGraphicSubImage::SetRectReference(const RECT& rect) { m_rect = rect; }
void CGraphicSubImage::SetSearchPath(const char* path)
{
if (!path) return;
std::strncpy(m_SearchPath, path, sizeof(m_SearchPath) - 1);
m_SearchPath[sizeof(m_SearchPath) - 1] = 0;
}
bool CGraphicSubImage::OnLoad(int size, const void* bytes)
{
if (!bytes || size <= 0) return false;
std::istringstream input(std::string(static_cast<const char*>(bytes), static_cast<size_t>(size)));
std::map<std::string, std::string> tokens;
std::string line;
while (std::getline(input, line)) {
std::istringstream fields(line);
std::string key, value;
if (!(fields >> key >> value)) continue;
if (!value.empty() && value.front() == '"') {
value.erase(0, 1);
if (!value.empty() && value.back() == '"') value.pop_back();
}
std::transform(key.begin(), key.end(), key.begin(), [](unsigned char c) { return std::tolower(c); });
std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) { return std::tolower(c); });
tokens[key] = value;
}
if (tokens["title"] != "subimage" || tokens["image"].empty()) return false;
std::string image_path;
if (tokens["version"] == "2.0") {
const std::string parent = GetFileNameString();
const auto slash = parent.find_last_of("\\/");
image_path = slash == std::string::npos ? tokens["image"] : parent.substr(0, slash + 1) + tokens["image"];
} else {
image_path = std::string(m_SearchPath) + tokens["image"];
}
if (!SetImageFileName(image_path.c_str())) return false;
SetRectPosition(std::atoi(tokens["left"].c_str()), std::atoi(tokens["top"].c_str()),
std::atoi(tokens["right"].c_str()), std::atoi(tokens["bottom"].c_str()));
return true;
}
void CGraphicSubImage::OnClear()
{
m_roImage.Clear();
m_imageTexture.Destroy();
m_rect = {0, 0, 0, 0};
}
bool CGraphicSubImage::OnIsEmpty() const { return m_roImage.IsNull() || m_roImage->IsEmpty(); }
bool CGraphicSubImage::OnIsType(TType type) { return type == Type() || CGraphicImage::OnIsType(type); }
+102
View File
@@ -0,0 +1,102 @@
// 40250 EterLib/GrpText.cpp, verbatim.
#include "EterLib/StdAfx.h"
#include "EterBase/Utils.h"
#include "EterLib/GrpText.h"
CGraphicText::CGraphicText(const char* c_szFileName) : CResource(c_szFileName)
{
}
CGraphicText::~CGraphicText()
{
}
bool CGraphicText::CreateDeviceObjects()
{
return m_fontTexture.CreateDeviceObjects();
}
void CGraphicText::DestroyDeviceObjects()
{
m_fontTexture.DestroyDeviceObjects();
}
CGraphicFontTexture* CGraphicText::GetFontTexturePointer()
{
return &m_fontTexture;
}
CGraphicText::TType CGraphicText::Type()
{
static TType s_type = StringToType("CGraphicText");
return s_type;
}
bool CGraphicText::OnLoad(int /*iSize*/, const void* /*c_pvBuf*/)
{
static char strName[32];
int size;
bool bItalic = false;
// format
// 굴림.fnt "굴림" 폰트 기본 사이즈 12 로 로딩
// 굴림:18.fnt "굴림" 폰트 사이즈 18 로 로딩
// 굴림:14i.fnt "굴림" 폰트 사이즈 14 & 이탤릭으로 로딩
const char * p = strrchr(GetFileName(), ':');
if (p)
{
strncpy(strName, GetFileName(), MIN(31, p - GetFileName()));
++p;
static char num[8];
int i = 0;
while (*p && isdigit(*p))
{
num[i++] = *(p++);
}
num[i] = '\0';
if(*p == 'i')
bItalic = true;
size = atoi(num);
}
else
{
p = strrchr(GetFileName(), '.');
if (!p)
{
assert(!"CGraphicText::OnLoadFromFile there is no extension (ie: .fnt)");
strName[0] = '\0';
}
else
strncpy(strName, GetFileName(), MIN(31, p - GetFileName()));
size = 12;
}
if (!m_fontTexture.Create(strName, size, bItalic))
return false;
return true;
}
void CGraphicText::OnClear()
{
m_fontTexture.Destroy();
}
bool CGraphicText::OnIsEmpty() const
{
return m_fontTexture.IsEmpty();
}
bool CGraphicText::OnIsType(TType type)
{
if (CGraphicText::Type() == type)
return true;
return CResource::OnIsType(type);
}
File diff suppressed because it is too large Load Diff
+64
View File
@@ -0,0 +1,64 @@
// Platform skeleton for EterLib/GrpTexture.h (40250 EterLib/GrpTexture.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpTexture.h"
#include "../PlatformStub.h"
#include "UIRenderCommands.h"
auto CGraphicTexture::IsEmpty() const -> bool
{
return m_bEmpty;
}
auto CGraphicTexture::GetWidth() const -> int
{
return m_width;
}
auto CGraphicTexture::GetHeight() const -> int
{
return m_height;
}
auto CGraphicTexture::SetTextureStage(int) const -> void
{
MT_PLATFORM_STUB();
}
auto CGraphicTexture::GetD3DTexture() const -> LPDIRECT3DTEXTURE8
{
return m_lpd3dTexture;
}
// PORT: safe_release(m_lpd3dTexture); the platform textures are memory textures and file-texture handles.
auto CGraphicTexture::DestroyDeviceObjects() -> void
{
if (m_lpd3dTexture)
UIRenderReleaseMemoryTexture(m_lpd3dTexture);
m_lpd3dTexture = NULL;
}
CGraphicTexture::CGraphicTexture()
{
Initialize();
}
CGraphicTexture::~CGraphicTexture()
{
}
auto CGraphicTexture::Destroy() -> void
{
DestroyDeviceObjects();
Initialize();
}
auto CGraphicTexture::Initialize() -> void
{
m_lpd3dTexture = NULL;
m_width = 0;
m_height = 0;
m_bEmpty = true;
}
+162
View File
@@ -0,0 +1,162 @@
// 40250 EterLib/GrpVertexBuffer.cpp over CPU memory (CpuBuffer.h): the device buffer is a byte vector
// that Lock hands out directly, so Granny vertex loading and deform write real data.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpVertexBuffer.h"
#include "EterLib/StateManager.h"
#include "CpuBuffer.h"
int CGraphicVertexBuffer::GetVertexStride() const
{
int retSize = mt_fvf_vertex_size(m_dwFVF);
return retSize;
}
DWORD CGraphicVertexBuffer::GetFlexibleVertexFormat() const
{
return m_dwFVF;
}
int CGraphicVertexBuffer::GetVertexCount() const
{
return m_vtxCount;
}
void CGraphicVertexBuffer::SetStream(int stride, int layer) const
{
STATEMANAGER.SetStreamSource(layer, m_lpd3dVB, stride);
}
bool CGraphicVertexBuffer::LockRange(unsigned count, void** pretVertices) const
{
if (!m_lpd3dVB)
return false;
*pretVertices = static_cast<MtCpuVertexBuffer*>(m_lpd3dVB)->bytes.data();
return true;
}
bool CGraphicVertexBuffer::Lock(void ** pretVertices) const
{
if (!m_lpd3dVB)
return false;
*pretVertices = static_cast<MtCpuVertexBuffer*>(m_lpd3dVB)->bytes.data();
return true;
}
bool CGraphicVertexBuffer::Unlock() const
{
if (!m_lpd3dVB)
return false;
static_cast<MtCpuVertexBuffer*>(m_lpd3dVB)->revision++;
return true;
}
// Returns true when a buffer exists, as 40250 does.
bool CGraphicVertexBuffer::IsEmpty() const
{
if (m_lpd3dVB)
return true;
else
return false;
}
bool CGraphicVertexBuffer::LockDynamic(void** pretVertices)
{
if (!m_lpd3dVB)
return false;
*pretVertices = static_cast<MtCpuVertexBuffer*>(m_lpd3dVB)->bytes.data();
return true;
}
bool CGraphicVertexBuffer::Lock(void ** pretVertices)
{
if (!m_lpd3dVB)
return false;
*pretVertices = static_cast<MtCpuVertexBuffer*>(m_lpd3dVB)->bytes.data();
return true;
}
bool CGraphicVertexBuffer::Unlock()
{
if (!m_lpd3dVB)
return false;
static_cast<MtCpuVertexBuffer*>(m_lpd3dVB)->revision++;
return true;
}
bool CGraphicVertexBuffer::Copy(int bufSize, const void* srcVertices)
{
void * dstVertices;
if (!Lock(&dstVertices))
return false;
memcpy(dstVertices, srcVertices, bufSize);
Unlock();
return true;
}
bool CGraphicVertexBuffer::CreateDeviceObjects()
{
assert(m_lpd3dVB == NULL);
MtCpuVertexBuffer* buffer = new MtCpuVertexBuffer;
buffer->bytes.assign(m_dwBufferSize, 0);
buffer->fvf = m_dwFVF;
m_lpd3dVB = buffer;
return true;
}
void CGraphicVertexBuffer::DestroyDeviceObjects()
{
delete static_cast<MtCpuVertexBuffer*>(m_lpd3dVB);
m_lpd3dVB = NULL;
}
bool CGraphicVertexBuffer::Create(int vtxCount, DWORD fvf, DWORD usage, D3DPOOL d3dPool)
{
assert(vtxCount > 0);
Destroy();
m_vtxCount = vtxCount;
m_dwBufferSize = mt_fvf_vertex_size(fvf) * m_vtxCount;
m_d3dPool = d3dPool;
m_dwUsage = usage;
m_dwFVF = fvf;
if (usage == D3DUSAGE_WRITEONLY || usage == D3DUSAGE_DYNAMIC)
m_dwLockFlag = 0;
else
m_dwLockFlag = D3DLOCK_READONLY;
return CreateDeviceObjects();
}
void CGraphicVertexBuffer::Destroy()
{
DestroyDeviceObjects();
}
void CGraphicVertexBuffer::Initialize()
{
m_lpd3dVB = NULL;
m_vtxCount = 0;
m_dwBufferSize = 0;
m_dwFVF = 0;
}
CGraphicVertexBuffer::CGraphicVertexBuffer()
{
Initialize();
}
CGraphicVertexBuffer::~CGraphicVertexBuffer()
{
Destroy();
}
@@ -0,0 +1,22 @@
// Platform skeleton for EterLib/GrpVertexBufferDynamic.h (40250 EterLib/GrpVertexBufferDynamic.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/GrpVertexBufferDynamic.h"
#include "../PlatformStub.h"
CDynamicVertexBuffer::CDynamicVertexBuffer()
{
MT_PLATFORM_STUB();
}
CDynamicVertexBuffer::~CDynamicVertexBuffer()
{
MT_PLATFORM_STUB();
}
auto CDynamicVertexBuffer::Create(int, int) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
// The cursor in client coordinates, as the host (Godot) last pushed it. 40250 CMSWindow::GetMousePosition
// asks Win32 (GetCursorPos + ScreenToClient); here the host is the only source of mouse input.
void MtHostSetCursor(int x, int y);
+752
View File
@@ -0,0 +1,752 @@
// Platform implementation of EterLib/IME.h (40250 EterLib/IME.cpp).
// The edit buffer (m_wText, cursor, SetText/GetText, OnChar/InsertString, IsMax, the colour-tag aware cursor
// moves) and WMChar are the 40250 bodies verbatim. What 40250 gets from Win32 IMM/TSF — composition strings,
// the candidate list, the reading window, keyboard-layout code pages — has no counterpart under Godot: the
// host delivers committed characters only (Metin2PythonHost.ui_char -> WMChar, or InsertString for text the
// input code page cannot hold, which is what 40250's ResultProcess does with a GCS_RESULTSTR). Those entry
// points keep 40250's "no IME present" behaviour: no composition, empty candidate/reading lists.
#include "EterLib/StdAfx.h"
#include "EterLib/IME.h"
#include "EterLib/TextTag.h"
#include "EterLib/GrpTextInstance.h"
#include "EterLib/Util.h"
#include <algorithm>
#include <cwctype>
namespace
{
// 40250 s_aszIndicator[INDICATOR_NON_IME] (IME.cpp:67); CheckInputLocale overwrites it with the locale's
// two-letter abbreviation, which here is the locale code page's language.
wchar_t s_aszNonImeIndicator[3] = L"En";
}
/*---------------------------------------------------------------------------*/ /* Public */
CIME::CIME()
{
ms_hWnd = NULL;
ms_bCandidateList = false;
ms_bReadingInformation = false;
Clear();
m_max = 0;
m_userMax = 0;
m_bOnlyNumberMode = FALSE;
m_hOrgIMC = NULL;
m_bEnablePaste = false;
m_bUseDefaultIME = false;
}
CIME::~CIME()
{
}
// PORT: 40250 loads imm32.dll, disables Cicero, reads the keyboard layout and sets up the TSF sinks. The
// Godot host has no IMM context; only the part the edit buffer depends on — the input/output code page from
// CheckInputLocale and SetSupportLevel(2) — is kept.
bool CIME::Initialize(HWND hWnd)
{
if(ms_bInitialized)
return true;
ms_hWnd = hWnd;
ms_bDisableIMECompletely = true;
ms_bInitialized = true;
CheckInputLocale();
ChangeInputLanguageWorker();
SetSupportLevel(2);
ms_bUILessMode = false;
CheckToggleState();
return true;
}
void CIME::Uninitialize()
{
if ( !ms_bInitialized )
return;
ms_hWnd = NULL;
m_hOrgIMC = NULL;
ms_bInitialized = false;
}
void CIME::UseDefaultIME()
{
m_bUseDefaultIME = true;
}
bool CIME::IsIMEEnabled()
{
return ms_bImeEnabled;
}
// PORT: 40250 ImmAssociateContext()s the window; ms_bDisableIMECompletely (no imm32) forces bEnable=false,
// which is always the case here.
void CIME::EnableIME(bool bEnable)
{
if (!ms_bInitialized || !ms_hWnd)
return;
if (ms_bDisableIMECompletely)
bEnable = false;
ms_bImeEnabled = bEnable;
if (bEnable)
CheckToggleState();
}
void CIME::DisableIME()
{
EnableIME(false);
}
void CIME::EnableCaptureInput()
{
ms_bCaptureInput = true;
}
void CIME::DisableCaptureInput()
{
ms_bCaptureInput = false;
}
bool CIME::IsCaptureEnabled()
{
return ms_bCaptureInput;
}
void CIME::Clear()
{
ms_lastpos = 0;
ms_curpos = 0;
ms_compLen = 0;
ms_ulbegin = 0;
ms_ulend = 0;
}
int CIME::GetReading(std::string & rstrText)
{
char reading[IMEREADING_MAXLEN];
if(ms_wstrReading.size() == 0)
return 0;
int readingLen = WideCharToMultiByte(ms_uOutputCodePage, 0, &ms_wstrReading[0], ms_wstrReading.size(), reading, sizeof(reading), NULL, NULL);
rstrText.append(GetCodePageText());
rstrText.append(reading, reading + readingLen);
return rstrText.size();
}
int CIME::GetReadingError()
{
return ms_iReadingError;
}
void CIME::SetMax(int iMax)
{
m_max = iMax;
}
void CIME::SetUserMax(int iMax)
{
m_userMax = iMax;
}
void CIME::SetText(const char* szText, int len)
{
ms_compLen = 0;
ms_ulbegin = 0;
ms_ulend = 0;
const char* begin = szText;
const char* end = begin + len;
const char* iter = FindToken(begin, end);
int m_wTextLen = sizeof(m_wText)/sizeof(wchar_t);
ms_lastpos = MultiByteToWideChar(ms_uInputCodePage, 0, begin, iter-begin, m_wText, m_wTextLen);
if (iter < end)
ms_lastpos += MultiByteToWideChar(ReadToken(iter), 0, (iter+5), end-(iter+5), m_wText+ms_lastpos, m_wTextLen-ms_lastpos);
ms_curpos = std::min(ms_curpos, ms_lastpos);
}
int CIME::GetText(std::string & rstrText, bool addCodePage)
{
int outCodePage = ms_uOutputCodePage;
int dataCodePage;
switch (outCodePage)
{
//case 1256: // ARABIC
case 1268: // VIETNAM
dataCodePage = CP_UTF8;
break;
default:
dataCodePage = outCodePage;
}
int len = 0;
char text[IMESTR_MAXLEN];
len += WideCharToMultiByte(dataCodePage, 0, m_wText, ms_curpos, text, sizeof(text)-len, NULL, NULL);
len += WideCharToMultiByte(dataCodePage, 0, m_wszComposition, ms_compLen, text+len, sizeof(text)-len, NULL, NULL);
len += WideCharToMultiByte(dataCodePage, 0, m_wText+ms_curpos, ms_lastpos-ms_curpos, text+len, sizeof(text)-len, NULL, NULL);
int i;
for(i=0; i<len; ++i)
if((BYTE)text[i] > 0x7F) break;
if(i == len)
{
rstrText.append(text, text+len);
}
else
{
rstrText.append(text, text+i);
//if (addCodePage)
// rstrText.append(GetCodePageText());
rstrText.append(text+i, text+len);
}
return rstrText.size();
}
const char* CIME::GetCodePageText()
{
static char szCodePage[16];
const int defCodePage = GetDefaultCodePage();
const int outCodePage = ms_uOutputCodePage;
if (outCodePage != defCodePage)
{
sprintf(szCodePage, "@%04d", outCodePage);
}
else
{
szCodePage[0] = 0;
}
return szCodePage;
}
int CIME::GetCodePage()
{
return ms_uOutputCodePage;
}
int CIME::GetCandidatePageCount()
{
return ms_dwCandidatePageSize;
}
int CIME::GetCandidateCount()
{
return ms_dwCandidateCount;
}
int CIME::GetCandidate(DWORD index, std::string & rstrText)
{
if(index >= MAX_CANDLIST)
return 0;
LPCWSTR wszText = ms_wszCandidate[index];
if(wszText == NULL)
return 0;
int wTextLen = wcslen(wszText);
if(wTextLen == 0)
return 0;
char text[IMESTR_MAXLEN];
int len = ::WideCharToMultiByte(CP_UTF8, 0, wszText, wTextLen, text, sizeof(text), 0, 0);
rstrText.append("@9999");
rstrText.append(text, text+len);
return wTextLen;
}
int CIME::GetCandidateSelection()
{
return ms_dwCandidateSelection;
}
// PORT: 40250 ImmSetConversionStatus / ImmGetConversionStatus. Without an IMM context the conversion mode is
// the alphanumeric one (IME_CMODE_ALPHANUMERIC == 0) and cannot be changed.
void CIME::SetInputMode(DWORD)
{
}
DWORD CIME::GetInputMode()
{
return 0;
}
void CIME::SetNumberMode()
{
m_bOnlyNumberMode = TRUE;
}
void CIME::SetStringMode()
{
m_bOnlyNumberMode = FALSE;
}
void CIME::AddExceptKey(wchar_t key)
{
m_exceptKey.push_back(key);
}
void CIME::ClearExceptKey()
{
m_exceptKey.clear();
}
bool CIME::__IsWritable(wchar_t key)
{
if ( m_exceptKey.end() == std::find(m_exceptKey.begin(),m_exceptKey.end(),key) )
return true;
else
return false;
}
void CIME::EnablePaste(bool bFlag)
{
m_bEnablePaste = bFlag;
}
// PORT: 40250 reads CF_TEXT from the Win32 clipboard. The host clipboard is not wired to the extension yet,
// so this pastes nothing (the same as an empty clipboard).
void CIME::PasteTextFromClipBoard()
{
if (!m_bEnablePaste)
return;
}
// PORT: 40250 cancels the IMM composition string and closes the candidate list. There is no composition
// here; the candidate-list close (and its event) is kept.
void CIME::FinalizeString(bool)
{
static bool s_bProcessing = false; // to avoid infinite recursion
if ( !ms_bInitialized || s_bProcessing )
return;
s_bProcessing = true;
CloseCandidateList();
s_bProcessing = false;
}
int CIME::GetCompLen()
{
return ms_compLen;
}
int CIME::GetULBegin()
{
return ms_ulbegin;
}
int CIME::GetULEnd()
{
return ms_ulend;
}
void CIME::CloseCandidateList()
{
ms_bCandidateList = false;
ms_dwCandidateCount = 0;
memset(&ms_wszCandidate, 0, sizeof(ms_wszCandidate));
if(ms_pEvent)
ms_pEvent->OnCloseCandidateList();
}
void CIME::CloseReadingInformation()
{
CIME::ms_bReadingInformation = false;
if(CIME::ms_pEvent)
CIME::ms_pEvent->OnCloseReadingWnd();
}
// PORT: 40250 re-reads the keyboard layout (GETLANG) and re-applies the IME support level when the language
// changed. The host has one fixed input locale, so only the toggle check and the code-page event remain.
void CIME::ChangeInputLanguage()
{
CheckToggleState();
ChangeInputLanguageWorker();
if(ms_pEvent)
ms_pEvent->OnChangeCodePage();
}
void CIME::ChangeInputLanguageWorker()
{
if ( !ms_bUILessMode )
ms_iCandListIndexBase = 1;
SetupImeApi();
}
// PORT: 40250 forces level 3 for the Korean keyboard layout; there is no keyboard layout here.
void CIME::SetSupportLevel( DWORD dwImeLevel )
{
if ( dwImeLevel < 2 || 3 < dwImeLevel )
return;
ms_dwIMELevel = dwImeLevel;
// cancel current composition string.
FinalizeString();
}
LRESULT CIME::WMInputLanguage(HWND, UINT, WPARAM, LPARAM)
{
ChangeInputLanguage();
return 0;
}
LRESULT CIME::WMStartComposition(HWND, UINT, WPARAM, LPARAM)
{
return 1L;
}
// PORT: 40250 pulls GCS_RESULTSTR/GCS_COMPSTR out of the IMM context. The host never sends compositions.
LRESULT CIME::WMComposition(HWND, UINT, WPARAM, LPARAM)
{
return 0;
}
LRESULT CIME::WMEndComposition(HWND, UINT, WPARAM, LPARAM)
{
ms_compLen = 0;
ms_ulbegin = 0;
ms_ulend = 0;
if(ms_pEvent)
ms_pEvent->OnUpdate();
return 0L;
}
// PORT: 40250 handles IMN_* candidate/reading/toggle notifications from IMM; none are sent here.
LRESULT CIME::WMNotify(HWND, UINT, WPARAM, LPARAM)
{
return 0;
}
LRESULT CIME::WMChar(HWND /*hWnd*/, UINT /*uiMsg*/, WPARAM wParam, LPARAM lParam)
{
unsigned char c = (unsigned char)(wParam & 0xff);
switch (c)
{
case 8:
if(ms_bCaptureInput == false)
return 0;
if (ms_curpos > 0)
{
DecCurPos();
DelCurPos();
}
if(ms_pEvent)
ms_pEvent->OnUpdate();
return 0;
break;
default:
if(ms_pEvent) {
if (ms_pEvent->OnWM_CHAR(wParam, lParam))
break;
}
if(ms_bCaptureInput == false)
return 0;
wchar_t w[10];
MultiByteToWideChar(ms_uInputCodePage, 0, (char*)&c, 1, w, 1);
OnChar(w[0]);
if (w[0] == L'|')
OnChar(w[0]);
if(ms_pEvent)
ms_pEvent->OnUpdate();
break;
}
return 0;
}
/*---------------------------------------------------------------------------*/ /* Protected */
void CIME::IncCurPos()
{
if (ms_curpos < ms_lastpos)
{
int pos = FindColorTagEndPosition(m_wText + ms_curpos, ms_lastpos - ms_curpos);
if (pos > 0)
ms_curpos = std::min(ms_lastpos, std::max(0, ms_curpos + (pos + 1)));
else
++ms_curpos;
//++ms_curpos;
}
}
void CIME::DecCurPos()
{
if (ms_curpos > 0)
{
int pos = FindColorTagStartPosition(m_wText + ms_curpos - 1, ms_curpos);
if (pos > 0)
ms_curpos = std::min(ms_lastpos, std::max(0, ms_curpos - (pos + 1)));
else
--ms_curpos;
//--ms_curpos;
}
}
int CIME::GetCurPos()
{
int pos = GetTextTagOutputLen(m_wText, ms_curpos);
return pos;
//return ms_curpos;
}
void CIME::SetCurPos(int offset)
{
if (offset < 0 || offset > ms_lastpos)
{
ms_curpos = ms_lastpos;
return;
}
else
{
// offset is a position in the rendered text, so it has to be mapped back to the buffer.
//ms_curpos = min(ms_lastpos, offset);
ms_curpos = std::min(ms_lastpos, GetTextTagInternalPosFromRenderPos(m_wText, ms_lastpos, offset));
}
}
void CIME::DelCurPos()
{
if (ms_curpos < ms_lastpos)
{
int eraseCount = FindColorTagEndPosition(m_wText + ms_curpos, ms_lastpos - ms_curpos) + 1;
// PORT: 40250 wcscpy()s the overlapping tail down; that is undefined for overlapping buffers, and the
// buffer is not guaranteed NUL-terminated at ms_lastpos, so move exactly the live tail.
memmove(m_wText + ms_curpos, m_wText + ms_curpos + eraseCount, sizeof(wchar_t) * (ms_lastpos - ms_curpos - eraseCount));
ms_lastpos -= eraseCount;
ms_curpos = std::min(ms_lastpos, ms_curpos);
}
}
void CIME::PasteString(const char * str)
{
const char * begin = str;
const char * end = str + strlen(str);
wchar_t m_wText[IMESTR_MAXLEN];
int wstrLen = MultiByteToWideChar(ms_uInputCodePage, 0, begin, end - begin, m_wText, IMESTR_MAXLEN);
InsertString(m_wText, wstrLen);
if(ms_pEvent)
ms_pEvent->OnUpdate();
}
// PORT: 40250 reads the keyboard layout's default ANSI code page (GetLocaleInfoA LOCALE_IDEFAULTANSICODEPAGE).
// The host's input locale is the client locale, so its code page (SetDefaultCodePage from locale.cfg) is used.
void CIME::CheckInputLocale()
{
static UINT s_uPrevCodePage = 0xFFFF;
ms_uInputCodePage = GetDefaultCodePage();
if ( s_uPrevCodePage == ms_uInputCodePage )
return;
s_uPrevCodePage = ms_uInputCodePage;
ms_bVerticalCandidate = false;
ms_wszCurrentIndicator = s_aszNonImeIndicator;
if(ms_uOutputCodePage != 1256) {
ms_uOutputCodePage = ms_uInputCodePage;
Clear();
}
}
// PORT: 40250 asks IMM whether an IME is open; there is none, so the state is IMEUI_STATE_OFF (0).
void CIME::CheckToggleState()
{
CheckInputLocale();
ms_bChineseIME = false;
ms_dwImeState = 0;
}
/*---------------------------------------------------------------------------*/ /* Private */
void CIME::InsertString(wchar_t* wString, int iSize)
{
if (IsMax(wString, iSize))
return;
if (ms_curpos < ms_lastpos)
memmove(m_wText+ms_curpos+iSize, m_wText+ms_curpos, sizeof(wchar_t)*(ms_lastpos-ms_curpos));
memcpy(m_wText+ms_curpos, wString, sizeof(wchar_t)*iSize);
ms_curpos += iSize;
ms_lastpos += iSize;
}
void CIME::OnChar(wchar_t c)
{
if (m_bOnlyNumberMode)
if (!iswdigit(c))
return;
if (!__IsWritable(c))
return;
InsertString(&c, 1);
}
// PORT: 40250 maps a keyboard-layout LANGID to its ANSI code page. Only CheckInputLocale's code page is used
// here (see there), so this answers with it.
UINT CIME::GetCodePageFromLang(LANGID)
{
return GetDefaultCodePage();
}
// PORT: the IMM composition/candidate/reading processors (40250 IME.cpp:951-1227). No IMM context exists.
void CIME::ResultProcess(HIMC) {}
void CIME::CompositionProcessBuilding(HIMC) {}
void CIME::CompositionProcess(HIMC) {}
void CIME::AttributeProcess(HIMC) {}
void CIME::CandidateProcess(HIMC) {}
void CIME::ReadingProcess(HIMC) {}
bool CIME::IsMax(const wchar_t* wInput, int len)
{
if (ms_lastpos + len > IMESTR_MAXLEN)
return true;
int textLen = WideCharToMultiByte(ms_uOutputCodePage, 0, m_wText, ms_lastpos, 0, 0, NULL, NULL);
int inputLen = WideCharToMultiByte(ms_uOutputCodePage, 0, wInput, len, 0, 0, NULL, NULL);
//return textLen + inputLen > m_max;
if (textLen + inputLen > m_max)
return true;
else if (m_userMax != 0 && m_max != m_userMax)
{
std::wstring str = GetTextTagOutputString(m_wText, ms_lastpos);
std::wstring input = GetTextTagOutputString(wInput, len);
int textLen = WideCharToMultiByte(ms_uOutputCodePage, 0, str.c_str(), str.length(), 0, 0, NULL, NULL);
int inputLen = WideCharToMultiByte(ms_uOutputCodePage, 0, input.c_str(), input.length(), 0, 0, NULL, NULL);
return textLen + inputLen > m_userMax;
}
return false;
}
// PORT: 40250 identifies the CHT/CHS IME DLL version and the reading-window orientation. No IME DLL here.
DWORD CIME::GetImeId(UINT)
{
return 0;
}
bool CIME::GetReadingWindowOrientation()
{
return true;
}
void CIME::SetupImeApi()
{
_GetReadingString = NULL;
_ShowReadingWindow = NULL;
}
decltype(CIME::_ImmLockIMC) CIME::_ImmLockIMC{};
decltype(CIME::_ImmUnlockIMC) CIME::_ImmUnlockIMC{};
decltype(CIME::_ImmLockIMCC) CIME::_ImmLockIMCC{};
decltype(CIME::_ImmUnlockIMCC) CIME::_ImmUnlockIMCC{};
decltype(CIME::_GetReadingString) CIME::_GetReadingString{};
decltype(CIME::_ShowReadingWindow) CIME::_ShowReadingWindow{};
decltype(CIME::ms_bInitialized) CIME::ms_bInitialized{};
decltype(CIME::ms_bDisableIMECompletely) CIME::ms_bDisableIMECompletely{};
decltype(CIME::ms_bUILessMode) CIME::ms_bUILessMode{};
decltype(CIME::ms_bImeEnabled) CIME::ms_bImeEnabled{};
decltype(CIME::ms_bCaptureInput) CIME::ms_bCaptureInput{};
decltype(CIME::ms_bChineseIME) CIME::ms_bChineseIME{};
decltype(CIME::ms_bUseIMMCandidate) CIME::ms_bUseIMMCandidate{};
decltype(CIME::ms_hWnd) CIME::ms_hWnd{};
decltype(CIME::ms_hklCurrent) CIME::ms_hklCurrent{};
decltype(CIME::ms_szKeyboardLayout) CIME::ms_szKeyboardLayout{};
decltype(CIME::ms_stOSVI) CIME::ms_stOSVI{};
decltype(CIME::ms_hImm32Dll) CIME::ms_hImm32Dll{};
decltype(CIME::ms_hCurrentImeDll) CIME::ms_hCurrentImeDll{};
decltype(CIME::ms_dwImeState) CIME::ms_dwImeState{};
decltype(CIME::ms_adwId) CIME::ms_adwId{};
decltype(CIME::ms_dwIMELevel) CIME::ms_dwIMELevel{};
decltype(CIME::ms_dwIMELevelSaved) CIME::ms_dwIMELevelSaved{};
decltype(CIME::ms_bCandidateList) CIME::ms_bCandidateList{};
decltype(CIME::ms_dwCandidateCount) CIME::ms_dwCandidateCount{};
decltype(CIME::ms_bVerticalCandidate) CIME::ms_bVerticalCandidate{};
decltype(CIME::ms_iCandListIndexBase) CIME::ms_iCandListIndexBase{};
decltype(CIME::ms_wszCandidate) CIME::ms_wszCandidate{};
decltype(CIME::ms_dwCandidateSelection) CIME::ms_dwCandidateSelection{};
decltype(CIME::ms_dwCandidatePageSize) CIME::ms_dwCandidatePageSize{};
decltype(CIME::ms_bReadingInformation) CIME::ms_bReadingInformation{};
decltype(CIME::ms_iReadingError) CIME::ms_iReadingError{};
decltype(CIME::ms_bHorizontalReading) CIME::ms_bHorizontalReading{};
decltype(CIME::ms_wstrReading) CIME::ms_wstrReading{};
decltype(CIME::ms_wszCurrentIndicator) CIME::ms_wszCurrentIndicator{};
decltype(CIME::ms_pEvent) CIME::ms_pEvent{};
decltype(CIME::m_wText) CIME::m_wText{};
decltype(CIME::ms_compLen) CIME::ms_compLen{};
decltype(CIME::ms_curpos) CIME::ms_curpos{};
decltype(CIME::ms_lastpos) CIME::ms_lastpos{};
decltype(CIME::ms_ulbegin) CIME::ms_ulbegin{};
decltype(CIME::ms_ulend) CIME::ms_ulend{};
decltype(CIME::ms_uOutputCodePage) CIME::ms_uOutputCodePage{};
decltype(CIME::ms_uInputCodePage) CIME::ms_uInputCodePage{};
+81
View File
@@ -0,0 +1,81 @@
// Platform skeleton for EterLib/Input.h (40250 EterLib/Input.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/Input.h"
#include "../PlatformStub.h"
CInputDevice::CInputDevice()
{
MT_PLATFORM_STUB();
}
CInputDevice::~CInputDevice()
{
MT_PLATFORM_STUB();
}
auto CInputDevice::CreateDevice(HWND) -> HRESULT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<HRESULT>();
}
decltype(CInputDevice::ms_lpDI) CInputDevice::ms_lpDI{};
CInputKeyboard::CInputKeyboard()
{
MT_PLATFORM_STUB();
}
CInputKeyboard::~CInputKeyboard()
{
MT_PLATFORM_STUB();
}
auto CInputKeyboard::InitializeKeyboard(HWND) -> bool
{
ResetKeyboard();
return true;
}
auto CInputKeyboard::UpdateKeyboard() -> void
{
}
auto CInputKeyboard::ResetKeyboard() -> void
{
memset(ms_bPressedKey, 0, sizeof(ms_bPressedKey));
memset(ms_diks, 0, sizeof(ms_diks));
}
auto CInputKeyboard::IsPressed(int iIndex) -> bool
{
if (iIndex >= 0 && iIndex < 256)
return (ms_diks[iIndex] & 0x80) != 0;
return false;
}
auto CInputKeyboard::KeyDown(int iIndex) -> void
{
if (iIndex >= 0 && iIndex < 256)
{
ms_bPressedKey[iIndex] = true;
ms_diks[iIndex] = (char)0x80;
}
}
auto CInputKeyboard::KeyUp(int iIndex) -> void
{
if (iIndex >= 0 && iIndex < 256)
{
ms_bPressedKey[iIndex] = false;
ms_diks[iIndex] = 0;
}
}
decltype(CInputKeyboard::ms_lpKeyboard) CInputKeyboard::ms_lpKeyboard{};
decltype(CInputKeyboard::ms_bPressedKey) CInputKeyboard::ms_bPressedKey{};
decltype(CInputKeyboard::ms_diks) CInputKeyboard::ms_diks{};
+49
View File
@@ -0,0 +1,49 @@
// Platform skeleton for EterLib/MSApplication.h (40250 EterLib/MSApplication.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/MSApplication.h"
#include "../PlatformStub.h"
CMSApplication::CMSApplication()
{
MT_PLATFORM_STUB();
}
CMSApplication::~CMSApplication()
{
MT_PLATFORM_STUB();
}
auto CMSApplication::Initialize(HINSTANCE) -> void
{
MT_PLATFORM_STUB();
}
auto CMSApplication::MessageLoop() -> void
{
MT_PLATFORM_STUB();
}
auto CMSApplication::IsMessage() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CMSApplication::MessageProcess() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CMSApplication::ClearWindowClass() -> void
{
MT_PLATFORM_STUB();
}
auto CMSApplication::WindowProcedure(HWND, UINT, WPARAM, LPARAM) -> LRESULT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<LRESULT>();
}
+150
View File
@@ -0,0 +1,150 @@
// Platform skeleton for EterLib/MSWindow.h (40250 EterLib/MSWindow.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/MSWindow.h"
#include "../PlatformStub.h"
#include "HostCursor.h"
CMSWindow::CMSWindow()
{
MT_PLATFORM_STUB();
}
CMSWindow::~CMSWindow()
{
MT_PLATFORM_STUB();
}
auto CMSWindow::Destroy() -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::Create(const char *, int, DWORD, DWORD, HICON, int) -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CMSWindow::Show() -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::Hide() -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::SetVisibleMode(bool) -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::SetPosition(int, int) -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::SetCenterPosition() -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::SetText(const char *) -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::AdjustSize(int, int) -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::SetSize(int, int) -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::IsVisible() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
auto CMSWindow::IsActive() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
namespace {
POINT g_host_cursor = {0, 0};
}
void MtHostSetCursor(int x, int y)
{
g_host_cursor.x = x;
g_host_cursor.y = y;
}
auto CMSWindow::GetMousePosition(POINT * ppt) -> void
{
*ppt = g_host_cursor;
}
auto CMSWindow::GetClientRect(RECT *) -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::GetWindowRect(RECT *) -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::GetScreenWidth() -> int
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<int>();
}
auto CMSWindow::GetScreenHeight() -> int
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<int>();
}
auto CMSWindow::GetWindowHandle() -> HWND
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<HWND>();
}
auto CMSWindow::GetInstance() -> HINSTANCE
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<HINSTANCE>();
}
auto CMSWindow::WindowProcedure(HWND, UINT, WPARAM, LPARAM) -> LRESULT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<LRESULT>();
}
auto CMSWindow::OnSize(WPARAM, LPARAM) -> void
{
MT_PLATFORM_STUB();
}
auto CMSWindow::RegisterWindowClass(DWORD, int, WNDPROC, HICON, int) -> const char *
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<const char *>();
}
decltype(CMSWindow::ms_stWCSet) CMSWindow::ms_stWCSet{};
decltype(CMSWindow::ms_hInstance) CMSWindow::ms_hInstance{};
+32
View File
@@ -0,0 +1,32 @@
// Platform skeleton for EterLib/Mutex.h (40250 EterLib/Mutex.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/Mutex.h"
#include "../PlatformStub.h"
Mutex::Mutex()
{
MT_PLATFORM_STUB();
}
Mutex::~Mutex()
{
MT_PLATFORM_STUB();
}
auto Mutex::Lock() -> void
{
MT_PLATFORM_STUB();
}
auto Mutex::Unlock() -> void
{
MT_PLATFORM_STUB();
}
auto Mutex::Trylock() -> bool
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<bool>();
}
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
#pragma once
// The platform's IDirect3DDevice8: CGraphicDevice::Create hands it to CStateManager, which keeps
// 40250's state caching; the device remembers the state it is given and turns every draw call into a
// Render3DDraw (RenderCommands3D.h) for the Godot renderer.
#include "EterLib/StdAfx.h"
IDirect3DDevice8* MtCreateRecordingDevice(int width, int height);
+141
View File
@@ -0,0 +1,141 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
// The 3D draw calls the ported game render (CPythonApplication::RenderGame) issues through
// CStateManager, recorded by the platform's IDirect3DDevice8 (RecordingDevice.cpp) and consumed by
// Godot. Like UIRenderCommands.h this header stays free of D3D and godot-cpp types.
//
// Matrices are D3D8's row-vector layout (translation in elements 12..14), exactly as 40250 set them.
struct Render3DDraw {
// Stable source-buffer identity and content version. Zero key means an immediate-mode draw
// without a reusable D3D buffer. Geometry may be reused only while both values match.
std::uint64_t geometry_key = 0;
std::uint64_t geometry_revision = 0;
float world[16];
float view[16];
float proj[16];
float viewport[4] = {}; // x, y, width, height
float viewport_z[2] = {0, 1}; // MinZ, MaxZ
// PORT: UIRenderOffsetX() when recorded (a draw from a shifted window layer); the host moves the
// viewport (and a pretransformed draw's screen positions) right by it.
float ui_offset_x = 0;
// IDirect3DDevice8::Clear on the back buffer, kept in draw order. A clear entry has no geometry;
// clear_flags holds D3DCLEAR_TARGET / D3DCLEAR_ZBUFFER / D3DCLEAR_STENCIL.
std::uint32_t clear_flags = 0;
std::uint32_t clear_color = 0; // 0xAARRGGBB
float clear_z = 1;
// Non-zero: the draw (or clear) targets an offscreen render-target texture instead of the back
// buffer -- the 40250 character shadow map. The renderer draws these into the texture named
// Render3DRenderTargetName(render_target, ...) ahead of the back-buffer pass, in recorded order.
// viewport is then in the target's pixels. Only emitted while GPU render targets are enabled.
std::uint32_t render_target = 0;
std::uint32_t target_width = 0, target_height = 0;
// Stage 0/1 textures, named like UIRenderTextureName: the pack path of a file texture or
// "mem:<id>@<revision>"; empty when the stage has no texture.
std::string texture0;
std::string texture1;
// The referenced vertices, rebased so indices start at 0. normals/uv0/uv1/diffuse are empty when
// the vertex format has no such element. pretransformed: D3DFVF_XYZRHW (screen-space x, y, z, rhw
// in positions + rhw).
bool pretransformed = false;
std::vector<float> positions; // x, y, z
std::vector<float> rhw;
// D3D8 vertex fog of an XYZRHW draw: the D3DFVF_SPECULAR alpha (0..1); empty otherwise.
std::vector<float> vertex_fog;
std::vector<float> normals; // x, y, z
std::vector<float> uv0; // u, v
std::vector<float> uv1; // u, v
std::vector<std::uint32_t> diffuse; // 0xAARRGGBB
std::vector<std::uint32_t> indices; // triangle list (strips and fans are expanded), or line list
std::vector<std::uint8_t> bone_indices; // 4 uint8 per vertex (mesh-local bone palette index)
std::vector<float> bone_weights; // 4 floats per vertex
std::vector<float> bone_matrices; // 16 floats per bone in the mesh's palette (D3D row-vector layout)
bool lines = false;
// D3DRS_* / D3DTSS_* values in effect for the draw.
std::uint32_t alpha_blend = 0, src_blend = 0, dest_blend = 0;
std::uint32_t alpha_test = 0, alpha_ref = 0, alpha_func = 0;
std::uint32_t cull_mode = 0, z_enable = 0, z_write = 0, z_func = 0;
std::uint32_t lighting = 0, texture_factor = 0, fog_enable = 0;
std::uint32_t fog_color = 0, fog_vertex_mode = 0, fog_table_mode = 0, fog_range_enable = 0;
float fog_start = 0, fog_end = 0, fog_density = 0;
std::uint32_t color_op[2] = {}, color_arg1[2] = {}, color_arg2[2] = {};
std::uint32_t alpha_op[2] = {}, alpha_arg1[2] = {}, alpha_arg2[2] = {};
std::uint32_t address_u[2] = {}, address_v[2] = {};
std::uint32_t min_filter[2] = {}, mag_filter[2] = {}, mip_filter[2] = {};
std::uint32_t border_color[2] = {};
// D3DTSS_TEXCOORDINDEX (set index | D3DTSS_TCI_* generation mode), D3DTSS_TEXTURETRANSFORMFLAGS and
// D3DTS_TEXTURE0/1 per stage. The renderer generates and transforms texture coordinates from
// these the way the D3D8 fixed-function vertex pipeline does; uv0/uv1 stay the raw vertex sets.
std::uint32_t texcoord_index[2] = {0, 1};
std::uint32_t texture_transform_flags[2] = {};
float texture_matrix[2][16] = {{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}};
// D3DMATERIAL8 diffuse/ambient/emissive (r, g, b, a) and light 0 when enabled.
float material_diffuse[4] = {1, 1, 1, 1};
float material_ambient[4] = {};
float material_emissive[4] = {};
bool light0 = false;
float light0_direction[3] = {};
float light0_diffuse[4] = {};
float light0_ambient[4] = {};
std::uint32_t ambient = 0; // D3DRS_AMBIENT
struct Light {
std::uint32_t type = 0; // zero when disabled; D3DLIGHT_POINT/SPOT/DIRECTIONAL otherwise
float position[3] = {};
float direction[3] = {};
float diffuse[4] = {};
float ambient[4] = {};
float attenuation[3] = {};
float range = 0;
float theta = 0, phi = 0, falloff = 0;
} lights[8];
std::uint32_t diffuse_material_source = 0;
std::uint32_t ambient_material_source = 0;
std::uint32_t emissive_material_source = 0;
std::uint32_t color_vertex = 0;
std::uint32_t normalize_normals = 0; // D3DRS_NORMALIZENORMALS
std::uint32_t local_viewer = 1; // D3DRS_LOCALVIEWER
};
// The texture coordinates stage 0/1 samples at each vertex, computed on the CPU with the same
// D3D8 fixed-function rules the native renderer's vertex shader applies (TEXCOORDINDEX generation,
// then D3DTS_TEXTUREn under TEXTURETRANSFORMFLAGS). For consumers without that shader (Godot).
void Render3DStageTexcoords(const Render3DDraw& draw, int stage, std::vector<float>& out);
struct GpuSkinSubrangeView {
std::uint64_t source_mesh_key = 0;
std::uint32_t mesh_base_vertex = 0;
std::uint32_t mesh_vertex_count = 0;
const std::uint8_t* bone_indices = nullptr; // mesh_vertex_count * 4
const float* bone_weights = nullptr; // mesh_vertex_count * 4
const float* bone_matrices = nullptr; // bone_count * 16
std::uint32_t bone_count = 0;
};
void SetNativeTerrainRenderEnabled(bool enabled);
bool IsNativeTerrainRenderEnabled();
void SetGpuSkinningEnabled(bool enabled);
bool IsGpuSkinningEnabled();
bool LookupGpuSkinSubrange(const void* vertex_buffer_base, std::uint32_t stride,
std::uint32_t lo_vertex, std::uint32_t hi_vertex,
GpuSkinSubrangeView* out_view);
// GPU render targets: shadow-map draws are recorded with render_target set and sampled as
// "rt:<id>:<w>x<h>" instead of being rasterized on the CPU into a "mem:cpu_<id>" texture. Off by
// default (the Godot consumer has no offscreen pass); the native Vulkan renderer turns it on.
void SetGpuRenderTargetsEnabled(bool enabled);
bool IsGpuRenderTargetsEnabled();
std::string Render3DRenderTargetName(std::uint32_t id, std::uint32_t width, std::uint32_t height);
void Render3DBeginFrame();
void Render3DAdd(Render3DDraw draw);
const std::vector<Render3DDraw>& Render3DDraws();
+787
View File
@@ -0,0 +1,787 @@
// Platform implementation of EterLib/SkyBox.cpp (40250 EterLib/SkyBox.cpp).
#include "EterLib/StdAfx.h"
#include "EterLib/SkyBox.h"
#include "EterLib/Camera.h"
#include "EterLib/StateManager.h"
#include "EterLib/ResourceManager.h"
#include "EterBase/Timer.h"
#include "RenderCommands3D.h"
CSkyObjectQuad::CSkyObjectQuad()
{
m_Indices[0] = 0;
m_Indices[1] = 2;
m_Indices[2] = 1;
m_Indices[3] = 3;
for (unsigned char uci = 0; uci < 4; ++uci)
{
memset(&m_Vertex[uci], 0, sizeof(TPDTVertex));
}
}
CSkyObjectQuad::~CSkyObjectQuad()
{
}
void CSkyObjectQuad::Clear(const unsigned char & c_rucNumVertex,
const float & c_rfRed,
const float & c_rfGreen,
const float & c_rfBlue,
const float & c_rfAlpha)
{
if (c_rucNumVertex > 3)
return;
m_Helper[c_rucNumVertex].Clear(c_rfRed, c_rfGreen, c_rfBlue, c_rfAlpha);
}
void CSkyObjectQuad::SetSrcColor(const unsigned char & c_rucNumVertex,
const float & c_rfRed,
const float & c_rfGreen,
const float & c_rfBlue,
const float & c_rfAlpha)
{
if (c_rucNumVertex > 3)
return;
m_Helper[c_rucNumVertex].SetSrcColor(c_rfRed, c_rfGreen, c_rfBlue, c_rfAlpha);
}
void CSkyObjectQuad::SetTransition(const unsigned char & c_rucNumVertex,
const float & c_rfRed,
const float & c_rfGreen,
const float & c_rfBlue,
const float & c_rfAlpha,
DWORD dwDuration)
{
if (c_rucNumVertex > 3)
return;
m_Helper[c_rucNumVertex].SetTransition(c_rfRed, c_rfGreen, c_rfBlue, c_rfAlpha, dwDuration);
}
void CSkyObjectQuad::SetVertex(const unsigned char & c_rucNumVertex, const TPDTVertex & c_rPDTVertex)
{
if (c_rucNumVertex > 3)
return;
memcpy(&m_Vertex[m_Indices[c_rucNumVertex]], &c_rPDTVertex, sizeof(TPDTVertex));
}
void CSkyObjectQuad::StartTransition()
{
for (unsigned char uci = 0; uci < 4; ++uci)
{
m_Helper[uci].StartTransition();
}
}
bool CSkyObjectQuad::Update()
{
bool bResult = false;
for (unsigned char uci = 0; uci < 4; ++uci)
{
bResult = m_Helper[uci].Update() || bResult;
m_Vertex[m_Indices[uci]].diffuse = m_Helper[uci].GetCurColor();
}
return bResult;
}
void CSkyObjectQuad::Render()
{
if (CGraphicBase::SetPDTStream(m_Vertex, 4))
STATEMANAGER.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
CSkyObject::CSkyObject() :
m_v3Position(0.0f, 0.0f, 0.0f),
m_fScaleX(1.0f),
m_fScaleY(1.0f),
m_fScaleZ(1.0f)
{
D3DXMatrixIdentity(&m_matWorld);
D3DXMatrixIdentity(&m_matTranslation);
D3DXMatrixIdentity(&m_matWorldCloud);
D3DXMatrixIdentity(&m_matTranslationCloud);
D3DXMatrixIdentity(&m_matTextureCloud);
m_dwlastTime = CTimer::Instance().GetCurrentMillisecond();
m_fCloudPositionU = 0.0f;
m_fCloudPositionV = 0.0f;
m_fCloudScaleX = 1.0f;
m_fCloudScaleY = 1.0f;
m_fCloudHeight = 0.0f;
m_fCloudTextureScaleX = 1.0f;
m_fCloudTextureScaleY = 1.0f;
m_fCloudScrollSpeedU = 0.0f;
m_fCloudScrollSpeedV = 0.0f;
m_ucRenderMode = SKY_RENDER_MODE_DEFAULT;
m_bTransitionStarted = false;
m_bSkyMatrixUpdated = false;
}
CSkyObject::~CSkyObject()
{
}
void CSkyObject::Destroy()
{
}
void CSkyObject::Update()
{
CCamera* pCamera = CCameraManager::Instance().GetCurrentCamera();
if (!pCamera)
return;
D3DXVECTOR3 v3Eye = pCamera->GetEye();
if (m_v3Position == v3Eye)
if (m_bSkyMatrixUpdated == false)
return;
m_v3Position = v3Eye;
m_matWorld._41 = m_v3Position.x;
m_matWorld._42 = m_v3Position.y;
m_matWorld._43 = m_v3Position.z;
m_matWorldCloud._41 = m_v3Position.x;
m_matWorldCloud._42 = m_v3Position.y;
m_matWorldCloud._43 = m_v3Position.z + m_fCloudHeight;
if (m_bSkyMatrixUpdated)
m_bSkyMatrixUpdated = false;
}
void CSkyObject::Render()
{
}
void CSkyObject::StartTransition()
{
}
CGraphicImageInstance * CSkyObject::GenerateTexture(const char * szfilename)
{
if (!szfilename || !*szfilename)
return NULL;
CResource * pResource = CResourceManager::Instance().GetResourcePointer(szfilename);
if (!pResource || !pResource->IsType(CGraphicImage::Type()))
return NULL;
CGraphicImageInstance * pImageInstance = CGraphicImageInstance::New();
pImageInstance->SetImagePointer(static_cast<CGraphicImage *>(pResource));
return pImageInstance;
}
void CSkyObject::DeleteTexture(CGraphicImageInstance * pImageInstance)
{
if (pImageInstance)
CGraphicImageInstance::Delete(pImageInstance);
}
void CSkyObject::TSkyObjectFace::StartTransition()
{
for (unsigned char uci = 0; uci < m_SkyObjectQuadVector.size(); ++uci)
{
m_SkyObjectQuadVector[uci].StartTransition();
}
}
bool CSkyObject::TSkyObjectFace::Update()
{
bool bResult = false;
for (DWORD dwi = 0; dwi < m_SkyObjectQuadVector.size(); ++dwi)
bResult = m_SkyObjectQuadVector[dwi].Update() || bResult;
return bResult;
}
void CSkyObject::TSkyObjectFace::Render()
{
for (unsigned char uci = 0; uci < m_SkyObjectQuadVector.size(); ++uci)
{
m_SkyObjectQuadVector[uci].Render();
}
}
CSkyBox::CSkyBox()
{
m_ucVirticalGradientLevelUpper = 0;
m_ucVirticalGradientLevelLower = 0;
}
CSkyBox::~CSkyBox()
{
Destroy();
}
void CSkyBox::Destroy()
{
Unload();
}
void CSkyBox::Unload()
{
TGraphicImageInstanceMap::iterator itor = m_GraphicImageInstanceMap.begin();
while (itor != m_GraphicImageInstanceMap.end())
{
DeleteTexture(itor->second);
++itor;
}
m_GraphicImageInstanceMap.clear();
}
void CSkyBox::SetSkyBoxScale(const D3DXVECTOR3 & c_rv3Scale)
{
m_fScaleX = c_rv3Scale.x;
m_fScaleY = c_rv3Scale.y;
m_fScaleZ = c_rv3Scale.z;
m_bSkyMatrixUpdated = true;
D3DXMatrixScaling(&m_matWorld, m_fScaleX, m_fScaleY, m_fScaleZ);
}
void CSkyBox::SetGradientLevel(BYTE byUpper, BYTE byLower)
{
m_ucVirticalGradientLevelUpper = byUpper;
m_ucVirticalGradientLevelLower = byLower;
}
void CSkyBox::SetFaceTexture(const char* c_szFileName, int iFaceIndex)
{
if (iFaceIndex < 0 || iFaceIndex > 5 || !c_szFileName || !*c_szFileName)
return;
TGraphicImageInstanceMap::iterator itor = m_GraphicImageInstanceMap.find(c_szFileName);
if (m_GraphicImageInstanceMap.end() != itor)
return;
m_Faces[iFaceIndex].m_strFaceTextureFileName = c_szFileName;
CGraphicImageInstance * pGraphicImageInstance = GenerateTexture(c_szFileName);
m_GraphicImageInstanceMap.insert(TGraphicImageInstanceMap::value_type(c_szFileName, pGraphicImageInstance));
}
void CSkyBox::SetCloudTexture(const char * c_szFileName)
{
if (!c_szFileName || !*c_szFileName)
return;
TGraphicImageInstanceMap::iterator itor = m_GraphicImageInstanceMap.find(c_szFileName);
if (m_GraphicImageInstanceMap.end() != itor)
return;
m_FaceCloud.m_strfacename = c_szFileName;
CGraphicImageInstance * pGraphicImageInstance = GenerateTexture(c_szFileName);
m_GraphicImageInstanceMap.insert(TGraphicImageInstanceMap::value_type(m_FaceCloud.m_strfacename, pGraphicImageInstance));
}
void CSkyBox::SetCloudScale(const D3DXVECTOR2 & c_rv2CloudScale)
{
m_fCloudScaleX = c_rv2CloudScale.x;
m_fCloudScaleY = c_rv2CloudScale.y;
D3DXMatrixScaling(&m_matWorldCloud, m_fCloudScaleX, m_fCloudScaleY, 1.0f);
}
void CSkyBox::SetCloudHeight(float fHeight)
{
m_fCloudHeight = fHeight;
}
void CSkyBox::SetCloudTextureScale(const D3DXVECTOR2 & c_rv2CloudTextureScale)
{
m_fCloudTextureScaleX = c_rv2CloudTextureScale.x;
m_fCloudTextureScaleY = c_rv2CloudTextureScale.y;
m_matTextureCloud._11 = m_fCloudTextureScaleX;
m_matTextureCloud._22 = m_fCloudTextureScaleY;
}
void CSkyBox::SetCloudScrollSpeed(const D3DXVECTOR2 & c_rv2CloudScrollSpeed)
{
m_fCloudScrollSpeedU = c_rv2CloudScrollSpeed.x;
m_fCloudScrollSpeedV = c_rv2CloudScrollSpeed.y;
}
void CSkyBox::SetSkyObjectQuadVertical(TSkyObjectQuadVector * pSkyObjectQuadVector, const D3DXVECTOR2 * c_pv2QuadPoints)
{
TPDTVertex aPDTVertex;
DWORD dwIndex = 0;
pSkyObjectQuadVector->clear();
pSkyObjectQuadVector->resize(m_ucVirticalGradientLevelUpper + m_ucVirticalGradientLevelLower);
unsigned char ucY;
for (ucY = 0; ucY < m_ucVirticalGradientLevelUpper; ++ucY)
{
CSkyObjectQuad & rSkyObjectQuad = pSkyObjectQuadVector->at(dwIndex++);
aPDTVertex.position.x = c_pv2QuadPoints[0].x;
aPDTVertex.position.y = c_pv2QuadPoints[0].y;
aPDTVertex.position.z = 1.0f - (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper);
aPDTVertex.texCoord.x = 0.0f;
aPDTVertex.texCoord.y = (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
rSkyObjectQuad.SetVertex(0, aPDTVertex);
aPDTVertex.position.x = c_pv2QuadPoints[0].x;
aPDTVertex.position.y = c_pv2QuadPoints[0].y;
aPDTVertex.position.z = 1.0f - (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper);
aPDTVertex.texCoord.x = 0.0f;
aPDTVertex.texCoord.y = (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
rSkyObjectQuad.SetVertex(1, aPDTVertex);
aPDTVertex.position.x = c_pv2QuadPoints[1].x;
aPDTVertex.position.y = c_pv2QuadPoints[1].y;
aPDTVertex.position.z = 1.0f - (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper);
aPDTVertex.texCoord.x = 1.0f;
aPDTVertex.texCoord.y = (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
rSkyObjectQuad.SetVertex(2, aPDTVertex);
aPDTVertex.position.x = c_pv2QuadPoints[1].x;
aPDTVertex.position.y = c_pv2QuadPoints[1].y;
aPDTVertex.position.z = 1.0f - (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper);
aPDTVertex.texCoord.x = 1.0f;
aPDTVertex.texCoord.y = (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
rSkyObjectQuad.SetVertex(3, aPDTVertex);
}
for (ucY = 0; ucY < m_ucVirticalGradientLevelLower; ++ucY)
{
CSkyObjectQuad & rSkyObjectQuad = pSkyObjectQuadVector->at(dwIndex++);
aPDTVertex.position.x = c_pv2QuadPoints[0].x;
aPDTVertex.position.y = c_pv2QuadPoints[0].y;
aPDTVertex.position.z = -(float)(ucY + 1) / (float)(m_ucVirticalGradientLevelLower);
aPDTVertex.texCoord.x = 0.0f;
aPDTVertex.texCoord.y = 0.5f + (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
rSkyObjectQuad.SetVertex(0, aPDTVertex);
aPDTVertex.position.x = c_pv2QuadPoints[0].x;
aPDTVertex.position.y = c_pv2QuadPoints[0].y;
aPDTVertex.position.z = -(float)(ucY) / (float)(m_ucVirticalGradientLevelLower);
aPDTVertex.texCoord.x = 0.0f;
aPDTVertex.texCoord.y = 0.5f + (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
rSkyObjectQuad.SetVertex(1, aPDTVertex);
aPDTVertex.position.x = c_pv2QuadPoints[1].x;
aPDTVertex.position.y = c_pv2QuadPoints[1].y;
aPDTVertex.position.z = -(float)(ucY + 1) / (float)(m_ucVirticalGradientLevelLower);
aPDTVertex.texCoord.x = 1.0f;
aPDTVertex.texCoord.y = 0.5f + (float)(ucY + 1) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
rSkyObjectQuad.SetVertex(2, aPDTVertex);
aPDTVertex.position.x = c_pv2QuadPoints[1].x;
aPDTVertex.position.y = c_pv2QuadPoints[1].y;
aPDTVertex.position.z = -(float)(ucY) / (float)(m_ucVirticalGradientLevelLower);
aPDTVertex.texCoord.x = 1.0f;
aPDTVertex.texCoord.y = 0.5f + (float)(ucY) / (float)(m_ucVirticalGradientLevelUpper) * 0.5f;
rSkyObjectQuad.SetVertex(3, aPDTVertex);
}
}
void CSkyBox::SetSkyObjectQuadHorizon(TSkyObjectQuadVector * pSkyObjectQuadVector, const D3DXVECTOR3 * c_pv3QuadPoints)
{
pSkyObjectQuadVector->clear();
pSkyObjectQuadVector->resize(1);
CSkyObjectQuad & rSkyObjectQuad = pSkyObjectQuadVector->at(0);
TPDTVertex aPDTVertex{};
aPDTVertex.position = c_pv3QuadPoints[0];
aPDTVertex.texCoord.x = 0.0f;
aPDTVertex.texCoord.y = 1.0f;
rSkyObjectQuad.SetVertex(0, aPDTVertex);
aPDTVertex.position = c_pv3QuadPoints[1];
aPDTVertex.texCoord.x = 0.0f;
aPDTVertex.texCoord.y = 0.0f;
rSkyObjectQuad.SetVertex(1, aPDTVertex);
aPDTVertex.position = c_pv3QuadPoints[2];
aPDTVertex.texCoord.x = 1.0f;
aPDTVertex.texCoord.y = 1.0f;
rSkyObjectQuad.SetVertex(2, aPDTVertex);
aPDTVertex.position = c_pv3QuadPoints[3];
aPDTVertex.texCoord.x = 1.0f;
aPDTVertex.texCoord.y = 0.0f;
rSkyObjectQuad.SetVertex(3, aPDTVertex);
}
void CSkyBox::Refresh()
{
D3DXVECTOR3 v3QuadPoints[4];
if (m_ucRenderMode == CSkyObject::SKY_RENDER_MODE_DEFAULT || m_ucRenderMode == CSkyObject::SKY_RENDER_MODE_DIFFUSE)
{
if (m_ucVirticalGradientLevelUpper + m_ucVirticalGradientLevelLower <= 0)
return;
D3DXVECTOR2 v2QuadPoints[2];
v2QuadPoints[0] = D3DXVECTOR2(1.0f, -1.0f);
v2QuadPoints[1] = D3DXVECTOR2(-1.0f, -1.0f);
SetSkyObjectQuadVertical(&m_Faces[0].m_SkyObjectQuadVector, v2QuadPoints);
m_Faces[0].m_strfacename = "front";
v2QuadPoints[0] = D3DXVECTOR2(-1.0f, 1.0f);
v2QuadPoints[1] = D3DXVECTOR2(1.0f, 1.0f);
SetSkyObjectQuadVertical(&m_Faces[1].m_SkyObjectQuadVector, v2QuadPoints);
m_Faces[1].m_strfacename = "back";
v2QuadPoints[0] = D3DXVECTOR2(-1.0f, -1.0f);
v2QuadPoints[1] = D3DXVECTOR2(-1.0f, 1.0f);
SetSkyObjectQuadVertical(&m_Faces[2].m_SkyObjectQuadVector, v2QuadPoints);
m_Faces[2].m_strfacename = "left";
v2QuadPoints[0] = D3DXVECTOR2(1.0f, 1.0f);
v2QuadPoints[1] = D3DXVECTOR2(1.0f, -1.0f);
SetSkyObjectQuadVertical(&m_Faces[3].m_SkyObjectQuadVector, v2QuadPoints);
m_Faces[3].m_strfacename = "right";
v3QuadPoints[0] = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
v3QuadPoints[1] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
v3QuadPoints[2] = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
SetSkyObjectQuadHorizon(&m_Faces[4].m_SkyObjectQuadVector, v3QuadPoints);
m_Faces[4].m_strfacename = "top";
v3QuadPoints[0] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
v3QuadPoints[3] = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
SetSkyObjectQuadHorizon(&m_Faces[5].m_SkyObjectQuadVector, v3QuadPoints);
m_Faces[5].m_strfacename = "bottom";
}
else if (m_ucRenderMode == CSkyObject::SKY_RENDER_MODE_TEXTURE)
{
v3QuadPoints[0] = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
v3QuadPoints[1] = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
SetSkyObjectQuadHorizon(&m_Faces[0].m_SkyObjectQuadVector, v3QuadPoints);
m_Faces[0].m_strfacename = "front";
v3QuadPoints[0] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
v3QuadPoints[1] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
v3QuadPoints[2] = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
v3QuadPoints[3] = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
SetSkyObjectQuadHorizon(&m_Faces[1].m_SkyObjectQuadVector, v3QuadPoints);
m_Faces[1].m_strfacename = "back";
v3QuadPoints[0] = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
v3QuadPoints[2] = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
v3QuadPoints[3] = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
SetSkyObjectQuadHorizon(&m_Faces[2].m_SkyObjectQuadVector, v3QuadPoints);
m_Faces[2].m_strfacename = "left";
v3QuadPoints[0] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
v3QuadPoints[1] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
SetSkyObjectQuadHorizon(&m_Faces[3].m_SkyObjectQuadVector, v3QuadPoints);
m_Faces[3].m_strfacename = "right";
v3QuadPoints[0] = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
SetSkyObjectQuadHorizon(&m_Faces[4].m_SkyObjectQuadVector, v3QuadPoints);
m_Faces[4].m_strfacename = "top";
v3QuadPoints[0] = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
SetSkyObjectQuadHorizon(&m_Faces[5].m_SkyObjectQuadVector, v3QuadPoints);
m_Faces[5].m_strfacename = "bottom";
}
v3QuadPoints[0] = D3DXVECTOR3(1.0f, 1.0f, 0.0f);
v3QuadPoints[1] = D3DXVECTOR3(-1.0f, 1.0f, 0.0f);
v3QuadPoints[2] = D3DXVECTOR3(1.0f, -1.0f, 0.0f);
v3QuadPoints[3] = D3DXVECTOR3(-1.0f, -1.0f, 0.0f);
SetSkyObjectQuadHorizon(&m_FaceCloud.m_SkyObjectQuadVector, v3QuadPoints);
}
void CSkyBox::SetCloudColor(const TGradientColor & c_rColor, const TGradientColor & c_rNextColor, const DWORD & dwTransitionTime)
{
TSkyObjectFace & aFaceCloud = m_FaceCloud;
for (DWORD dwk = 0; dwk < aFaceCloud.m_SkyObjectQuadVector.size(); ++dwk)
{
CSkyObjectQuad & aSkyObjectQuad = aFaceCloud.m_SkyObjectQuadVector[dwk];
for (unsigned char v = 0; v < 4; ++v)
{
aSkyObjectQuad.SetSrcColor(v,
c_rColor.m_FirstColor.r,
c_rColor.m_FirstColor.g,
c_rColor.m_FirstColor.b,
c_rColor.m_FirstColor.a);
aSkyObjectQuad.SetTransition(v,
c_rNextColor.m_FirstColor.r,
c_rNextColor.m_FirstColor.g,
c_rNextColor.m_FirstColor.b,
c_rNextColor.m_FirstColor.a,
dwTransitionTime);
}
}
}
void CSkyBox::SetSkyColor(const TVectorGradientColor & c_rColorVector, const TVectorGradientColor & c_rNextColorVector, long lTransitionTime)
{
if (c_rColorVector.empty() || c_rNextColorVector.empty())
return;
unsigned long ulVectorGradientColornum = 0;
unsigned long uck;
for (unsigned char ucj = 0; ucj < 4; ++ucj)
{
TSkyObjectFace & aFace = m_Faces[ucj];
ulVectorGradientColornum = 0;
for (uck = 0; uck < aFace.m_SkyObjectQuadVector.size(); ++uck)
{
if (ulVectorGradientColornum >= c_rColorVector.size() || ulVectorGradientColornum >= c_rNextColorVector.size())
break;
CSkyObjectQuad & aSkyObjectQuad = aFace.m_SkyObjectQuadVector[uck];
aSkyObjectQuad.SetSrcColor(0,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.r,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.g,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.b,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.a);
aSkyObjectQuad.SetTransition(0,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.r,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.g,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.b,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.a,
lTransitionTime);
aSkyObjectQuad.SetSrcColor(1,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.r,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.g,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.b,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.a);
aSkyObjectQuad.SetTransition(1,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.r,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.g,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.b,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.a,
lTransitionTime);
aSkyObjectQuad.SetSrcColor(2,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.r,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.g,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.b,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.a);
aSkyObjectQuad.SetTransition(2,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.r,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.g,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.b,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.a,
lTransitionTime);
aSkyObjectQuad.SetSrcColor(3,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.r,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.g,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.b,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.a);
aSkyObjectQuad.SetTransition(3,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.r,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.g,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.b,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.a,
lTransitionTime);
ulVectorGradientColornum++;
}
}
TSkyObjectFace & aFaceTop = m_Faces[4];
ulVectorGradientColornum = 0;
for (uck = 0; uck < aFaceTop.m_SkyObjectQuadVector.size(); ++uck)
{
CSkyObjectQuad & aSkyObjectQuad = aFaceTop.m_SkyObjectQuadVector[uck];
for (unsigned char v = 0; v < 4; ++v)
{
aSkyObjectQuad.SetSrcColor(v,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.r,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.g,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.b,
c_rColorVector[ulVectorGradientColornum].m_FirstColor.a);
aSkyObjectQuad.SetTransition(v,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.r,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.g,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.b,
c_rNextColorVector[ulVectorGradientColornum].m_FirstColor.a,
lTransitionTime);
}
}
TSkyObjectFace & aFaceBottom = m_Faces[5];
ulVectorGradientColornum = c_rColorVector.size() - 1;
for (uck = 0; uck < aFaceBottom.m_SkyObjectQuadVector.size(); ++uck)
{
CSkyObjectQuad & aSkyObjectQuad = aFaceBottom.m_SkyObjectQuadVector[uck];
for (unsigned char v = 0; v < 4; ++v)
{
aSkyObjectQuad.SetSrcColor(v,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.r,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.g,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.b,
c_rColorVector[ulVectorGradientColornum].m_SecondColor.a);
aSkyObjectQuad.SetTransition(v,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.r,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.g,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.b,
c_rNextColorVector[ulVectorGradientColornum].m_SecondColor.a,
lTransitionTime);
}
}
}
void CSkyBox::StartTransition()
{
m_bTransitionStarted = true;
for (unsigned char ucj = 0; ucj < 6; ++ucj)
m_Faces[ucj].StartTransition();
m_FaceCloud.StartTransition();
}
void CSkyBox::Update()
{
CSkyObject::Update();
if (!m_bTransitionStarted)
return;
bool bResult = false;
for (unsigned char uci = 0; uci < 6; ++uci)
bResult = m_Faces[uci].Update() || bResult;
bResult = m_FaceCloud.Update() || bResult;
m_bTransitionStarted = bResult;
}
void CSkyBox::Render()
{
if (!IsNativeTerrainRenderEnabled())
return;
STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_FOGENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SetTexture(1, NULL);
STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
STATEMANAGER.SetVertexShader(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
STATEMANAGER.SetTransform(D3DTS_WORLD, &m_matWorld);
if (m_ucRenderMode == CSkyObject::SKY_RENDER_MODE_TEXTURE)
{
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
for (unsigned int i = 0; i < 6; ++i)
{
CGraphicImageInstance * pFaceImageInstance = m_GraphicImageInstanceMap[m_Faces[i].m_strFaceTextureFileName];
if (!pFaceImageInstance)
break;
STATEMANAGER.SetTexture(0, pFaceImageInstance->GetTextureReference().GetD3DTexture());
m_Faces[i].Render();
}
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSU);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSV);
}
else
{
STATEMANAGER.SetTexture(0, NULL);
for (unsigned int i = 0; i < 6; ++i)
{
m_Faces[i].Render();
}
}
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_FOGENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG2);
}
void CSkyBox::RenderCloud()
{
if (!IsNativeTerrainRenderEnabled())
return;
CGraphicImageInstance * pCloudGraphicImageInstance = m_GraphicImageInstanceMap[m_FaceCloud.m_strfacename];
if (!pCloudGraphicImageInstance || pCloudGraphicImageInstance->IsEmpty() || !pCloudGraphicImageInstance->GetTexturePointer())
return;
STATEMANAGER.SaveRenderState(D3DRS_ZENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_FOGENABLE, FALSE);
STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
m_matTextureCloud._31 = m_fCloudPositionU;
m_matTextureCloud._32 = m_fCloudPositionV;
DWORD dwCurTime = CTimer::Instance().GetCurrentMillisecond();
m_fCloudPositionU += m_fCloudScrollSpeedU * (float)(dwCurTime - m_dwlastTime) * 0.001f;
if (m_fCloudPositionU >= 1.0f)
m_fCloudPositionU = 0.0f;
m_fCloudPositionV += m_fCloudScrollSpeedV * (float)(dwCurTime - m_dwlastTime) * 0.001f;
if (m_fCloudPositionV >= 1.0f)
m_fCloudPositionV = 0.0f;
m_dwlastTime = dwCurTime;
STATEMANAGER.SaveTransform(D3DTS_TEXTURE0, &m_matTextureCloud);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATEINVALPHA_ADDCOLOR);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
D3DXMATRIX matProjCloud;
D3DXMatrixPerspectiveFovRH(&matProjCloud, D3DX_PI * 0.25f, 1.33333f, 50.0f, 999999.0f);
STATEMANAGER.SetTransform(D3DTS_WORLD, &m_matWorldCloud);
STATEMANAGER.SaveTransform(D3DTS_PROJECTION, &matProjCloud);
STATEMANAGER.SetTexture(0, pCloudGraphicImageInstance->GetTexturePointer()->GetD3DTexture());
m_FaceCloud.Render();
STATEMANAGER.RestoreTransform(D3DTS_PROJECTION);
STATEMANAGER.RestoreTransform(D3DTS_TEXTURE0);
STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS);
STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING);
STATEMANAGER.RestoreRenderState(D3DRS_ZENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_FOGENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND);
STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND);
}
+41
View File
@@ -0,0 +1,41 @@
// Platform skeleton for EterLib/TextBar.h (40250 EterLib/TextBar.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/TextBar.h"
#include "../PlatformStub.h"
CTextBar::CTextBar(int, bool)
{
MT_PLATFORM_STUB();
}
CTextBar::~CTextBar()
{
MT_PLATFORM_STUB();
}
auto CTextBar::TextOut(int, int, const char *) -> void
{
MT_PLATFORM_STUB();
}
auto CTextBar::SetTextColor(int, int, int) -> void
{
MT_PLATFORM_STUB();
}
auto CTextBar::GetTextExtent(const char *, SIZE *) -> void
{
MT_PLATFORM_STUB();
}
auto CTextBar::__SetFont(int, bool) -> void
{
MT_PLATFORM_STUB();
}
auto CTextBar::OnCreate() -> void
{
MT_PLATFORM_STUB();
}
+29
View File
@@ -0,0 +1,29 @@
// Platform skeleton for EterLib/Thread.h (40250 EterLib/Thread.cpp), generated by platform_stub.py.
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
#include "EterLib/StdAfx.h"
#include "EterLib/Thread.h"
#include "../PlatformStub.h"
CThread::CThread()
{
MT_PLATFORM_STUB();
}
auto CThread::Create(void *) -> int
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<int>();
}
auto CThread::EntryPoint(void *) -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
auto CThread::Run(void *) -> UINT
{
MT_PLATFORM_STUB();
return mt_platform_stub_return<UINT>();
}
+147
View File
@@ -0,0 +1,147 @@
#include "EterLib/StdAfx.h"
#include "UIRenderCommands.h"
#include "RenderCommands3D.h"
#include "EterLib/StateManager.h"
#include <algorithm>
namespace {
struct Point { float x, y; };
std::vector<Point> clip_polygon(std::vector<Point> polygon, int edge, float bound) {
std::vector<Point> result;
if (polygon.empty()) return result;
auto inside = [edge, bound](Point p) {
return edge == 0 ? p.x >= bound : edge == 1 ? p.x <= bound
: edge == 2 ? p.y >= bound : p.y <= bound;
};
auto intersect = [edge, bound](Point a, Point b) {
const float t = edge < 2 ? (bound - a.x) / (b.x - a.x)
: (bound - a.y) / (b.y - a.y);
return Point{a.x + t * (b.x - a.x), a.y + t * (b.y - a.y)};
};
Point previous = polygon.back();
for (Point current : polygon) {
const bool was_inside = inside(previous), is_inside = inside(current);
if (was_inside != is_inside) result.push_back(intersect(previous, current));
if (is_inside) result.push_back(current);
previous = current;
}
return result;
}
std::vector<UIRenderCommand> commands;
std::uint64_t frame_id = 0;
int canvas_width = 0;
int canvas_height = 0;
float clip_x1 = 0, clip_y1 = 0, clip_x2 = 0, clip_y2 = 0;
float saved_x1 = 0, saved_y1 = 0, saved_x2 = 0, saved_y2 = 0;
float offset_x = 0;
}
void UIRenderSetOffsetX(float x) { offset_x = x; }
float UIRenderOffsetX() { return offset_x; }
void UIRenderSetSize(int width, int height) { canvas_width = width; canvas_height = height; }
void UIRenderGetSize(unsigned* width, unsigned* height) {
if (width) *width = canvas_width;
if (height) *height = canvas_height;
}
void UIRenderBeginFrame() {
++frame_id;
commands.clear();
clip_x1 = clip_y1 = 0;
clip_x2 = canvas_width;
clip_y2 = canvas_height;
}
std::uint64_t UIRenderFrameId() { return frame_id; }
void UIRenderAdd(UIRenderCommand command) {
if (offset_x != 0) {
command.x1 += offset_x;
command.x2 += offset_x;
if (command.quad)
for (float& x : command.qx) x += offset_x;
}
command.clip_x1 = clip_x1; command.clip_y1 = clip_y1;
command.clip_x2 = clip_x2; command.clip_y2 = clip_y2;
command.behind_3d = Render3DDraws().empty();
if (command.kind == UIRenderCommand::Bar && command.quad) {
// Cooldown fans are triangles. Clip their geometry before either renderer consumes it.
std::vector<Point> polygon{{command.qx[0], command.qy[0]},
{command.qx[1], command.qy[1]},
{command.qx[2], command.qy[2]}};
const float bounds[4] = {clip_x1, clip_x2, clip_y1, clip_y2};
for (int edge = 0; edge < 4; ++edge)
polygon = clip_polygon(std::move(polygon), edge, bounds[edge]);
for (std::size_t i = 1; i + 1 < polygon.size(); ++i) {
UIRenderCommand piece = command;
const Point tri[3] = {polygon[0], polygon[i], polygon[i + 1]};
const float area = (tri[1].x - tri[0].x) * (tri[2].y - tri[0].y) -
(tri[1].y - tri[0].y) * (tri[2].x - tri[0].x);
if (area == 0.0f) continue;
for (int k = 0; k < 4; ++k) {
piece.qx[k] = tri[k < 3 ? k : 2].x;
piece.qy[k] = tri[k < 3 ? k : 2].y;
}
piece.x1 = std::min({tri[0].x, tri[1].x, tri[2].x});
piece.y1 = std::min({tri[0].y, tri[1].y, tri[2].y});
piece.x2 = std::max({tri[0].x, tri[1].x, tri[2].x});
piece.y2 = std::max({tri[0].y, tri[1].y, tri[2].y});
commands.push_back(std::move(piece));
}
return;
}
commands.push_back(command);
}
const std::vector<UIRenderCommand>& UIRenderCommands() { return commands; }
void UIRenderSetClip(float x, float y, float width, float height) {
saved_x1 = clip_x1; saved_y1 = clip_y1; saved_x2 = clip_x2; saved_y2 = clip_y2;
clip_x1 = x + offset_x; clip_y1 = y;
clip_x2 = x + offset_x + width; clip_y2 = y + height;
}
void UIRenderRestoreClip() {
clip_x1 = saved_x1; clip_y1 = saved_y1;
clip_x2 = saved_x2; clip_y2 = saved_y2;
}
void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const float y[4],
float su, float sv, float eu, float ev, std::uint32_t argb, int blend) {
// 40250 draws the image quad through the device: the UI pass's world transform places it
// (identity except where a caller sets one, e.g. CPythonMiniMap::RenderAtlas's window offset) and a
// stage-0 MODULATE with D3DTA_TFACTOR tints it (the atlas's NPC/warp/waypoint marks).
D3DXMATRIX world;
D3DXMatrixIdentity(&world);
if (CStateManager* state = CStateManager::InstancePtr()) {
state->GetTransform(D3DTS_WORLD, &world);
DWORD op = 0, arg1 = 0, arg2 = 0;
state->GetTextureStageState(0, D3DTSS_COLOROP, &op);
state->GetTextureStageState(0, D3DTSS_COLORARG1, &arg1);
state->GetTextureStageState(0, D3DTSS_COLORARG2, &arg2);
if (op == D3DTOP_MODULATE && (arg1 == D3DTA_TFACTOR || arg2 == D3DTA_TFACTOR)) {
// TFACTOR x TEXTURE drops the vertex colour; TFACTOR x DIFFUSE scales it. The canvas
// multiplies the texture in.
const std::uint32_t factor = state->GetRenderState(D3DRS_TEXTUREFACTOR) & 0x00FFFFFFu;
const DWORD other = arg1 == D3DTA_TFACTOR ? arg2 : arg1;
if (other == D3DTA_DIFFUSE) {
std::uint32_t tinted = argb & 0xFF000000u;
for (int shift = 0; shift < 24; shift += 8)
tinted |= ((((argb >> shift) & 255) * ((factor >> shift) & 255) + 127) / 255) << shift;
argb = tinted;
} else {
argb = (argb & 0xFF000000u) | factor;
}
}
}
UIRenderCommand command{UIRenderCommand::Image, 0, 0, 0, 0, argb};
for (int i = 0; i < 4; ++i) {
command.qx[i] = x[i] * world._11 + y[i] * world._21 + world._41 + 0.5f;
command.qy[i] = x[i] * world._12 + y[i] * world._22 + world._42 + 0.5f;
}
command.x1 = std::min({command.qx[0], command.qx[1], command.qx[2], command.qx[3]});
command.y1 = std::min({command.qy[0], command.qy[1], command.qy[2], command.qy[3]});
command.x2 = std::max({command.qx[0], command.qx[1], command.qx[2], command.qx[3]});
command.y2 = std::max({command.qy[0], command.qy[1], command.qy[2], command.qy[3]});
command.text = UIRenderTextureName(texture);
command.quad = true;
command.su = su; command.sv = sv; command.eu = eu; command.ev = ev;
command.blend = blend;
UIRenderAdd(std::move(command));
}
+86
View File
@@ -0,0 +1,86 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
// Commands emitted by the 40250 UI drawing calls, consumed by Godot's CanvasItem.
// The port layer stays independent of godot-cpp.
struct UIRenderCommand {
enum Kind { Bar, Line, Text, Image, GradientBar } kind;
float x1, y1, x2, y2;
std::uint32_t argb;
std::uint32_t end_argb = 0; // GradientBar only: colour on the bottom edge.
float clip_x1 = 0, clip_y1 = 0, clip_x2 = 0, clip_y2 = 0;
std::string text;
// Image only: text is the texture's file, drawn as the quad (vertices 0..3 = TL, TR, BL, BR)
// with texture coordinates su,sv..eu,ev; x1..y2 is the quad's bounding box.
bool quad = false;
float qx[4] = {}, qy[4] = {};
float su = 0, sv = 0, eu = 1, ev = 1;
int blend = 0; // CGraphicExpandedImageInstance::RENDERING_MODE_*
// A second texture stage that modulates the colour and replaces the alpha (40250 CPythonMiniMap's
// circular minimap_image_filter): the mask's texture coordinates at the quad's four corners.
std::string mask;
float mu[4] = {}, mv[4] = {};
bool behind_3d = false;
};
// D3DXCOLOR (0..1 floats) -> the 0xAARRGGBB the commands carry.
template <class Color>
std::uint32_t UIRenderColor(const Color& color) {
auto channel = [](float value) -> std::uint32_t {
return static_cast<std::uint32_t>((value < 0 ? 0 : value > 1 ? 1 : value) * 255.0f + 0.5f);
};
return (channel(color.a) << 24) | (channel(color.r) << 16) | (channel(color.g) << 8) | channel(color.b);
}
class CGraphicTexture;
// A file-backed texture is named by its pack path; a memory texture (CGraphicImageTexture::Create,
// filled through Lock/Unlock: the CGraphicFontTexture glyph pages) by "mem:<id>@<revision>", the
// revision counting Unlocks so the canvas knows when to fetch the pixels again.
std::string UIRenderTextureName(const CGraphicTexture* texture);
// The pixels of memory texture "mem:<id>" (the part of the name before '@'), as 0xAARRGGBB.
struct UIMemoryTexture {
int width = 0;
int height = 0;
std::uint32_t revision = 0;
std::vector<std::uint32_t> argb;
};
bool UIRenderMemoryTexture(const std::string& name, UIMemoryTexture* out);
struct IDirect3DTexture8;
struct IDirect3DBaseTexture8;
// Frees the platform texture behind a CGraphicTexture: a memory texture or a file texture's handle.
void UIRenderReleaseMemoryTexture(IDirect3DTexture8* texture);
// The name (as UIRenderTextureName) of the texture a D3D handle belongs to; "" for null or unknown.
std::string UIRenderTextureNameFromHandle(const IDirect3DBaseTexture8* handle);
std::string MtCpuTextureNameFromHandle(const IDirect3DBaseTexture8* handle);
bool MtCpuMemoryTexture(const std::string& name, UIMemoryTexture* out);
// A textured quad from 40250's TPDTVertex[4] (TL, TR, BL, BR) positions and texture coordinates.
// PORT: D3D8 puts pixel centres on integers, which is why 40250 subtracts 0.5 from every vertex; the
// Godot canvas puts them on .5, so the quad is shifted back by +0.5 here.
void UIRenderAddImage(const CGraphicTexture* texture, const float x[4], const float y[4],
float su, float sv, float eu, float ev, std::uint32_t argb, int blend = 0);
void UIRenderSetSize(int width, int height);
void UIRenderGetSize(unsigned* width, unsigned* height);
void UIRenderBeginFrame();
std::uint64_t UIRenderFrameId();
void UIRenderAdd(UIRenderCommand command);
const std::vector<UIRenderCommand>& UIRenderCommands();
void UIRenderSetClip(float x, float y, float width, float height);
// PORT (mobile safe area): shifts the commands (and clips) recorded after it right by x canvas
// pixels, so the 40250 window layers can sit inside the rounded screen corners while the GAME layer
// (3D world, text tails) keeps the full canvas. 0 is the verbatim 40250 path.
void UIRenderSetOffsetX(float x);
float UIRenderOffsetX();
void UIRenderRestoreClip();
// HiDPI text: CGraphicFontTexture rasterises its glyph pages at this multiple of the logical font
// size (the swapchain's pixels per UI pixel) while keeping the 40250 glyph metrics and page UVs in
// logical pixels. 1 (the default) is the verbatim 40250 path. Latched when the first font page is
// created, so set it before the game creates fonts.
void UISetFontOversample(int scale);
int UIFontOversample();
+109
View File
@@ -0,0 +1,109 @@
// 40250 EterLib/Util.cpp:140-297, the default code page and font face.
//
// The rest of Util.cpp (LoadTextData / base64 / TokenTo*) is logic and not here. The 9x face table has
// CP949/Shift-JIS/GBK/Big5 literals, so this block is copied by hand instead of port_copy.
#include "EterLib/StdAfx.h"
#include "EterLib/Util.h"
#include "EterLocale/CodePageId.h"
static std::string gs_fontFace="";
static DWORD gs_codePage=0;
int GetCharsetFromCodePage(WORD codePage)
{
switch( codePage )
{
case CP_932:
return SHIFTJIS_CHARSET;
case CP_949:
return HANGUL_CHARSET;
case CP_936:
return GB2312_CHARSET;
case CP_950:
return CHINESEBIG5_CHARSET;
case CP_1253:
return GREEK_CHARSET;
case CP_1254:
return TURKISH_CHARSET;
case CP_1255:
return HEBREW_CHARSET;
case CP_1256:
return ARABIC_CHARSET;
case CP_1257:
return BALTIC_CHARSET;
case CP_1258:
return VIETNAMESE_CHARSET;
case CP_874:
return THAI_CHARSET;
case CP_1250:
return EASTEUROPE_CHARSET;
case CP_1251:
return RUSSIAN_CHARSET;
default:
return DEFAULT_CHARSET;
}
}
const char* GetFontFaceFromCodePageNT(WORD codePage)
{
switch( codePage )
{
case CP_932:
return "MS PGothic";
case CP_949:
return "GulimChe";
case CP_936:
return "SimSun";
case CP_950:
return "MingLiU";
case CP_874:
return "Tahoma";
case CP_1252:
return "Arial";
case CP_1256:
return "Tahoma";
case CP_1258:
return "Tahoma";
case CP_65001:
return "Arial";
default:
return "Arial";
}
}
DWORD GetDefaultCodePage()
{
return gs_codePage;
}
const char * GetDefaultFontFace()
{
return gs_fontFace.c_str();
}
// PORT: 40250 asks EnumFontFamiliesEx for the 9x (native-script) face name, then the NT one. The native
// names never match a font file here; CreateFontIndirect (platform/Win32Gdi.cpp) substitutes a missing
// face, so the NT name is the answer.
const char* GetFontFaceFromCodePage(WORD codePage)
{
return GetFontFaceFromCodePageNT(codePage);
}
void SetDefaultFontFace(const char* fontFace)
{
gs_fontFace=fontFace;
}
bool SetDefaultCodePage(DWORD codePage)
{
gs_codePage=codePage;
std::string fontFace=GetFontFaceFromCodePage(codePage);
if (fontFace.empty())
return false;
SetDefaultFontFace(fontFace.c_str());
return true;
}