#ifndef TGL_D3DRM_IMPL_H
#define TGL_D3DRM_IMPL_H

#include "compat.h"
#include "decomp.h"
#include "tgl/tgl.h"

#ifdef MINIWIN
#include "miniwin/d3drm.h"
typedef void* LPD3DRM_APPDATA;
#else
#include <d3drm.h>

typedef DWORD LPD3DRM_APPDATA;
#endif

// Forward declare D3D types
struct IDirect3DRM2;
struct IDirect3DRMDevice2;
struct IDirect3DRMViewport;
struct IDirect3DRMFrame2;
struct IDirect3DRMMesh;
struct IDirect3DRMMeshBuilder;
struct IDirect3DRMTexture;

namespace TglImpl
{

using namespace Tgl;

// Utility function used by implementations
// FUNCTION: BETA10 0x10169cf0
inline Result ResultVal(HRESULT result)
{
	return SUCCEEDED(result) ? Success : Error;
}

// Forward declare implementations
class RendererImpl;
class DeviceImpl;
class ViewImpl;
class LightImpl;
class CameraImpl;
class GroupImpl;
class MeshImpl;
class TextureImpl;
class MeshBuilderImpl;

// VTABLE: LEGO1 0x100db910
// VTABLE: BETA10 0x101c30d8
class RendererImpl : public Renderer {
public:
	// FUNCTION: BETA10 0x10169a20
	RendererImpl() : m_data(0) {}

	// FUNCTION: BETA10 0x10169d20
	~RendererImpl() override { Destroy(); }

	void* ImplementationDataPtr() override;

	// vtable+0x08
	Device* CreateDevice(const DeviceDirectDrawCreateData&) override;
	Device* CreateDevice(const DeviceDirect3DCreateData&) override;

	// vtable+0x10
	View* CreateView(
		const Device*,
		const Camera*,
		unsigned int x,
		unsigned int y,
		unsigned int width,
		unsigned int height
	) override;
	Camera* CreateCamera() override;
	Light* CreateLight(LightType, float r, float g, float b) override;
	Group* CreateGroup(const Group* pParent) override;

	// vtable+0x20
	MeshBuilder* CreateMeshBuilder() override;
	Texture* CreateTexture(
		int width,
		int height,
		int bitsPerTexel,
		const void* pTexels,
		int pTexelsArePersistent,
		int paletteEntryCount,
		const PaletteEntry* pEntries
	) override;
	Texture* CreateTexture() override;

	Result SetTextureDefaultShadeCount(unsigned int) override;

	// vtable+0x30
	Result SetTextureDefaultColorCount(unsigned int) override;

	HRESULT CreateTextureFromSurface(LPDIRECTDRAWSURFACE pSurface, LPDIRECT3DRMTEXTURE2* pTexture2)
	{
		return m_data->CreateTextureFromSurface(pSurface, pTexture2);
	}

	typedef IDirect3DRM2* RendererDataType;

	const RendererDataType& ImplementationData() const { return m_data; }

	// FUNCTION: BETA10 0x10174c10
	RendererDataType& ImplementationData() { return m_data; }

public:
	inline Result Create();
	inline void Destroy();
	inline Result CreateLight(LightType type, float r, float g, float b, LightImpl& rLight);
	inline Result CreateGroup(const GroupImpl* pParentGroup, GroupImpl& rpGroup);
	inline Result CreateView(
		const DeviceImpl& rDevice,
		const CameraImpl& rCamera,
		unsigned int x,
		unsigned int y,
		unsigned int width,
		unsigned int height,
		ViewImpl& rView
	);
	inline Result CreateMeshBuilder(MeshBuilderImpl& rMesh);
	inline Result CreateCamera(CameraImpl& rCamera);
	inline Result CreateTexture(TextureImpl& rTexture);
	inline Result CreateTexture(
		TextureImpl& rTexture,
		int width,
		int height,
		int bitsPerTexel,
		const void* pTexels,
		int texelsArePersistent,
		int paletteEntryCount,
		const PaletteEntry* pEntries
	);
	inline Result CreateDevice(const DeviceDirect3DCreateData& rCreateData, DeviceImpl& rDevice);
	inline Result CreateDevice(const DeviceDirectDrawCreateData& rCreateData, DeviceImpl& rDevice);

private:
	RendererDataType m_data;
};

extern IDirect3DRM2* g_pD3DRM;

// FUNCTION: BETA10 0x1016dd20
inline void RendererDestroy(IDirect3DRM2* pRenderer)
{
	int refCount = pRenderer->Release();
	if (refCount <= 0) {
		g_pD3DRM = NULL;
	}
}

// Inlined only
// FUNCTION: BETA10 0x1016dce0
void RendererImpl::Destroy()
{
	if (m_data) {
		RendererDestroy(m_data);
		m_data = NULL;
	}
}

// VTABLE: LEGO1 0x100db988
// VTABLE: BETA10 0x101c31f0
class DeviceImpl : public Device {
public:
	// FUNCTION: BETA10 0x1016b2e0
	DeviceImpl() : m_data(0) {}

	// FUNCTION: BETA10 0x1016dd80
	~DeviceImpl() override { Destroy(); }

	void* ImplementationDataPtr() override;

	// vtable+0x08
	unsigned int GetWidth() override;
	unsigned int GetHeight() override;

	// vtable+0x10
	Result SetColorModel(ColorModel) override;
	Result SetShadingModel(ShadingModel) override;
	Result SetShadeCount(unsigned int) override;
	Result SetDither(int) override;

	// vtable+0x20
	Result Update() override;
	void HandleActivate(WORD) override;
	void HandlePaint(void*) override;

	typedef IDirect3DRMDevice2* DeviceDataType;

	// FUNCTION: BETA10 0x101708e0
	const DeviceDataType& ImplementationData() const { return m_data; }

	// FUNCTION: BETA10 0x100d9540
	DeviceDataType& ImplementationData() { return m_data; }

	void SetImplementationData(IDirect3DRMDevice2* device) { m_data = device; }

	inline void Destroy();

	friend class RendererImpl;

private:
	DeviceDataType m_data;
};

// FUNCTION: BETA10 0x101708c0
inline void DeviceDestroy(IDirect3DRMDevice2* pDevice)
{
	pDevice->Release();
}

// FUNCTION: BETA10 0x10170880
void DeviceImpl::Destroy()
{
	if (m_data) {
		DeviceDestroy(m_data);
		m_data = NULL;
	}
}

// VTABLE: LEGO1 0x100db9e8
// VTABLE: BETA10 0x101c3220
class ViewImpl : public View {
public:
	// FUNCTION: BETA10 0x1016b360
	ViewImpl() : m_data(0) {}

	// FUNCTION: BETA10 0x1016e5d0
	~ViewImpl() override { Destroy(); }

	void* ImplementationDataPtr() override;

	// vtable+0x08
	Result Add(const Light*) override;
	Result Remove(const Light*) override;

	// vtable+0x10
	Result SetCamera(const Camera*) override;
	Result SetProjection(ProjectionType) override;
	Result SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees) override;
	Result SetBackgroundColor(float r, float g, float b) override;

	// vtable+0x20
	Result GetBackgroundColor(float* r, float* g, float* b) override;
	Result Clear() override;
	Result Render(const Group*) override;
	Result ForceUpdate(unsigned int x, unsigned int y, unsigned int width, unsigned int height) override;

	// vtable+0x30
	Result TransformWorldToScreen(const float world[3], float screen[4]) override;
	Result TransformScreenToWorld(const float screen[4], float world[3]) override;
	Result Pick(
		int x,
		int y,
		const Group** ppGroupsToPickFrom,
		int groupsToPickFromCount,
		const Group**& rppPickedGroups,
		int& rPickedGroupCount
	) override;

	typedef IDirect3DRMViewport* ViewDataType;

	const ViewDataType& ImplementationData() const { return m_data; }

	// FUNCTION: BETA10 0x101711c0
	ViewDataType& ImplementationData() { return m_data; }

	void SetImplementationData(IDirect3DRMViewport* viewport) { m_data = viewport; }

	static Result ViewportCreateAppData(IDirect3DRM2*, IDirect3DRMViewport*, IDirect3DRMFrame2*);

	inline void Destroy();
	Result Add(const LightImpl& rLight);
	Result Remove(const LightImpl& rLight);
	Result SetCamera(const CameraImpl& rCamera);
	Result Render(const GroupImpl& rScene);
	Result Pick(
		int x,
		int y,
		const GroupImpl** ppGroupsToPickFrom,
		int groupsToPickFromCount,
		const Group**& rppPickedGroups,
		int& rPickedGroupCount
	);

	friend class RendererImpl;

private:
	ViewDataType m_data;
};

// FUNCTION: BETA10 0x101711a0
inline void ViewDestroy(IDirect3DRMViewport* pView)
{
	pView->Release();
}

// FUNCTION: BETA10 0x10171160
void ViewImpl::Destroy()
{
	if (m_data) {
		ViewDestroy(m_data);
		m_data = NULL;
	}
}

// VTABLE: LEGO1 0x100dbad8
// VTABLE: BETA10 0x101c3260
class CameraImpl : public Camera {
public:
	// FUNCTION: BETA10 0x1016b3e0
	CameraImpl() : m_data(0) {}

	// FUNCTION: BETA10 0x1016f200
	~CameraImpl() override { Destroy(); }

	void* ImplementationDataPtr() override;

	// vtable+0x08
	Result SetTransformation(FloatMatrix4&) override;

	typedef IDirect3DRMFrame2* CameraDataType;

	// FUNCTION: BETA10 0x10170960
	const CameraDataType& ImplementationData() const { return m_data; }

	// FUNCTION: BETA10 0x10170980
	CameraDataType& ImplementationData() { return m_data; }

	inline void Destroy();

	friend class RendererImpl;

private:
	CameraDataType m_data;
};

// FUNCTION: BETA10 0x10170940
inline void CameraDestroy(IDirect3DRMFrame2* pFrame)
{
	pFrame->Release();
}

// FUNCTION: BETA10 0x10170900
void CameraImpl::Destroy()
{
	if (m_data) {
		CameraDestroy(m_data);
		m_data = NULL;
	}
}

// VTABLE: LEGO1 0x100dbaf8
// VTABLE: BETA10 0x101c3270
class LightImpl : public Light {
public:
	// FUNCTION: BETA10 0x1016b460
	LightImpl() : m_data(0) {}

	// FUNCTION: BETA10 0x1016f5c0
	~LightImpl() override { Destroy(); }

	void* ImplementationDataPtr() override;

	// vtable+0x08
	Result SetTransformation(FloatMatrix4&) override;
	Result SetColor(float r, float g, float b) override;

	typedef IDirect3DRMFrame2* LightDataType;

	// FUNCTION: BETA10 0x10171b90
	const LightDataType& ImplementationData() const { return m_data; }

	// FUNCTION: BETA10 0x10171240
	LightDataType& ImplementationData() { return m_data; }

	inline void Destroy();

	friend class RendererImpl;

private:
	LightDataType m_data;
};

// FUNCTION: BETA10 0x10171220
inline void LightDestroy(IDirect3DRMFrame2* pLight)
{
	pLight->Release();
}

// FUNCTION: BETA10 0x101711e0
void LightImpl::Destroy()
{
	if (m_data) {
		LightDestroy(m_data);
		m_data = NULL;
	}
}

// VTABLE: LEGO1 0x100dbb88
// VTABLE: BETA10 0x101c3340
class MeshImpl : public Mesh {
public:
	// FUNCTION: BETA10 0x1016f970
	MeshImpl() : m_data(0) {}

	// FUNCTION: BETA10 0x10170460
	~MeshImpl() override { Destroy(); }

	void* ImplementationDataPtr() override;

	// vtable+0x08
	Result SetColor(float r, float g, float b, float a) override;
	Result SetTexture(const Texture*) override;

	// vtable+0x10
	Result GetTexture(Texture*&) override;
	Result SetTextureMappingMode(TextureMappingMode) override;
	Result SetShadingModel(ShadingModel) override;
	Mesh* DeepClone(MeshBuilder*) override;

	// vtable+0x20
	Mesh* ShallowClone(MeshBuilder*) override;

	struct MeshData {
		IDirect3DRMMesh* groupMesh;
		D3DRMGROUPINDEX groupIndex;
	};

	typedef MeshData* MeshDataType;

	const MeshDataType& ImplementationData() const { return m_data; }

	// FUNCTION: BETA10 0x10171b70
	MeshDataType& ImplementationData() { return m_data; }

	inline void Destroy();
	inline Mesh* DeepClone(const MeshBuilderImpl& rMesh);
	inline Result GetTexture(TextureImpl** ppTexture);
	inline Result SetTexture(const TextureImpl* pTexture);
	inline Mesh* ShallowClone(const MeshBuilderImpl& rMesh);

	friend class RendererImpl;

private:
	MeshDataType m_data;
};

// FUNCTION: BETA10 0x10171b40
inline void MeshDestroy(MeshImpl::MeshDataType pMesh)
{
	delete pMesh;
}

// FUNCTION: BETA10 0x10171b00
void MeshImpl::Destroy()
{
	if (m_data) {
		MeshDestroy(m_data);
		m_data = NULL;
	}
}

// VTABLE: LEGO1 0x100dba68
// VTABLE: BETA10 0x101c3150
class GroupImpl : public Group {
public:
	// FUNCTION: BETA10 0x1016a240
	GroupImpl() : m_data(0) {}

	// FUNCTION: BETA10 0x1016a410
	~GroupImpl() override { Destroy(); }

	void* ImplementationDataPtr() override;

	// vtable+0x08
	Result SetTransformation(FloatMatrix4&) override;
	Result SetColor(float r, float g, float b, float a) override;

	// vtable+0x10
	Result SetTexture(const Texture*) override;
	Result GetTexture(Texture*&) override;
	Result SetMaterialMode(MaterialMode) override;
	Result Add(const Group*) override;

	// vtable+0x20
	Result Add(const MeshBuilder*) override;
	Result Remove(const Group*) override;
	Result Remove(const MeshBuilder*) override;
	Result RemoveAll() override;

	// vtable+0x30
	Result Bounds(D3DVECTOR* p_min, D3DVECTOR* p_max) override;

	typedef IDirect3DRMFrame2* GroupDataType;

	// FUNCTION: BETA10 0x1016fc20
	const GroupDataType& ImplementationData() const { return m_data; }

	// FUNCTION: BETA10 0x1016fce0
	GroupDataType& ImplementationData() { return m_data; }

	inline void Destroy();
	inline Result SetTexture(const TextureImpl* pTexture);
	inline Result GetTexture(TextureImpl** ppTexture);
	inline Result Add(const GroupImpl& rGroup);
	inline Result Add(const MeshBuilderImpl& rMesh);
	inline Result Remove(const GroupImpl& rGroup);
	inline Result Remove(const MeshBuilderImpl& rMesh);

	friend class RendererImpl;

private:
	GroupDataType m_data;
};

// FUNCTION: BETA10 0x1016c2b0
inline void GroupDestroy(IDirect3DRMFrame2* pGroup)
{
	pGroup->Release();
}

// FUNCTION: BETA10 0x1016c270
void GroupImpl::Destroy()
{
	if (m_data) {
		GroupDestroy(m_data);
		m_data = NULL;
	}
}

// VTABLE: LEGO1 0x100dbb18
// VTABLE: BETA10 0x101c31e0
class MeshBuilderImpl : public MeshBuilder {
public:
	// FUNCTION: BETA10 0x1016b260
	MeshBuilderImpl() : m_data(0) {}

	// FUNCTION: BETA10 0x1016c7e0
	~MeshBuilderImpl() override { Destroy(); }

	void* ImplementationDataPtr() override;

	// vtable+0x08
	Mesh* CreateMesh(
		unsigned int faceCount,
		unsigned int vertexCount,
		float (*pPositions)[3],
		float (*pNormals)[3],
		float (*pTextureCoordinates)[2],
		unsigned int (*pFaceIndices)[3],
		unsigned int (*pTextureIndices)[3],
		ShadingModel shadingModel
	) override;
	Result GetBoundingBox(float min[3], float max[3]) const override;

	// vtable+0x10
	MeshBuilder* Clone() override;

	typedef IDirect3DRMMesh* MeshBuilderDataType;

	// FUNCTION: BETA10 0x10170420
	const MeshBuilderDataType& ImplementationData() const { return m_data; }

	// FUNCTION: BETA10 0x10170440
	MeshBuilderDataType& ImplementationData() { return m_data; }

	inline void Destroy();

	friend class RendererImpl;

private:
	inline Result CreateMeshImpl(
		MeshImpl* pMeshImpl,
		unsigned int faceCount,
		unsigned int vertexCount,
		float (*pPositions)[3],
		float (*pNormals)[3],
		float (*pTextureCoordinates)[2],
		unsigned int (*pFaceIndices)[3],
		unsigned int (*pTextureIndices)[3],
		ShadingModel shadingModel
	);

	MeshBuilderDataType m_data;
};

// FUNCTION: BETA10 0x10170390
inline void MeshBuilderDestroy(IDirect3DRMMesh* pMeshBuilder)
{
	pMeshBuilder->Release();
}

// FUNCTION: BETA10 0x10170350
void MeshBuilderImpl::Destroy()
{
	if (m_data) {
		MeshBuilderDestroy(m_data);
		m_data = NULL;
	}
}

// No vtable, this is just a simple wrapper around D3DRMIMAGE
class TglD3DRMIMAGE {
public:
	TglD3DRMIMAGE(
		int width,
		int height,
		int depth,
		void* pBuffer,
		int useBuffer,
		int paletteSize,
		PaletteEntry* pEntries
	);
	~TglD3DRMIMAGE();

	Result CreateBuffer(int width, int height, int depth, void* pBuffer, int useBuffer);
	void Destroy();
	Result FillRowsOfTexture(int y, int height, char* content);
	Result InitializePalette(int paletteSize, PaletteEntry* pEntries);

	D3DRMIMAGE m_image;
	int m_texelsAllocatedByClient;

	// SYNTHETIC: BETA10 0x1016abb0
	// TglImpl::TglD3DRMIMAGE::`scalar deleting destructor'
};

// VTABLE: LEGO1 0x100dbb48
// VTABLE: BETA10 0x101c31c0
class TextureImpl : public Texture {
public:
	// FUNCTION: BETA10 0x1016b1e0
	TextureImpl() : m_data(0) {}

	// FUNCTION: BETA10 0x1016c2d0
	~TextureImpl() override { Destroy(); }

	void* ImplementationDataPtr() override;

	// vtable+0x08
	Result SetTexels(int width, int height, int bitsPerTexel, void* pTexels, int pTexelsArePersistent) override;
	void FillRowsOfTexture(int y, int height, void* pBuffer) override;

	// vtable+0x10
	Result Changed(int texelsChanged, int paletteChanged) override;
	Result GetBufferAndPalette(
		int* pWidth,
		int* pHeight,
		int* pDepth,
		void** ppBuffer,
		int* ppPaletteSize,
		unsigned char (*pEntries)[3]
	) override;
	Result SetPalette(int entryCount, PaletteEntry* entries) override;

	typedef IDirect3DRMTexture* TextureDataType;

	// FUNCTION: BETA10 0x1016fd60
	const TextureDataType& ImplementationData() const { return m_data; }

	// FUNCTION: BETA10 0x1016fe20
	TextureDataType& ImplementationData() { return m_data; }

	void SetImplementation(IDirect3DRMTexture* pData) { m_data = pData; }

	inline void Destroy();

	friend class RendererImpl;

	static Result SetImage(IDirect3DRMTexture* pSelf, TglD3DRMIMAGE* pImage);

private:
	TextureDataType m_data;
};

// FUNCTION: BETA10 0x1016fd40
inline void TextureDestroy(IDirect3DRMTexture* pTexture)
{
	pTexture->Release();
}

// FUNCTION: BETA10 0x1016fd00
void TextureImpl::Destroy()
{
	if (m_data) {
		TextureDestroy(m_data);
		m_data = NULL;
	}
}

// Used by both Mesh and MeshBuilder
// FUNCTION: BETA10 0x10170270
inline Result MeshSetTextureMappingMode(MeshImpl::MeshData* pMesh, TextureMappingMode mode)
{
	if (mode == PerspectiveCorrect) {
		return ResultVal(pMesh->groupMesh->SetGroupMapping(pMesh->groupIndex, D3DRMMAP_PERSPCORRECT));
	}
	else {
		return ResultVal(pMesh->groupMesh->SetGroupMapping(pMesh->groupIndex, D3DRMMAP_NONE));
	}
}

// Translation helpers
// FUNCTION: BETA10 0x1016fc40
inline D3DRMRENDERQUALITY Translate(ShadingModel tglShadingModel)
{
	D3DRMRENDERQUALITY renderQuality;

	switch (tglShadingModel) {
	case Wireframe:
		renderQuality = D3DRMRENDER_WIREFRAME;
		break;
	case UnlitFlat:
		renderQuality = D3DRMRENDER_UNLITFLAT;
		break;
	case Flat:
		renderQuality = D3DRMRENDER_FLAT;
		break;
	case Gouraud:
		renderQuality = D3DRMRENDER_GOURAUD;
		break;
	case Phong:
		renderQuality = D3DRMRENDER_PHONG;
		break;
	default:
		renderQuality = D3DRMRENDER_FLAT;
		break;
	}

	return renderQuality;
}

// FUNCTION: BETA10 0x101703b0
inline D3DRMPROJECTIONTYPE Translate(ProjectionType tglProjectionType)
{
	D3DRMPROJECTIONTYPE projectionType;
	switch (tglProjectionType) {
	case Perspective:
		projectionType = D3DRMPROJECT_PERSPECTIVE;
		break;
	case Orthographic:
		projectionType = D3DRMPROJECT_ORTHOGRAPHIC;
		break;
	default:
		projectionType = D3DRMPROJECT_PERSPECTIVE;
		break;
	}
	return projectionType;
}

// Yes this function serves no purpose, originally they intended it to
// convert from doubles to floats but ended up using floats throughout
// the software stack.
// FUNCTION: BETA10 0x1016fa10
inline D3DRMMATRIX4D* Translate(FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DRMMatrix4x4)
{
	for (int i = 0; i < (sizeof(rD3DRMMatrix4x4) / sizeof(rD3DRMMatrix4x4[0])); i++) {
		for (int j = 0; j < (sizeof(rD3DRMMatrix4x4[0]) / sizeof(rD3DRMMatrix4x4[0][0])); j++) {
			rD3DRMMatrix4x4[i][j] = D3DVAL(tglMatrix4x4[i][j]);
		}
	}
	return &rD3DRMMatrix4x4;
}

// FUNCTION: BETA10 0x1016fba0
inline D3DVECTOR* Translate(const float tglVector[3], D3DVECTOR& rD3DVector)
{
	rD3DVector.x = D3DVAL(tglVector[0]);
	rD3DVector.y = D3DVAL(tglVector[1]);
	rD3DVector.z = D3DVAL(tglVector[2]);

	return &rD3DVector;
}

// FUNCTION: BETA10 0x1016fd80
inline D3DRMLIGHTTYPE Translate(LightType tglLightType)
{
	D3DRMLIGHTTYPE lightType;

	// ??? use lookup table
	switch (tglLightType) {
	case Ambient:
		lightType = D3DRMLIGHT_AMBIENT;
		break;
	case Point:
		lightType = D3DRMLIGHT_POINT;
		break;
	case Spot:
		lightType = D3DRMLIGHT_SPOT;
		break;
	case Directional:
		lightType = D3DRMLIGHT_DIRECTIONAL;
		break;
	case ParallelPoint:
		lightType = D3DRMLIGHT_PARALLELPOINT;
		break;
	default:
		lightType = D3DRMLIGHT_AMBIENT;
		break;
	}

	return lightType;
}

// FUNCTION: BETA10 0x101702e0
inline D3DRMMATERIALMODE Translate(MaterialMode mode)
{
	D3DRMMATERIALMODE d3dMode;
	switch (mode) {
	case FromParent:
		d3dMode = D3DRMMATERIAL_FROMPARENT;
		break;
	case FromFrame:
		d3dMode = D3DRMMATERIAL_FROMFRAME;
		break;
	case FromMesh:
		d3dMode = D3DRMMATERIAL_FROMMESH;
		break;
	}
	return d3dMode;
}

} /* namespace TglImpl */

// SYNTHETIC: LEGO1 0x100a16d0
// SYNTHETIC: BETA10 0x10169aa0
// TglImpl::RendererImpl::`scalar deleting destructor'

// SYNTHETIC: LEGO1 0x100a22c0
// SYNTHETIC: BETA10 0x1016b700
// TglImpl::DeviceImpl::`scalar deleting destructor'

// SYNTHETIC: LEGO1 0x100a23a0
// SYNTHETIC: BETA10 0x1016b810
// TglImpl::ViewImpl::`scalar deleting destructor'

// SYNTHETIC: LEGO1 0x100a2480
// SYNTHETIC: BETA10 0x1016a2c0
// TglImpl::GroupImpl::`scalar deleting destructor'

// SYNTHETIC: LEGO1 0x100a2560
// SYNTHETIC: BETA10 0x1016b920
// TglImpl::CameraImpl::`scalar deleting destructor'

// SYNTHETIC: LEGO1 0x100a2640
// SYNTHETIC: BETA10 0x1016ba30
// TglImpl::LightImpl::`scalar deleting destructor'

// SYNTHETIC: LEGO1 0x100a2720
// SYNTHETIC: BETA10 0x1016b5f0
// TglImpl::MeshBuilderImpl::`scalar deleting destructor'

// SYNTHETIC: LEGO1 0x100a2800
// SYNTHETIC: BETA10 0x1016b4e0
// TglImpl::TextureImpl::`scalar deleting destructor'

// SYNTHETIC: LEGO1 0x100a3d80
// SYNTHETIC: BETA10 0x1016fa90
// TglImpl::MeshImpl::`scalar deleting destructor'

// SYNTHETIC: BETA10 0x10169960
// ViewportAppData::`scalar deleting destructor'

// GLOBAL: LEGO1 0x100dd1e0
// IID_IDirect3DRMMeshBuilder

// GLOBAL: LEGO1 0x100dd1f0
// IID_IDirect3DRMMesh

#endif
