text: // AirSim Weather API library
  
  #pragma once
  
  #include "CoreMinimal.h"
  #include "Kismet/BlueprintFunctionLibrary.h"
  #include "Materials/MaterialParameterCollectionInstance.h"
  
  #include "WeatherLib.generated.h"
  
  // NOTE: when adding new enums, you must add it to GetWeatherParamScalarName()'s switch statement
  // with a name for the corresponding material collection param name
  // can't use enum's display names because on package those get deleted.
  UENUM(BlueprintType)
  enum class EWeatherParamScalar : uint8
  {
  	WEATHER_PARAM_SCALAR_RAIN = 0	UMETA(DisplayName = "Rain"),
  	WEATHER_PARAM_SCALAR_ROADWETNESS = 1	UMETA(DisplayName = "RoadWetness"),
  	WEATHER_PARAM_SCALAR_SNOW = 2	UMETA(DisplayName = "Snow"),
  	WEATHER_PARAM_SCALAR_ROADSNOW = 3	UMETA(DisplayName = "RoadSnow"),
  	WEATHER_PARAM_SCALAR_MAPLELEAF = 4	UMETA(DisplayName = "MapleLeaf"),
  	WEATHER_PARAM_SCALAR_ROADLEAF = 5	UMETA(DisplayName = "RoadLeaf"),
  	WEATHER_PARAM_SCALAR_DUST = 6	UMETA(DisplayName = "Dust"),
  	WEATHER_PARAM_SCALAR_FOG = 7	UMETA(DisplayName = "Fog"),
  	WEATHER_PARAM_SCALAR_WEATHERENABLED = 8	UMETA(DisplayName = "WeatherEnabled")
  };
  
  UENUM(BlueprintType)
  enum class EWeatherParamVector : uint8
  {
  	WEATHER_PARAM_VECTOR_WIND = 0	UMETA(DisplayName = "Wind"),
  	WEATHER_PARAM_VECTOR_MAX = 1	UMETA(DisplayName = "MAX")
  };
  /**
   * 
   */
  UCLASS(BlueprintType)
  class AIRSIM_API UWeatherLib : public UBlueprintFunctionLibrary
  {
  	GENERATED_BODY()
  
  	// not sure why, but content folder should be omitted in the path
  	// location of the weather UMaterialParameterCollection, params for rain snow wind etc
  		static const TCHAR* getWeatherParamsObjectPath()
  	{
  		return TEXT("/AirSim/Weather/WeatherFX/WeatherGlobalParams");
  	}
  	static const FSoftClassPath getWeatherMenuObjectPath()
  	{
  		return FSoftClassPath(TEXT("AActor'/AirSim/Weather/UI/MenuActor.MenuActor_C'"));
  	}
  
  	static const FSoftClassPath getWeatherActorPath()
  	{
  		return FSoftClassPath(TEXT("AActor'/AirSim/Weather/WeatherFX/WeatherActor.WeatherActor_C'"));
  	}
  	
  	static const FSoftClassPath getWeatherMenuWidgetClass()
  	{
  		return FSoftClassPath(TEXT("UUserWidget'/AirSim/HUDAssets/OptionsMenu.OptionsMenu_C'"));
  	}
  	// menu class name for finding and closing it
  	static const FString getWeatherMenuClassName()
  	{
  		return TEXT("OptionsMenu_C");
  	}
  
  
  	// corresponding param name to set in Weather Params material collection
  	static const FName GetWeatherParamScalarName(EWeatherParamScalar WeatherParam)
  	{
  		switch (WeatherParam) 
  		{
  			case EWeatherParamScalar::WEATHER_PARAM_SCALAR_RAIN:
  			{
  				return TEXT("Rain");
  				break;
  			}
  			case EWeatherParamScalar::WEATHER_PARAM_SCALAR_ROADWETNESS:
  			{
  				return TEXT("RoadWetness");
  				break;
  			}
  			case EWeatherParamScalar::WEATHER_PARAM_SCALAR_SNOW:
  			{
  				return TEXT("Snow");
  				break;
  			}
  			case EWeatherParamScalar::WEATHER_PARAM_SCALAR_ROADSNOW:
  			{
  				return TEXT("RoadSnow");
  				break;
  			}
  			case EWeatherParamScalar::WEATHER_PARAM_SCALAR_MAPLELEAF:
  			{
  				return TEXT("MapleLeaf");
  				break;
  			}
  			case EWeatherParamScalar::WEATHER_PARAM_SCALAR_ROADLEAF:
  			{
  				return TEXT("RoadLeaf");
  				break;
  			}
  			case EWeatherParamScalar::WEATHER_PARAM_SCALAR_DUST:
  			{
  				return TEXT("Dust");
  				break;
  			}
  			case EWeatherParamScalar::WEATHER_PARAM_SCALAR_FOG:
  			{
  				return TEXT("Fog");
  				break;
  			}
  			case EWeatherParamScalar::WEATHER_PARAM_SCALAR_WEATHERENABLED:
  			{
  				return TEXT("WeatherEnabled");
  				break;
  			}
  		}
  		return TEXT("");
  	}
  	// corresponding param name to set in Weather Params material collection
  	static const FName GetWeatherParamVectorName(EWeatherParamVector WeatherParam)
  	{
  		switch (WeatherParam)
  		{
  			case EWeatherParamVector::WEATHER_PARAM_VECTOR_WIND:
  			{
  				return TEXT("Wind");
  				break;
  			}
  		}
  		return TEXT("");
  	}
  
  	static UMaterialParameterCollectionInstance* getWeatherMaterialCollectionInstance(UWorld* World);
  
  public:
  	// ActorsToAttachTo is an array of actors that we will attach weather particles to
  	// in most cases, this will be the playable pawns so they will always have weather fx
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static void initWeather(UWorld* World, TArray<AActor*> ActorsToAttachTo);
  
  	/* only sets or gets one param. need any actor in the world for WorldContextObject, so we can get world*/
  	UFUNCTION(BlueprintCallable, Category=Weather)
  	static void setWeatherParamScalar(UWorld* World, EWeatherParamScalar Param, float Amount);
  
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static float getWeatherParamScalar(UWorld* World, EWeatherParamScalar Param);
  
  	// only vector for now
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static FVector getWeatherWindDirection(UWorld* World);
  
  	// in a range of (-1, -1, -1) to (1, 1, 1)
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static void setWeatherWindDirection(UWorld* World, FVector NewWind);
  
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static bool getIsWeatherEnabled(UWorld* World);
  
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static void setWeatherEnabled(UWorld* World, bool bEnabled);
  
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static void showWeatherMenu(UWorld* World);
  
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static void hideWeatherMenu(UWorld* World);
  
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static bool isMenuVisible(UWorld* World);
  
  	UFUNCTION(BlueprintCallable, Category = Weather)
  	static void toggleWeatherMenu(UWorld* World);
  
  	// blueprint callable function for widget to get world
  	// since GetWorld() isn't exposed to bp
  	// widget isnt a subclass of actor, so it needs its own implementation
  	UFUNCTION(BlueprintCallable, Category = World)
  	static UWorld* widgetGetWorld(UUserWidget* Widget);
  
  	// blueprint callable function for actor to get world
  	// since GetWorld() isn't exposed to bp
  	UFUNCTION(BlueprintCallable, Category = World)
  	static UWorld* actorGetWorld(AActor* Actor);
  };
  