// Icon Studio - Mathew Simon

#pragma once

#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "IconStudioTypes.h"
#include "IconStudioPreset.generated.h"

class UTextureCube;

/**
 * Le "look" d'une serie d'icones : angle, cadrage, lumieres, resolution.
 *
 * C'est la piece centrale de l'outil. Regler ces valeurs a la main objet par
 * objet donnerait deux cents icones qui ne vont pas ensemble -- des tailles
 * apparentes differentes, des ombres qui changent de cote. Un preset se regle
 * une fois sur un objet representatif, puis tous les autres passent dedans.
 *
 * Creer autant de presets que de familles d'icones : un pour l'inventaire, un
 * autre pour les grandes vignettes de recettes, par exemple.
 */
UCLASS(BlueprintType)
class ICONSTUDIO_API UIconStudioPreset : public UDataAsset
{
	GENERATED_BODY()

public:
	UIconStudioPreset();

	// ------------------------------------------------------------------
	// Camera et cadrage
	// ------------------------------------------------------------------

	/** Rotation horizontale autour de l'objet. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera", meta = (ClampMin = "-180", ClampMax = "180", Units = "deg"))
	float CameraYaw = 135.f;

	/** Negatif = on regarde l'objet de haut. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera", meta = (ClampMin = "-89", ClampMax = "89", Units = "deg"))
	float CameraPitch = -25.f;

	/**
	 * Projection orthographique par defaut : sans point de fuite, une caisse
	 * reste une caisse et deux objets de tailles differentes se comparent a
	 * l'oeil. La perspective ne sert que pour un rendu de presentation.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera")
	bool bOrthographic = true;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera", meta = (EditCondition = "!bOrthographic", ClampMin = "5", ClampMax = "120", Units = "deg"))
	float FieldOfView = 30.f;

	/** Marge laissee entre l'objet et le bord de l'image, en fraction de sa taille. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera", meta = (ClampMin = "0", UIMax = "0.5"))
	float FramingPadding = 0.06f;

	/**
	 * Decalage fin du cadre, en fraction de la largeur d'image.
	 * Sert quand l'objet est visuellement desequilibre (un manche tres long).
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera", meta = (UIMin = "-0.5", UIMax = "0.5"))
	FVector2D FramingOffset = FVector2D::ZeroVector;

	/**
	 * Cadre tous les objets a la meme echelle au lieu de remplir l'image.
	 *
	 * Cadrage automatique : une pomme et un tronc occupent la meme place dans
	 * leur icone. Echelle fixe : le tronc est visiblement plus gros, ce qui aide
	 * a lire l'inventaire mais demande de choisir une taille de reference qui
	 * ne laisse rien deborder.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera")
	bool bUseFixedScale = false;

	/** Largeur du cadre en centimetres quand l'echelle est fixe. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Camera", meta = (EditCondition = "bUseFixedScale", ClampMin = "1", Units = "cm"))
	float FixedFrameWidth = 100.f;

	// ------------------------------------------------------------------
	// Eclairage
	// ------------------------------------------------------------------

	/** Lumiere principale : celle qui dessine la forme. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lighting")
	FIconStudioLight KeyLight;

	/** Deboucheur : remonte les ombres du cote oppose, sans ombre portee. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lighting")
	FIconStudioLight FillLight;

	/** Contre-jour : decolle l'objet du fond par un liseré lumineux. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lighting")
	FIconStudioLight RimLight;

	/**
	 * Cubemap d'ambiance. Sans elle, tout ce qui est metallique ou lisse rend
	 * noir : le speculaire n'a rien a reflechir dans une scene vide.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lighting")
	TSoftObjectPtr<UTextureCube> SkyCubemap;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lighting", meta = (ClampMin = "0", UIMax = "5"))
	float SkyIntensity = 1.f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lighting")
	FLinearColor SkyColor = FLinearColor::White;

	// ------------------------------------------------------------------
	// Rendu
	// ------------------------------------------------------------------

	/** Cote de l'image finale, en pixels. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Render", meta = (ClampMin = "16", ClampMax = "2048"))
	int32 Resolution = 256;

	/**
	 * Facteur de suranalyse : on rend a Resolution x ce facteur, puis on reduit.
	 *
	 * C'est le seul antialiasing utilisable ici. L'antialiasing temporel du
	 * moteur a besoin d'un historique de plusieurs images, qu'une capture unique
	 * n'a pas : il produirait un tremblement different a chaque rendu, et surtout
	 * un masque de transparence different entre les deux passes de fond.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Render", meta = (ClampMin = "1", ClampMax = "8"))
	int32 SupersampleFactor = 4;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Render")
	EIconStudioBackground BackgroundMode = EIconStudioBackground::Transparent;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Render", meta = (EditCondition = "BackgroundMode == EIconStudioBackground::SolidColor", EditConditionHides))
	FLinearColor BackgroundColor = FLinearColor(0.05f, 0.05f, 0.06f, 1.f);

	/** Correction d'exposition, en diaphragmes. L'exposition auto est desactivee. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Render", meta = (UIMin = "-5", UIMax = "5"))
	float ExposureBias = 0.f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Render", meta = (ClampMin = "0", UIMax = "2"))
	float BloomIntensity = 0.f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Render")
	bool bAmbientOcclusion = true;

	/**
	 * Etale la couleur des bords sur les pixels transparents.
	 *
	 * Un pixel entierement transparent n'a pas de couleur definie ; laisse a
	 * noir, il ressort en liseré sombre des que l'icone est filtree ou reduite.
	 * Le defaut classique des icones generees.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Render", meta = (ClampMin = "0", ClampMax = "8"))
	int32 EdgeBleedPasses = 2;

	// ------------------------------------------------------------------
	// Sortie
	// ------------------------------------------------------------------

	/** Dossier de destination des textures generees. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Output", meta = (ContentDir))
	FDirectoryPath OutputDirectory;

	/** Prefixe des assets crees. Le suffixe vient du nom de l'objet source. */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Output")
	FString AssetPrefix = TEXT("T_Icon_");

	/**
	 * Ecrit aussi un PNG dans Saved/IconStudio/.
	 * Utile pour retoucher une icone dans un logiciel externe ; l'asset, lui,
	 * est cree dans tous les cas.
	 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Output")
	bool bAlsoWritePngToDisk = true;

	/** Resolution effective du rendu avant reduction. */
	int32 GetRenderResolution() const { return Resolution * FMath::Clamp(SupersampleFactor, 1, 8); }
};
