
// zlib open source license
//
// Copyright (c) 2010 to 2013 David Forsgren Piuva
// 
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// 
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 
//    1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
// 
//    2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
// 
//    3. This notice may not be removed or altered from any source
//    distribution.

#pragma once

// Includes

#include "..\GlobalConstants.h"

// Standard Windows includes
#include <windows.h>
#include <initguid.h>
#include <assert.h>
#include <wchar.h>
#include <mmsystem.h>
#include <commctrl.h>
#include <shellapi.h>
#include <new.h>
#include <shlobj.h>
#include <math.h>
#include <limits.h>
#include <stdio.h>

// Macros

#define FileExist(FILENAME) (::GetFileAttributesW(FILENAME) != 0xFFFFFFFF)

#define COLLECTION_STRUCT_DATA(NAME) int Index; int useCount; int ID; NAME##_Struct* NextGarbage;
#define COLLECTION_STRUCT_DATA_RESOURCE wchar_t FileName[260]; bool Locked;

// Constant buffers

struct LightSource {
	int Type; DVector3 Pos;
	float Radius; DVector3 Color;
	DVector3 XAxis; float WidthSlope;
	DVector3 YAxis; float HeightSlope;
	DVector3 ZAxis; float NearClip; //Radius = FarClip when rendering shadows
	DVector4 TextureAtlasRect;
	DVector4 DepthAtlasRect;
	DVector2 ZWCorrection; float ShadowOffset; float ShadowTransparency; //ZWCorrection = (outside intensity, fade size) when orthogonal
};

struct CBEveryRender {
	DMatrix mWorldToCamera_NoRefraction;
	DMatrix mWorldToCamera;
	DMatrix mCameraToImage;
	DMatrix mWorldToImage; //mWorldToCamera * mCameraToImage
	DVector3 CameraPos_WorldSpace; // X,Y,Z
	float EnableCuttingPlane; // 0 = no cutting plane, 1 = cut on negative side
	DVector4 CuttingPlane; // DX, DY, DZ, Offset
	DVector4 FogColor; // R,G,B,A
	DVector4 SceneSettingsA; // MaxDepth/FarClip,FogIntensity,NearClip,?
	DVector3 AmbientLight; int NumberOfLights;
	LightSource Lights[MaxNumberOfLights];
	DVector2 Dimensions; float GlobalTime; float Padding_EveryRender;
};

struct CBEveryObject {
	DMatrix mObjectToWorld;
	DVector4 Color;
	int BoneBuffer; float DetailLevel; DVector2 Padding_EveryObject;
};

struct CBEveryDebugRender {
	DMatrix mWorldToImage;
};

struct CBArgBuffer {
	DVector4 UserProperties_Instance[NumberOfUserVectorsPerInstance];
};

struct SingleBone {
	DVector4 Start; // Content in xyz and UserData.x in w
	DVector4 YAxis; // Content in xyz and UserData.y in w
	DVector4 ZAxis; // Content in xyz and UserData.z in w
};

struct CBBoneFrame_8 {
	SingleBone Bone[8];
};
struct CBBoneFrame_16 {
	SingleBone Bone[16];
};
struct CBBoneFrame_32 {
	SingleBone Bone[32];
};
struct CBBoneFrame_64 {
	SingleBone Bone[64];
};

struct CBPostEffect {
	DVector2 Dimensions; float GlobalTime; float PaddingA;
	DVector4 PostEffectInput[NumberOfUserVectorsPerPostEffect];
	DVector2 ZWCorrection[16];
};

struct CBDraw {
	DVector4 Color;
	DVector4 SrcRectUV1;
	DVector4 SrcRectUV2;
	DVector2 Dimensions; float GlobalTime; float PaddingA;
	DVector2 XAxis; DVector2 YAxis;
	DVector2 Center; DVector2 PaddingB;
	DVector4 Arg[16];
};

// Collection types

struct Texture_Struct {
	COLLECTION_STRUCT_DATA(Texture)
	COLLECTION_STRUCT_DATA_RESOURCE
	ID3D11ShaderResourceView* ColorOutput;
	int Width;
	int Height;
};

struct BoneFrame_Struct {
	COLLECTION_STRUCT_DATA(BoneFrame)
	CBBoneFrame_64 Content; // Position and orientation for the maximum number of bones
};

struct DrawSurface_Struct {
	COLLECTION_STRUCT_DATA(DrawSurface)
	
	// Auto size data
	bool							AutoSize;
	float							WidthMultiplier;
	float							HeightMultiplier;
	int								WidthAdder;
	int								HeightAdder;
	
	// Dimensions
	int								CurrentWidth;
	int								CurrentHeight;
	
	// Flags
	int								DepthBuffers; // Does is have a depth buffer
	bool							HaveExtraColorBuffer; // Does it have an extra color buffer
	bool								SwapState; // Who is newest
	bool							FinalSurface; // Is it the final draw surface
	bool							HasContent; // Has it been drawn to since the last automatic resizing
	
	// How many things in the scene are using this as a texture?
	// Knowing this can prevent rendering to a single buffer draw surface that is used as a texture
	int MaterialCount;
	
	// Dynamic interface
	ID3D11RenderTargetView*			ColorInput; // Input
	ID3D11ShaderResourceView*		ColorOutput; // Output
	ID3D11RenderTargetView*			ColorInput_Reverse; // Input
	ID3D11ShaderResourceView*		ColorOutput_Reverse; // Output
	
	// Color buffer
	ID3D11RenderTargetView*			OriginalColorInput; // Input
	ID3D11Texture2D*				OriginalColorBuffer; // Buffer
	ID3D11ShaderResourceView*		OriginalColorOutput; // Output
	
	// Extra color buffer
	ID3D11RenderTargetView*			ExtraColorInput; // Input
	ID3D11Texture2D*				ExtraColorBuffer; // Buffer
	ID3D11ShaderResourceView*		ExtraColorOutput; // Output
	
	// Depth buffer
	ID3D11Texture2D*				DepthBuffer; // Buffer
	ID3D11DepthStencilView*			DepthInputAndOutput; // Input and output
	
	// Extra depth buffer
	ID3D11Texture2D*				ExtraDepthBuffer; // Buffer
	
	// Any depth buffer
	ID3D11ShaderResourceView*		DepthOutput; // Output
	bool							HaveValidDepthBuffer;
	DVector2						ZWCorrection;
};

// Not a collection
struct DepthBuffer_Struct {
	// Dimensions
	int								CurrentWidth;
	int								CurrentHeight;
	
	// Depth buffer
	ID3D11Texture2D*				DepthBuffer; // Buffer
	ID3D11DepthStencilView*			DepthInputAndOutput; // Input and output
	ID3D11ShaderResourceView*		DepthOutput; // Output
};

struct SurfaceCombo {
	int iSurfaceType;
	void* pSurface;
};

// Select shader collection per part
// Use header files and macro arguments to get named shaders
// Use underscore in the filename to make collections of shaders that have a common header
// Some headers will be reused for many shader collections
struct VertexShader {
	ID3D11InputLayout*				pVertexLayout;
	ID3D11VertexShader*				pVertexShader;
};
struct PixelShader {
	ID3D11PixelShader*				pPixelShader;
};
struct GeometryShader {
	ID3D11GeometryShader*				pGeometryShader;
};
struct Shader_Struct {
	COLLECTION_STRUCT_DATA(Shader)
	COLLECTION_STRUCT_DATA_RESOURCE
	VertexShader VS;
	PixelShader PS;
	GeometryShader GS;
	int								ShaderType;
	bool							Compiled;
};
