Initial commit: ROW Client source code
Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,343 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// File: usefuldi.cpp
|
||||
//
|
||||
// Desc: Contains various DInput-specific utility classes and functions
|
||||
// to help the UI carry its operations more easily.
|
||||
//
|
||||
// Copyright (C) 1999-2001 Microsoft Corporation. All Rights Reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
// don't want useful.cpp to use precompiled header
|
||||
#include "useful.cpp"
|
||||
|
||||
|
||||
BOOL IsObjectOnExcludeList(DWORD dwOfs)
|
||||
{
|
||||
if (dwOfs == DIK_PREVTRACK ||
|
||||
dwOfs == DIK_NEXTTRACK ||
|
||||
dwOfs == DIK_MUTE ||
|
||||
dwOfs == DIK_CALCULATOR ||
|
||||
dwOfs == DIK_PLAYPAUSE ||
|
||||
dwOfs == DIK_MEDIASTOP ||
|
||||
dwOfs == DIK_VOLUMEDOWN ||
|
||||
dwOfs == DIK_VOLUMEUP ||
|
||||
dwOfs == DIK_WEBHOME ||
|
||||
dwOfs == DIK_SLEEP ||
|
||||
dwOfs == DIK_WEBSEARCH ||
|
||||
dwOfs == DIK_WEBFAVORITES ||
|
||||
dwOfs == DIK_WEBREFRESH ||
|
||||
dwOfs == DIK_WEBSTOP ||
|
||||
dwOfs == DIK_WEBFORWARD ||
|
||||
dwOfs == DIK_WEBBACK ||
|
||||
dwOfs == DIK_MYCOMPUTER ||
|
||||
dwOfs == DIK_MAIL ||
|
||||
dwOfs == DIK_MEDIASELECT ||
|
||||
dwOfs == DIK_LWIN ||
|
||||
dwOfs == DIK_RWIN ||
|
||||
dwOfs == DIK_POWER ||
|
||||
dwOfs == DIK_WAKE)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CALLBACK IncrementValPerObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
|
||||
{
|
||||
if (pvRef != NULL)
|
||||
++(*((int *)pvRef));
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
BOOL CALLBACK KeyboardIncrementValPerObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
|
||||
{
|
||||
if (pvRef != NULL && !IsObjectOnExcludeList(lpddoi->dwOfs))
|
||||
++(*((int *)pvRef));
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
BOOL CALLBACK FillDIDeviceObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
|
||||
{
|
||||
if (pvRef == NULL || lpddoi == NULL)
|
||||
return DIENUM_CONTINUE;
|
||||
|
||||
DIDEVOBJSTRUCT &os = *((DIDEVOBJSTRUCT *)pvRef);
|
||||
assert(os.pdoi != NULL);
|
||||
assert(os.n < os.nObjects);
|
||||
if (os.pdoi != NULL && os.n < os.nObjects)
|
||||
os.pdoi[os.n++] = *lpddoi;
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
// This is a special EnumObjects() callback for keyboard type devices. When we enumerate, dwOfs
|
||||
// member of lpddoi is meaningless. We need to take the middle 16 bits of dwType as dwOfs
|
||||
// (also same as DIK_xxx).
|
||||
BOOL CALLBACK FillDIKeyboardDeviceObject(LPCDIDEVICEOBJECTINSTANCEW lpddoi, LPVOID pvRef)
|
||||
{
|
||||
if (pvRef == NULL || lpddoi == NULL || IsObjectOnExcludeList(lpddoi->dwOfs))
|
||||
return DIENUM_CONTINUE;
|
||||
|
||||
DIDEVOBJSTRUCT &os = *((DIDEVOBJSTRUCT *)pvRef);
|
||||
assert(os.pdoi != NULL);
|
||||
assert(os.n < os.nObjects);
|
||||
if (os.pdoi != NULL && os.n < os.nObjects)
|
||||
{
|
||||
os.pdoi[os.n] = *lpddoi;
|
||||
os.pdoi[os.n].dwOfs = os.pdoi[os.n].dwType >> 8;
|
||||
wcscpy(os.pdoi[os.n].tszName, lpddoi->tszName);
|
||||
++os.n;
|
||||
}
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
HRESULT FillDIDeviceObjectStruct(DIDEVOBJSTRUCT &os, LPDIRECTINPUTDEVICE8W pDID)
|
||||
{
|
||||
if (pDID == NULL)
|
||||
return E_FAIL;
|
||||
|
||||
DIDEVICEINSTANCEW didi;
|
||||
didi.dwSize = sizeof(didi);
|
||||
pDID->GetDeviceInfo(&didi);
|
||||
|
||||
HRESULT hr;
|
||||
if (LOBYTE(didi.dwDevType) == DI8DEVTYPE_KEYBOARD)
|
||||
hr = pDID->EnumObjects(KeyboardIncrementValPerObject, &os.nObjects,
|
||||
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
|
||||
else
|
||||
hr = pDID->EnumObjects(IncrementValPerObject, &os.nObjects,
|
||||
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os.nObjects = 0;
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (os.nObjects == 0)
|
||||
return S_OK;
|
||||
|
||||
if (os.pdoi != NULL)
|
||||
free(os.pdoi);
|
||||
os.pdoi = (DIDEVICEOBJECTINSTANCEW *)malloc(sizeof(DIDEVICEOBJECTINSTANCEW) * os.nObjects);
|
||||
if (os.pdoi == NULL)
|
||||
{
|
||||
os.nObjects = 0;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Check if this device is a keyboard. If so, it needs special treatment.
|
||||
os.n = 0;
|
||||
if ((didi.dwDevType & 0xFF) == DI8DEVTYPE_KEYBOARD)
|
||||
{
|
||||
hr = pDID->EnumObjects(FillDIKeyboardDeviceObject, &os,
|
||||
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
|
||||
} else {
|
||||
hr = pDID->EnumObjects(FillDIDeviceObject, &os,
|
||||
DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os.nObjects = 0;
|
||||
return hr;
|
||||
}
|
||||
|
||||
assert(os.nObjects == os.n);
|
||||
os.nObjects = os.n;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LPTSTR AllocConfigureFlagStr(DWORD dwFlags)
|
||||
{
|
||||
static const AFS_FLAG flag[] = {
|
||||
#define f(F) { F, _T(#F) }
|
||||
f(DICD_EDIT), f(DICD_DEFAULT)
|
||||
#undef f
|
||||
};
|
||||
static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
|
||||
return AllocFlagStr(dwFlags, flag, flags);
|
||||
}
|
||||
|
||||
LPTSTR AllocActionFlagStr(DWORD dwFlags)
|
||||
{
|
||||
static const AFS_FLAG flag[] = {
|
||||
#define f(F) { F, _T(#F) }
|
||||
f(DIA_FORCEFEEDBACK),
|
||||
f(DIA_APPMAPPED),
|
||||
f(DIA_APPNOMAP),
|
||||
f(DIA_NORANGE),
|
||||
#undef f
|
||||
}; static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
|
||||
return AllocFlagStr(dwFlags, flag, flags);
|
||||
}
|
||||
|
||||
LPTSTR AllocActionHowFlagStr(DWORD dwFlags)
|
||||
{
|
||||
static const AFS_FLAG flag[] = {
|
||||
#define f(F) { F, _T(#F) }
|
||||
f(DIAH_UNMAPPED),
|
||||
f(DIAH_USERCONFIG),
|
||||
f(DIAH_APPREQUESTED),
|
||||
f(DIAH_HWAPP),
|
||||
f(DIAH_HWDEFAULT),
|
||||
f(DIAH_DEFAULT),
|
||||
f(DIAH_ERROR)
|
||||
#undef f
|
||||
}; static const int flags = sizeof(flag) / sizeof(AFS_FLAG);
|
||||
return AllocFlagStr(dwFlags, flag, flags);
|
||||
}
|
||||
|
||||
void CleanupActionFormatCopy(DIACTIONFORMATW &c)
|
||||
{
|
||||
if (c.rgoAction != NULL)
|
||||
{
|
||||
for (DWORD i = 0; i < c.dwNumActions; i++)
|
||||
if (c.rgoAction[i].lptszActionName != NULL)
|
||||
free((LPTSTR)c.rgoAction[i].lptszActionName);
|
||||
free(c.rgoAction);
|
||||
}
|
||||
c.rgoAction = NULL;
|
||||
}
|
||||
|
||||
HRESULT CopyActionFormat(DIACTIONFORMATW &to, const DIACTIONFORMATW &from)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
// copy all simple members
|
||||
to = from;
|
||||
|
||||
// null copied pointers since we're going to duplicate them (makes sure cleanup works)
|
||||
to.rgoAction = NULL;
|
||||
|
||||
// handle pointers/arrays/strings
|
||||
to.rgoAction = new DIACTIONW [to.dwNumActions];
|
||||
if (to.rgoAction == NULL)
|
||||
goto fail;
|
||||
|
||||
// first null it all
|
||||
memset(to.rgoAction, 0, sizeof(DIACTIONW) * to.dwNumActions);
|
||||
|
||||
// now copy...
|
||||
for (i = 0; i < to.dwNumActions; i++)
|
||||
{
|
||||
// copy simple members
|
||||
to.rgoAction[i] = from.rgoAction[i];
|
||||
|
||||
// handle pointers/arrays/strings
|
||||
to.rgoAction[i].lptszActionName = _wcsdup(from.rgoAction[i].lptszActionName);
|
||||
if (to.rgoAction[i].lptszActionName == NULL)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
fail:
|
||||
CleanupActionFormatCopy(to);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
LPDIACTIONFORMATW DupActionFormat(LPCDIACTIONFORMATW lpAcFor)
|
||||
{
|
||||
if (!lpAcFor)
|
||||
return NULL;
|
||||
|
||||
LPDIACTIONFORMATW pdup = new DIACTIONFORMATW;
|
||||
if (!pdup)
|
||||
return NULL;
|
||||
|
||||
if (FAILED(CopyActionFormat(*pdup, *lpAcFor)))
|
||||
{
|
||||
delete pdup;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pdup;
|
||||
}
|
||||
|
||||
void FreeActionFormatDup(LPDIACTIONFORMATW &lpAcFor)
|
||||
{
|
||||
if (!lpAcFor)
|
||||
return;
|
||||
|
||||
CleanupActionFormatCopy(*lpAcFor);
|
||||
delete lpAcFor;
|
||||
lpAcFor = NULL;
|
||||
}
|
||||
|
||||
void TraceActionFormat(LPTSTR header, const DIACTIONFORMATW &acf)
|
||||
{
|
||||
#ifdef CFGUI__TRACE_ACTION_FORMATS
|
||||
tracescope(a, header);
|
||||
trace(_T("\n"));
|
||||
|
||||
traceDWORD(acf.dwSize);
|
||||
traceDWORD(acf.dwActionSize);
|
||||
traceDWORD(acf.dwDataSize);
|
||||
traceDWORD(acf.dwNumActions);
|
||||
{tracescope(b, _T("acf.rgoAction Array\n"));
|
||||
for (DWORD i = 0; i < acf.dwNumActions; i++)
|
||||
{
|
||||
const DIACTIONW &a = acf.rgoAction[i];
|
||||
static TCHAR buf[MAX_PATH];
|
||||
_stprintf(buf, _T("Action %d\n"), i);
|
||||
{tracescope(c, buf);
|
||||
traceHEX(a.uAppData);
|
||||
traceDWORD(a.dwSemantic);
|
||||
LPTSTR str = AllocActionFlagStr(a.dwFlags);
|
||||
trace1(_T("a.dwFlags = %s\n"), str);
|
||||
free(str);
|
||||
traceWSTR(a.lptszActionName);
|
||||
traceUINT(a.uResIdString);
|
||||
traceDWORD(a.dwObjID);
|
||||
traceGUID(a.guidInstance);
|
||||
str = AllocActionHowFlagStr(a.dwHow);
|
||||
trace1(_T("a.dwHow = %s\n"), str);
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
traceGUID(acf.guidActionMap);
|
||||
traceDWORD(acf.dwGenre);
|
||||
traceDWORD(acf.dwBufferSize);
|
||||
traceLONG(acf.lAxisMin);
|
||||
traceLONG(acf.lAxisMax);
|
||||
traceHEX(acf.hInstString);
|
||||
traceHEX(acf.dwCRC);
|
||||
traceWSTR(acf.tszActionMap);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL IsZeroOrInvalidColorSet(const DICOLORSET &cs)
|
||||
{
|
||||
if (cs.dwSize < sizeof(DICOLORSET))
|
||||
return TRUE;
|
||||
|
||||
const int colors = 8;
|
||||
D3DCOLOR color[colors] = {
|
||||
cs.cTextFore,
|
||||
cs.cTextHighlight,
|
||||
cs.cCalloutLine,
|
||||
cs.cCalloutHighlight,
|
||||
cs.cBorder,
|
||||
cs.cControlFill,
|
||||
cs.cHighlightFill,
|
||||
cs.cAreaFill
|
||||
};
|
||||
|
||||
for (int i = 0; i < colors; i++)
|
||||
if (color[i])
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// D3DCOLOR2COLORREF swaps the blue and red components since GDI and D3D store RGB in the opposite order.
|
||||
// It also removes the alpha component as the GDI doesn't use that, and including it causes incorrect color.
|
||||
COLORREF D3DCOLOR2COLORREF(D3DCOLOR c)
|
||||
{
|
||||
LPBYTE pC = (LPBYTE)&c;
|
||||
|
||||
return (COLORREF)((DWORD(*pC) << 16) + (DWORD(*(pC+1)) << 8) + DWORD(*(pC+2)));
|
||||
}
|
||||
Reference in New Issue
Block a user