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