diff --git a/BluntDx/AssemblyInfo.cpp b/BluntDx/AssemblyInfo.cpp new file mode 100644 index 0000000000..8d857b81b9 --- /dev/null +++ b/BluntDx/AssemblyInfo.cpp @@ -0,0 +1,18 @@ +using namespace System; +using namespace System::Reflection; +using namespace System::Runtime::CompilerServices; +using namespace System::Runtime::InteropServices; +using namespace System::Security::Permissions; + +[assembly:AssemblyTitleAttribute("BluntDx")]; +[assembly:AssemblyDescriptionAttribute("BluntDirectX Lightweight MDX Replacement")]; +[assembly:AssemblyConfigurationAttribute("")]; +[assembly:AssemblyCompanyAttribute("C Forbes & Associates")]; +[assembly:AssemblyProductAttribute("BluntDx")]; +[assembly:AssemblyCopyrightAttribute("Copyright (c) C Forbes & Associates 2006")]; +[assembly:AssemblyTrademarkAttribute("")]; +[assembly:AssemblyCultureAttribute("")]; +[assembly:AssemblyVersionAttribute("1.0.*")]; +[assembly:ComVisible(false)]; +[assembly:CLSCompliantAttribute(true)]; +[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; diff --git a/BluntDx/BluntDx.vcproj b/BluntDx/BluntDx.vcproj new file mode 100644 index 0000000000..c65bc6125d --- /dev/null +++ b/BluntDx/BluntDx.vcproj @@ -0,0 +1,270 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BluntDx/Direct3D.cpp b/BluntDx/Direct3D.cpp new file mode 100644 index 0000000000..a2ae5c5b44 --- /dev/null +++ b/BluntDx/Direct3D.cpp @@ -0,0 +1,39 @@ +#pragma comment(lib, "d3d9.lib") +#pragma comment(lib, "d3dx9.lib") +#pragma comment(lib, "user32.lib") +#pragma comment(lib, "gdi32.lib") + +#pragma unmanaged + +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x0500 + +#include +#include +#include + +#pragma managed + +#include + +#pragma once + +#using "System.Drawing.dll" +#using "System.Windows.Forms.dll" + +using namespace System; +using namespace System::Windows::Forms; +using namespace System::IO; +using namespace System::Drawing; + +#include "Utilities.h" + +#include "Enumerations.h" +#include "GraphicsDevice.h" +#include "ImageInformation.h" +#include "Texture.h" +#include "SpriteHelper.h" +#include "FontHelper.h" +#include "Mesh.h" +#include "Effect.h" +#include "VertexBuffer.h" \ No newline at end of file diff --git a/BluntDx/DirectInput.cpp b/BluntDx/DirectInput.cpp new file mode 100644 index 0000000000..ed9034f51d --- /dev/null +++ b/BluntDx/DirectInput.cpp @@ -0,0 +1,37 @@ +#pragma comment(lib, "dxguid.lib") +#pragma comment(lib, "dinput8.lib") +#pragma comment(lib, "user32.lib") +#pragma comment(lib, "gdi32.lib") + +#pragma unmanaged + +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x0500 + +#define INITGUID +#define DIRECTINPUT_VERSION 0x0800 + +#include +#include + +#pragma managed + +#include + +#pragma once + +#using "System.Drawing.dll" +#using "System.Windows.Forms.dll" + +using namespace System; +using namespace System::Windows::Forms; +using namespace System::IO; +using namespace System::Drawing; + +#include "Utilities.h" + +#include "InputManager.h" +#include "KeyboardState.h" +#include "MouseState.h" +#include "JoystickState.h" +#include "InputDevice.h" \ No newline at end of file diff --git a/BluntDx/Effect.h b/BluntDx/Effect.h new file mode 100644 index 0000000000..877050bb23 --- /dev/null +++ b/BluntDx/Effect.h @@ -0,0 +1,165 @@ +#pragma once + +using namespace System::Collections::Generic; + +namespace BluntDirectX { namespace Direct3D +{ + public enum class ShaderQuality + { + Low, + Medium, + High, + }; + + public ref class Effect + { + private: + static ID3DXEffectPool* effectPool; + + static Effect() + { + ID3DXEffectPool* e; + D3DXCreateEffectPool( &e ); + effectPool = e; + } + + ShaderQuality shaderQuality; + + internal: + ID3DXEffect* effect; + + public: + Effect(GraphicsDevice^ device, Stream^ data) + { + ID3DXEffect* e; + ID3DXBuffer* compilationErrors; + HRESULT hr; + + data->Position = 0; + array^ bytes = gcnew array((int)data->Length); + data->Read( bytes, 0, (int)data->Length ); + + pin_ptr pdata = &bytes[0]; + + if (FAILED( hr = D3DXCreateEffect( device->device, pdata, (UINT)data->Length, NULL, NULL, + D3DXSHADER_PACKMATRIX_COLUMNMAJOR | D3DXSHADER_USE_LEGACY_D3DX9_31_DLL, effectPool, &e, &compilationErrors ) )) + { + String^ errors = gcnew String((char*)compilationErrors->GetBufferPointer()); + compilationErrors->Release(); + + throw gcnew InvalidOperationException( String::Format( + "Failed compiling shader; HRESULT={0}, Errors:\n{1}", + hr, errors )); + } + + effect = e; + Quality = ShaderQuality::High; + } + + IntPtr GetHandle( String^ symbol ) + { + array^ chars = System::Text::Encoding::ASCII->GetBytes(symbol); + pin_ptr p = &chars[0]; + IntPtr result = IntPtr((void*)effect->GetParameterByName(NULL, (char*)p)); + return result; + } + + ~Effect() + { + safe_release( effect ); + } + + property ShaderQuality Quality + { + ShaderQuality get() { return shaderQuality; } + void set( ShaderQuality s ) + { + if (shaderQuality == s) + return; + + shaderQuality = s; + switch(s) + { + case ShaderQuality::High: + if (SUCCEEDED(effect->SetTechnique( "high_quality" ))) + break; + case ShaderQuality::Medium: + if (SUCCEEDED(effect->SetTechnique( "med_quality" ))) + break; + case ShaderQuality::Low: + if (SUCCEEDED(effect->SetTechnique( "low_quality" ))) + break; + default: + throw gcnew Exception( "Invalid shader quality" ); + } + } + }; + + void Commit() + { + effect->CommitChanges(); + } + + int Begin() + { + unsigned int passes; + effect->Begin( &passes, D3DXFX_DONOTSAVESTATE | D3DXFX_DONOTSAVESHADERSTATE ); + return passes; + } + + void End() + { + effect->End(); + } + + void BeginPass(int pass) + { + effect->BeginPass( pass ); + } + + void EndPass() + { + effect->EndPass(); + } + + generic< typename T> where T : value class + void SetValue( IntPtr handle, T value ) + { + pin_ptr pvalue = &value; + effect->SetValue( (D3DXHANDLE)handle.ToPointer(), pvalue, sizeof(T) ); + } + + void SetTexture( IntPtr handle, Texture^ texture ) + { + effect->SetTexture( (D3DXHANDLE)handle.ToPointer(), texture->texture ); + } + + property array>^ ShaderResources + { + array>^ get() + { + List>^ resources = gcnew List>(); + int id = 0; + D3DXHANDLE parameter; + + while( parameter = effect->GetParameter( NULL, id++ ) ) + { + D3DXHANDLE annotation; + + if (!(annotation = effect->GetAnnotationByName( parameter, "src" ))) + continue; + + char* value; + HRESULT hr; + + if (FAILED(hr = effect->GetString( annotation, (LPCSTR*)&value ))) + ThrowHelper::Hr(hr); + + resources->Add( KeyValuePair( IntPtr( (void*)parameter ), gcnew String(value) ) ); + } + + return resources->ToArray(); + } + } + }; +}} \ No newline at end of file diff --git a/BluntDx/Enumerations.h b/BluntDx/Enumerations.h new file mode 100644 index 0000000000..2c1f680cf3 --- /dev/null +++ b/BluntDx/Enumerations.h @@ -0,0 +1,27 @@ +#pragma once + +namespace BluntDirectX { namespace Direct3D +{ + [Flags] + public enum class Surfaces + { + None = 0, + Color = D3DCLEAR_TARGET, + Depth = D3DCLEAR_ZBUFFER, + }; + + [Flags] + public enum class VertexFormat + { + None = 0, + Position = D3DFVF_XYZ, + Normal = D3DFVF_NORMAL, + Texture = D3DFVF_TEX1, + }; + + public enum class PrimitiveType + { + PointList = D3DPT_POINTLIST, + TriangleList = D3DPT_TRIANGLELIST, + }; +}} \ No newline at end of file diff --git a/BluntDx/FontHelper.h b/BluntDx/FontHelper.h new file mode 100644 index 0000000000..5cf3b275d6 --- /dev/null +++ b/BluntDx/FontHelper.h @@ -0,0 +1,56 @@ +#pragma once + +namespace BluntDirectX { namespace Direct3D +{ + public ref class FontHelper + { + private: + static int MakeLogicalFontHeight( int emSize ) + { + int result; + HDC hdc = GetDC(NULL); + result = -MulDiv( emSize, GetDeviceCaps( hdc, LOGPIXELSY ), 72 ); + ReleaseDC( NULL, hdc ); + + return result; + } + + internal: + ID3DXFont* font; + + public: + FontHelper( GraphicsDevice^ device, String^ face, int emSize, bool bold ) + { + HRESULT hr; + ID3DXFont* f; + + pin_ptr uface = PtrToStringChars(face); + + int height = MakeLogicalFontHeight( emSize ); + + if (FAILED( + hr = D3DXCreateFont( device->device, height, 0, bold ? FW_BOLD : FW_NORMAL, 1, false, + DEFAULT_CHARSET, OUT_STRING_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, + uface, &f))) + ThrowHelper::Hr(hr); + + font = f; + } + + void Draw( SpriteHelper^ sprite, String^ text, int x, int y, int color ) + { + pin_ptr utext = PtrToStringChars(text); + RECT r = {x, y, x+1, y+1}; + font->DrawText( sprite->sprite, utext, -1, &r, DT_LEFT | DT_NOCLIP, color ); + } + + Size MeasureText( SpriteHelper^ sprite, String^ text ) + { + pin_ptr utext = PtrToStringChars(text); + RECT r = {0,0,1,1}; + int height = font->DrawText( sprite->sprite, utext, -1, &r, DT_LEFT | DT_CALCRECT, 0 ); + + return Size( r.right - r.left, height ); + } + }; +}} \ No newline at end of file diff --git a/BluntDx/GraphicsDevice.h b/BluntDx/GraphicsDevice.h new file mode 100644 index 0000000000..63041a026a --- /dev/null +++ b/BluntDx/GraphicsDevice.h @@ -0,0 +1,168 @@ +#pragma once + +namespace BluntDirectX { namespace Direct3D +{ + public ref class GraphicsDevice + { + private: + GraphicsDevice( IDirect3DDevice9* device, bool hasHardwareVp ) : device( device ), hardwareVp( hasHardwareVp ) + { + IDirect3DSurface9* s; + device->GetRenderTarget(0, &s); + defaultSurface = s; + } + + bool hardwareVp; + + internal: + IDirect3DDevice9* device; + IDirect3DSurface9* defaultSurface; + + void SetRenderTarget( IDirect3DSurface9* surface ) + { + if (surface == nullptr) + surface = defaultSurface; + + device->SetRenderTarget( 0, surface ); + } + + public: + void BindDefaultRenderTarget() + { + SetRenderTarget( nullptr ); + } + + void BindSurface( IntPtr p ) + { + SetRenderTarget( (IDirect3DSurface9*) p.ToPointer() ); + } + + IntPtr GetDefaultSurface() + { + return IntPtr(defaultSurface); + } + + void Begin() + { + device->BeginScene(); + } + + void End() + { + device->EndScene(); + } + + ~GraphicsDevice() + { + safe_release( device ); + } + + void Clear( int color ) + { + device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, (D3DCOLOR)color, 1.0f, 0 ); + } + + void Clear( int color, Surfaces surfaces ) + { + device->Clear( 0, NULL, (DWORD)surfaces, (D3DCOLOR)color, 1.0f, 0 ); + } + + void Present() + { + device->Present(NULL,NULL,NULL,NULL); + } + + property bool HasHardwareVP + { + bool get() { return hardwareVp; } + } + + static GraphicsDevice^ CreateRenderless() + { + IDirect3D9* d3d = Direct3DCreate9( D3D_SDK_VERSION ); + D3DPRESENT_PARAMETERS pp; + memset( &pp, 0, sizeof(pp) ); + + pp.BackBufferCount = 1; + pp.BackBufferFormat = D3DFMT_UNKNOWN; + pp.BackBufferWidth = pp.BackBufferHeight = 1; + pp.SwapEffect = D3DSWAPEFFECT_COPY; + pp.Windowed = true; + + IDirect3DDevice9* dev; + HRESULT hr; + + if (FAILED(hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, GetConsoleWindow(), + D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, &dev))) + ThrowHelper::Hr(hr); + + return gcnew GraphicsDevice( dev, true ); + } + + static GraphicsDevice^ Create(Control^ host, int width, int height, bool windowed, bool vsync) + { + IDirect3D9* d3d = Direct3DCreate9( D3D_SDK_VERSION ); + D3DPRESENT_PARAMETERS pp; + memset( &pp, 0, sizeof(pp) ); + + pp.BackBufferCount = vsync ? 1 : 2; + pp.BackBufferWidth = width; + pp.BackBufferHeight = height; + pp.BackBufferFormat = D3DFMT_X8R8G8B8; + + pp.AutoDepthStencilFormat = D3DFMT_D24X8; + pp.EnableAutoDepthStencil = true; + pp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + pp.Windowed = windowed; + pp.PresentationInterval = (vsync && !windowed) ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE; + + DWORD flags[] = { + D3DCREATE_PUREDEVICE | D3DCREATE_HARDWARE_VERTEXPROCESSING, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + D3DCREATE_MIXED_VERTEXPROCESSING, + D3DCREATE_SOFTWARE_VERTEXPROCESSING, + 0 + }; + + DWORD* pf = &flags[0]; + while(*pf) + { + IDirect3DDevice9* pd; + HRESULT hr; + + bool configHasHardwareVp = 0 != (*pf & D3DCREATE_HARDWARE_VERTEXPROCESSING); + + if (SUCCEEDED( hr = d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, (HWND)host->Handle.ToInt32(), + *pf, &pp, &pd))) + return gcnew GraphicsDevice( pd, configHasHardwareVp ); + + ++pf; + } + + throw gcnew ApplicationException("D3D not available."); + } + + void EnableScissor( int left, int top, int width, int height ) + { + RECT r = { left, top, width, height }; + device->SetScissorRect( &r ); + device->SetRenderState( D3DRS_SCISSORTESTENABLE, true ); + } + + void DisableScissor() + { + device->SetRenderState( D3DRS_SCISSORTESTENABLE, false ); + } + + void DrawPrimitives(PrimitiveType primtype, int count) + { + device->DrawPrimitive( (D3DPRIMITIVETYPE)primtype, 0, count ); + } + + void DrawIndexedPrimitives(PrimitiveType primtype, int vertexPoolSize, int numPrimitives) + { + device->DrawIndexedPrimitive( (D3DPRIMITIVETYPE)primtype, 0, 0, vertexPoolSize, 0, numPrimitives ); + } + }; +}} diff --git a/BluntDx/ImageInformation.h b/BluntDx/ImageInformation.h new file mode 100644 index 0000000000..3a5c69c55d --- /dev/null +++ b/BluntDx/ImageInformation.h @@ -0,0 +1,36 @@ +#pragma once + +namespace BluntDirectX { namespace Direct3D +{ + public value class ImageInformation + { + private: + ImageInformation( int width, int height, int depth, bool isCube ) + : Width( width ), Height( height ), Depth( depth ), IsCube( isCube ) {} + + public: + int Width; + int Height; + int Depth; + bool IsCube; + + static ImageInformation Create( Stream^ stream ) + { + D3DXIMAGE_INFO info; + + stream->Position = 0; + array^ data = gcnew array( (int)stream->Length ); + stream->Read( data, 0, data->Length ); + + HRESULT hr; + + pin_ptr p = &data[0]; + + if (FAILED( hr = D3DXGetImageInfoFromFileInMemory( p, data->Length, &info ))) + throw gcnew InvalidOperationException( "image information load failed" ); + + return ImageInformation( info.Width, info.Height, info.Depth, + info.ResourceType == D3DRTYPE_CUBETEXTURE ); + } + }; +}} \ No newline at end of file diff --git a/BluntDx/InputDevice.h b/BluntDx/InputDevice.h new file mode 100644 index 0000000000..52eba91eaa --- /dev/null +++ b/BluntDx/InputDevice.h @@ -0,0 +1,153 @@ +#pragma once + +namespace BluntDirectX { namespace DirectInput +{ + [Flags] + public enum class CooperativeLevel + { + OnlyWhenFocused = 0x1, + Exclusive = 0x2, + DisableWindowsKey = 0x4, + }; + + public enum class DeviceType + { + Keyboard, + Mouse, + Joystick, + }; + + public ref class DiInputDevice + { + private: + DiInputDevice( IDirectInputDevice8* device ) + : device(device), devtype( DeviceType::Joystick ) {} + + internal: + IDirectInputDevice8* device; + DeviceType devtype; + + public: + static property Guid SystemKeyboard + { + Guid get() + { + return *(Guid*)&GUID_SysKeyboard; + } + } + + static property Guid SystemMouse + { + Guid get() + { + return *(Guid*)&GUID_SysMouse; + } + } + + DiInputDevice( InputManager^ manager, Guid guid, DeviceType devtype ) : devtype( devtype ) + { + HRESULT hr; + IDirectInputDevice8* _device; + + GUID* p = (GUID*)&guid; + + if (FAILED( hr = manager->di->CreateDevice( *p, &_device, NULL ))) + ThrowHelper::Hr(hr); + + device = _device; + } + + void SetCooperativeLevel( Control^ host, CooperativeLevel level) + { + int _level = (int)level; + DWORD flags = 0; + HRESULT hr; + + flags |= ((_level & (int)CooperativeLevel::OnlyWhenFocused) ? DISCL_FOREGROUND : DISCL_BACKGROUND); + flags |= ((_level & (int)CooperativeLevel::Exclusive) ? DISCL_EXCLUSIVE : DISCL_NONEXCLUSIVE); + if (_level & (int)CooperativeLevel::DisableWindowsKey) + flags |= DISCL_NOWINKEY; + + if (FAILED( hr = device->SetCooperativeLevel( (HWND)host->Handle.ToInt32(), flags ) )) + ThrowHelper::Hr(hr); + + if (devtype == DeviceType::Keyboard) + device->SetDataFormat( &c_dfDIKeyboard ); + else if (devtype == DeviceType::Mouse) + device->SetDataFormat( &c_dfDIMouse ); + } + + void Acquire() + { + HRESULT hr; + if (FAILED(hr = device->Acquire())) + ThrowHelper::Hr(hr); + } + + void Unacquire() + { + HRESULT hr; + if (FAILED(hr = device->Unacquire())) + ThrowHelper::Hr(hr); + } + + void Poll() + { + HRESULT hr; + if (FAILED(hr = device->Poll())) + ThrowHelper::Hr(hr); + } + + KeyboardState^ GetKeyboardState() + { + char buffer[256]; + HRESULT hr; + + if (FAILED(hr = device->GetDeviceState(sizeof(buffer), (void*)buffer))) + ThrowHelper::Hr(hr); + + array^ result = gcnew array(256); + + for( int i=0; i<256; i++ ) + result[i] = (buffer[i] & 0x80) != 0; + + return gcnew KeyboardState(result); + } + + MouseState^ GetMouseState() + { + MouseData mouse; + HRESULT hr; + + if (FAILED(hr = device->GetDeviceState(sizeof(mouse), (void*)&mouse))) + ThrowHelper::Hr(hr); + + return gcnew MouseState(mouse); + } + + JoystickState^ GetJoystickState() + { + DIJOYSTATE state; + HRESULT hr; + + if (FAILED(hr = device->GetDeviceState(sizeof(state), (void*)&state))) + ThrowHelper::Hr(hr); + + return gcnew JoystickState( &state ); + } + + ~DiInputDevice() + { + safe_release( device ); + } + + static DiInputDevice^ GetJoystick( InputManager^ manager ) + { + IDirectInputDevice8* dev = CreateAndConfigureJoystick( manager->di ); + if (dev == nullptr) + return nullptr; + + return gcnew DiInputDevice( dev ); + } + }; +}} \ No newline at end of file diff --git a/BluntDx/InputManager.h b/BluntDx/InputManager.h new file mode 100644 index 0000000000..e02cb7918e --- /dev/null +++ b/BluntDx/InputManager.h @@ -0,0 +1,30 @@ +#pragma once + +namespace BluntDirectX { namespace DirectInput +{ + public ref class InputManager + { + private: + + internal: + IDirectInput8* di; + + public: + InputManager() + { + HINSTANCE hinst = GetModuleHandle(0); + HRESULT hr; + IDirectInput8* _di; + + if (FAILED( hr = DirectInput8Create( hinst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&_di, NULL ))) + ThrowHelper::Hr(hr); + + di = _di; + } + + ~InputManager() + { + safe_release(di); + } + }; +}} \ No newline at end of file diff --git a/BluntDx/JoystickState.h b/BluntDx/JoystickState.h new file mode 100644 index 0000000000..7e9ce39b13 --- /dev/null +++ b/BluntDx/JoystickState.h @@ -0,0 +1,159 @@ +#pragma once + +namespace BluntDirectX { namespace DirectInput { + +#define joy_axis_limit 1000 + +#pragma unmanaged + + int CALLBACK EnumDevicesCb( const DIDEVICEINSTANCE* inst, void* data ) + { + DIDEVICEINSTANCE* pdata = (DIDEVICEINSTANCE*)data; + memcpy( pdata, inst, sizeof( DIDEVICEINSTANCE ) ); + return DIENUM_STOP; + } + + int CALLBACK EnumDeviceObjectsCb( const DIDEVICEOBJECTINSTANCE* inst, void* data ) + { + IDirectInputDevice8* dev = (IDirectInputDevice8*) data; + + DIPROPRANGE p; + p.diph.dwSize = sizeof(DIPROPRANGE); + p.diph.dwHeaderSize = sizeof(DIPROPHEADER); + p.diph.dwHow = DIPH_BYID; + p.diph.dwObj = inst->dwType; + p.lMin = -joy_axis_limit; + p.lMax = joy_axis_limit; + + HRESULT hr; + if (FAILED(hr = dev->SetProperty( DIPROP_RANGE, &p.diph ))) + return DIENUM_STOP; + + return DIENUM_CONTINUE; + } + + IDirectInputDevice8* CreateAndConfigureJoystick( IDirectInput8* di ) + { + DIDEVICEINSTANCE inst; + memset( &inst, 0, sizeof(inst) ); + di->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumDevicesCb, (void*)&inst, DIEDFL_ATTACHEDONLY ); + if (inst.dwSize == 0) + return nullptr; + + IDirectInputDevice8* dev; + HRESULT hr = di->CreateDevice( inst.guidInstance, &dev, NULL ); + + if (FAILED(hr)) + return nullptr; + + hr = dev->EnumObjects( EnumDeviceObjectsCb, (void*)dev, DIDFT_AXIS ); + + if (FAILED(hr)) { + dev->Release(); + return nullptr; + } + + dev->SetDataFormat( &c_dfDIJoystick ); + return dev; + } + +#pragma managed + + public ref class JoystickState + { + private: + DIJOYSTATE* pstate; + + internal: + JoystickState(DIJOYSTATE* state) + { + DIJOYSTATE* p = new DIJOYSTATE; + pstate = p; + memcpy( pstate, state, sizeof( DIJOYSTATE ) ); + } + + public: + ~JoystickState() + { + delete pstate; + } + + property float x + { + float get() + { + return (float)pstate->lX / joy_axis_limit; + } + } + + property float y + { + float get() + { + return (float)pstate->lY / joy_axis_limit; + } + } + + property float z + { + float get() + { + return (float)pstate->lZ / joy_axis_limit; + } + } + + property float rx + { + float get() + { + return (float)pstate->lRx / joy_axis_limit; + } + } + + property float ry + { + float get() + { + return (float)pstate->lRy / joy_axis_limit; + } + } + + property float rz + { + float get() + { + return (float)pstate->lRz / joy_axis_limit; + } + } + + property float u + { + float get() + { + return (float)pstate->rglSlider[0] / joy_axis_limit; + } + } + + property float v + { + float get() + { + return (float)pstate->rglSlider[1] / joy_axis_limit; + } + } + + property int pov + { + int get() + { + return pstate->rgdwPOV[0]; + } + } + + bool button( int button ) + { + return (pstate->rgbButtons[button] & 0x80) != 0; + } + }; + +}} \ No newline at end of file diff --git a/BluntDx/KeyboardState.h b/BluntDx/KeyboardState.h new file mode 100644 index 0000000000..c209733b05 --- /dev/null +++ b/BluntDx/KeyboardState.h @@ -0,0 +1,77 @@ +#pragma once + +namespace BluntDirectX { namespace DirectInput +{ + public enum class Key : unsigned char + { + A = DIK_A, B = DIK_B, C = DIK_C, + D = DIK_D, E = DIK_E, F = DIK_F, + G = DIK_G, H = DIK_H, I = DIK_I, + J = DIK_J, K = DIK_K, L = DIK_L, + M = DIK_M, N = DIK_N, O = DIK_O, + P = DIK_P, Q = DIK_Q, R = DIK_R, + S = DIK_S, T = DIK_T, U = DIK_U, + V = DIK_V, W = DIK_W, X = DIK_X, + Y = DIK_Y, Z = DIK_Z, + + D0 = DIK_0, D1 = DIK_1, D2 = DIK_2, D3 = DIK_3, D4 = DIK_4, + D5 = DIK_5, D6 = DIK_6, D7 = DIK_7, D8 = DIK_8, D9 = DIK_9, + + ArrowUp = DIK_UPARROW, + ArrowLeft = DIK_LEFTARROW, + ArrowRight = DIK_RIGHTARROW, + ArrowDown = DIK_DOWNARROW, + + Space = DIK_SPACE, + + Escape = DIK_ESCAPE, + Tab = DIK_TAB, + Enter = DIK_RETURN, + + Tilde = DIK_GRAVE, + + F1 = DIK_F1, + F2 = DIK_F2, + F3 = DIK_F3, + F4 = DIK_F4, + F5 = DIK_F5, + F6 = DIK_F6, + F7 = DIK_F7, + F8 = DIK_F8, + F9 = DIK_F9, + F10 = DIK_F10, + F11 = DIK_F11, + F12 = DIK_F12, + + LeftControl = DIK_LCONTROL, + LeftShift = DIK_LSHIFT, + LeftAlt = DIK_LALT, + + Home = DIK_HOME, + End = DIK_END, + PageUp = DIK_PGUP, + PageDown = DIK_PGDN, + + RightControl = DIK_RCONTROL, + RightShift = DIK_RSHIFT, + RightAlt = DIK_RALT, + }; + + public ref class KeyboardState + { + private: + array^ data; + + internal: + KeyboardState( array^ data ) : data(data) {} + + public: + property bool default[ Key ] + { + bool get( Key key ) + { + return data[ (int) key ]; + } + } + }; +}} \ No newline at end of file diff --git a/BluntDx/Mesh.h b/BluntDx/Mesh.h new file mode 100644 index 0000000000..1ab4294e6b --- /dev/null +++ b/BluntDx/Mesh.h @@ -0,0 +1,66 @@ +#pragma once + +namespace BluntDirectX { namespace Direct3D +{ + + generic< typename T > where T : value class + public ref class Mesh + { + internal: + ID3DXMesh* mesh; + + public: + Mesh( GraphicsDevice^ device, VertexFormat vertexFormat, array^ vertices, array^ indices, + array^ attributes ) + { + ID3DXMesh* m; + HRESULT hr; + + if (FAILED( hr = + D3DXCreateMeshFVF( indices->Length / 3, vertices->Length, D3DXMESH_MANAGED, (DWORD)vertexFormat, + device->device, &m))) + ThrowHelper::Hr(hr); + + mesh = m; + + { + void* vb; + mesh->LockVertexBuffer(0, &vb); + pin_ptr t = &vertices[0]; + memcpy( vb, t, vertices->Length * sizeof(T) ); + mesh->UnlockVertexBuffer(); + } + + { + void* ib; + mesh->LockIndexBuffer(0, &ib); + pin_ptr t = &indices[0]; + memcpy( ib, t, indices->Length * sizeof(short) ); + mesh->UnlockIndexBuffer(); + } + + { + DWORD* ab; + mesh->LockAttributeBuffer(0, &ab); + pin_ptr t = &attributes[0]; + memcpy( ab, t, attributes->Length * sizeof(int) ); + mesh->UnlockAttributeBuffer(); + } + + DWORD* adjacency = new DWORD[ indices->Length ]; + mesh->GenerateAdjacency(1e-3f, adjacency); + mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT, adjacency, NULL, NULL, NULL); + delete[] adjacency; + } + + void DrawSubset( int attributeId ) + { + mesh->DrawSubset( attributeId ); + } + + ~Mesh() + { + safe_release( mesh ); + } + }; +}} diff --git a/BluntDx/MouseState.h b/BluntDx/MouseState.h new file mode 100644 index 0000000000..b930f565c7 --- /dev/null +++ b/BluntDx/MouseState.h @@ -0,0 +1,67 @@ +#pragma once + +namespace BluntDirectX { namespace DirectInput { + + value class MouseData + { + public: + long x; + long y; + long z; + unsigned char left, right, middle, aux; + }; + + public ref class MouseState + { + private: + MouseData d; + + internal: + MouseState( MouseData d ) : d(d) {} + + public: + property bool default[ int ] + { + bool get( int button ) + { + unsigned char value = 0; + switch( button ) + { + case 0: value = d.left; break; + case 1: value = d.right; break; + case 2: value = d.middle; break; + case 3: value = d.aux; break; + default: + throw gcnew System::Exception("you idiot"); + } + + return (value & 0x80) != 0; + } + } + + property int X + { + int get() + { + return (int)d.x; + } + } + + property int Y + { + int get() + { + return (int)d.y; + } + } + + property int Z + { + int get() + { + return (int)d.z; + } + } + }; + +}} \ No newline at end of file diff --git a/BluntDx/SpriteHelper.h b/BluntDx/SpriteHelper.h new file mode 100644 index 0000000000..da72a34d2f --- /dev/null +++ b/BluntDx/SpriteHelper.h @@ -0,0 +1,64 @@ +#pragma once + +namespace BluntDirectX { namespace Direct3D +{ + public ref class SpriteHelper + { + internal: + ID3DXSprite* sprite; + + public: + SpriteHelper( GraphicsDevice^ device ) + { + HRESULT hr; + ID3DXSprite* s; + + if (FAILED( + hr = D3DXCreateSprite( device->device, &s ))) + ThrowHelper::Hr( hr ); + + sprite = s; + } + + void SetTransform( float sx, float sy, float tx, float ty ) + { + D3DXMATRIX m; + memset( &m, 0, sizeof(m)); + m._11 = sx; m._22 = sy; m._33 = 1; m._44 = 1; + m._41 = tx; m._42 = ty; + + sprite->SetTransform(&m); + } + + void Begin() + { + sprite->Begin( D3DXSPRITE_ALPHABLEND ); + } + + void End() + { + sprite->End(); + } + + void Flush() + { + sprite->Flush(); + } + + void Draw( Texture^ texture, int left, int top, int width, int height, int color ) + { + RECT r = { left, top, width + left, height + top }; + sprite->Draw( (IDirect3DTexture9*)texture->texture, &r, NULL, NULL, color ); + } + + void Draw( Texture^ texture, int color ) + { + sprite->Draw( (IDirect3DTexture9*)texture->texture, NULL, NULL, NULL, color ); + } + + ~SpriteHelper() + { + safe_release( sprite ); + } + }; +}} diff --git a/BluntDx/Texture.h b/BluntDx/Texture.h new file mode 100644 index 0000000000..b03b73864c --- /dev/null +++ b/BluntDx/Texture.h @@ -0,0 +1,49 @@ +#pragma once + +namespace BluntDirectX { namespace Direct3D +{ + public ref class Texture + { + private: + Texture( IDirect3DBaseTexture9* texture ) : texture(texture) {} + + internal: + IDirect3DBaseTexture9* texture; + + public: + static Texture^ Create( Stream^ stream, GraphicsDevice^ device ) + { + stream->Position = 0; + array^ data = gcnew array( (int)stream->Length ); + stream->Read( data, 0, data->Length ); + + HRESULT hr; + IDirect3DBaseTexture9* tex; + + pin_ptr p = &data[0]; + + if (FAILED( hr = D3DXCreateTextureFromFileInMemory( device->device, p, data->Length, (IDirect3DTexture9**)&tex ) )) + throw gcnew InvalidOperationException("Texture load failed"); + + return gcnew Texture( tex ); + } + + static Texture^ CreateCube( Stream^ stream, GraphicsDevice^ device ) + { + stream->Position = 0; + array^ data = gcnew array((int)stream->Length); + stream->Read( data, 0, data->Length ); + + HRESULT hr; + IDirect3DBaseTexture9* tex; + + pin_ptr p = &data[0]; + + if (FAILED( hr = D3DXCreateCubeTextureFromFileInMemory( device->device, p, data->Length, (IDirect3DCubeTexture9**)&tex ) )) + throw gcnew InvalidOperationException("Texture load failed"); + + return gcnew Texture( tex ); + } + }; +} +} \ No newline at end of file diff --git a/BluntDx/Utilities.h b/BluntDx/Utilities.h new file mode 100644 index 0000000000..5d4c5fde68 --- /dev/null +++ b/BluntDx/Utilities.h @@ -0,0 +1,15 @@ +#pragma once + +#define safe_release(x) if(x) { (x)->Release(); x = NULL; } + +namespace BluntDirectX +{ + ref class ThrowHelper + { + public: + static void Hr( HRESULT hr ) + { + throw gcnew InvalidOperationException( String::Format("COM error in DirectX, hr={0}", hr) ); + } + }; +} \ No newline at end of file diff --git a/BluntDx/VertexBuffer.h b/BluntDx/VertexBuffer.h new file mode 100644 index 0000000000..0359a5bb63 --- /dev/null +++ b/BluntDx/VertexBuffer.h @@ -0,0 +1,161 @@ +#pragma once + +namespace BluntDirectX { namespace Direct3D +{ + public ref class IndexBuffer + { + internal: + IDirect3DIndexBuffer9* buffer; + IDirect3DDevice9* device; + int size; + + public: + IndexBuffer( GraphicsDevice^ device, int size ) + : size( size ), device( device->device ) + { + HRESULT hr; + IDirect3DIndexBuffer9* b; + + if (FAILED( hr = this->device->CreateIndexBuffer( sizeof( unsigned short ) * size, + device->HasHardwareVP ? 0 : D3DUSAGE_SOFTWAREPROCESSING, D3DFMT_INDEX16, D3DPOOL_SYSTEMMEM, &b, NULL ))) + ThrowHelper::Hr(hr); + + buffer = b; + } + + void SetData( array^ data ) + { + pin_ptr pdata = &data[0]; + void * ib; + + buffer->Lock( 0, sizeof(unsigned short) * size, &ib, D3DLOCK_DISCARD ); + memcpy( ib, pdata, sizeof(unsigned short) * size ); + buffer->Unlock(); + } + + void Bind() + { + device->SetIndices( buffer ); + } + + ~IndexBuffer() + { + safe_release( buffer ); + } + + property int Size { int get() { return size; } } + }; + + generic where T : value class + public ref class FvfVertexBuffer + { + internal: + IDirect3DVertexBuffer9* buffer; + IDirect3DDevice9* device; + int numVertices; + unsigned int fvf; + + public: + FvfVertexBuffer( GraphicsDevice^ device, int numVertices, VertexFormat fvf ) + : numVertices( numVertices ), device(device->device), fvf((unsigned int)fvf) + { + HRESULT hr; + IDirect3DVertexBuffer9* b; + + if (FAILED( hr = device->device->CreateVertexBuffer( sizeof(T) * numVertices, + device->HasHardwareVP ? 0 : D3DUSAGE_SOFTWAREPROCESSING, this->fvf, D3DPOOL_SYSTEMMEM, &b, NULL ))) + ThrowHelper::Hr(hr); + + buffer = b; + } + + void SetData( array^ data ) + { + pin_ptr pdata = &data[0]; + void* vb; + + buffer->Lock( 0, sizeof(T) * numVertices, &vb, D3DLOCK_DISCARD ); + memcpy( vb, pdata, sizeof(T) * data->Length ); + buffer->Unlock(); + } + + void Bind( int stream ) + { + device->SetStreamSource( stream, buffer, 0, sizeof(T) ); + device->SetFVF( fvf ); + } + + ~FvfVertexBuffer() + { + safe_release( buffer ); + } + + property int Size { int get() { return numVertices; } } + property VertexFormat FVF { VertexFormat get() { return (VertexFormat)fvf; }} + }; + + generic where T : value class + public ref class VertexBuffer + { + internal: + IDirect3DVertexBuffer9* buffer; + IDirect3DVertexDeclaration9* decl; + IDirect3DDevice9* device; + int numVertices; + + public: + VertexBuffer( GraphicsDevice^ device, int numVertices ) + : numVertices( numVertices ), device(device->device) + { + HRESULT hr; + IDirect3DVertexBuffer9* b; + IDirect3DVertexDeclaration9* d; + + D3DVERTEXELEMENT9 elements[] = + { + {0,0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0,12,D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,0}, + {0,28,D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,1}, + {0,44,D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_PSIZE,0}, + + D3DDECL_END() + }; + + if (FAILED( hr = device->device->CreateVertexDeclaration( elements, &d ) )) + ThrowHelper::Hr(hr); + + decl = d; + + if (FAILED( hr = device->device->CreateVertexBuffer( sizeof(T) * numVertices, + D3DUSAGE_DYNAMIC | D3DUSAGE_POINTS | + (device->HasHardwareVP ? 0 : D3DUSAGE_SOFTWAREPROCESSING), 0, D3DPOOL_DEFAULT, &b, NULL ))) + ThrowHelper::Hr(hr); + + buffer = b; + } + + void SetData( array^ data ) + { + pin_ptr pdata = &data[0]; + void* vb; + + buffer->Lock( 0, sizeof(T) * numVertices, &vb, D3DLOCK_DISCARD ); + memcpy( vb, pdata, sizeof(T) * data->Length ); + buffer->Unlock(); + } + + void Bind( int stream ) + { + device->SetStreamSource( stream, buffer, 0, sizeof(T) ); + device->SetVertexDeclaration( decl ); + } + + ~VertexBuffer() + { + safe_release( decl ); + safe_release( buffer ); + } + + property int Size { int get() { return numVertices; } } + }; +}} \ No newline at end of file