1. データモデルの作成
データ型の宣言(オプション)
DataManager.h
USTRUCT(BlueprintType)
struct FKawaiiStruct: public FTableRowBase
{
GENERATED_BODY()
// コンストラクタ
FKawaiiStruct(){}
FKawaiiStruct(const FName Name, const FSlateBrush Image): IconName(Name), IconImage(Image){}
// 構造体構成値1:名前(FName)
UPROPERTY(EditAnywhere, BlueprintReadOnly)
FName IconName;
// 構造体構成値2:画像(FSlateBrush)
UPROPERTY(EditAnywhere, BlueprintReadOnly)
FSlateBrush IconImage;
};
データアセットのデータ型の宣言
UPrimaryDataAssetを継承
DataManager.h
UCLASS(BlueprintType)
class UKawaiiAssetDataModel : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
// 実際のデータ
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Data Setting")
TArray<FKawaiiStruct> KawaiiData;
// データ読み込み元(画像)のディレクトリ指定用
UPROPERTY(EditAnywhere, Category="Data Setting", meta=(RelativeToGameContentDir))
FDirectoryPath ImagePath;
// データ取り込み用ファンクション
UFUNCTION(CallInEditor)
void LoadData();
};
データ読み込み用ファンクションの実装 (オプション)
DataManager.h
inline void UKawaiiAssetDataModel::LoadData()
{
// 初期化
KawaiiData.Empty();
// 画像参照先パスの生成
const FString Path = FPaths::Combine("/Game/", ImagePath.Path);
// 指定ディレクトリ内アセットのリスト(パス名)の取得
TArray<FString> Assets = UEditorAssetLibrary::ListAssets(Path, false);
uint32 counter = 0;
for(FString &Asset:Assets)
{
// パス名からアセットデータの取得
FAssetData AssetData = UEditorAssetLibrary::FindAssetData(Asset);
if(AssetData.AssetClass.ToString() == "Texture2D") // アセットがテクスチャの場合のみ処理
{
FSlateBrush IconImage;
IconImage.ImageSize = FVector2d(100.f, 100.f); // サイズの指定
IconImage.SetResourceObject(AssetData.GetAsset()); // 画像の指定
KawaiiData.Add(FKawaiiStruct(AssetData.AssetName, IconImage)); // 配列に追加
++counter;
}
}
if(counter == 0) // 一つも処理できなかった場合(ディレクトリの指定エラー)
{
const FText Title = FText::FromString("Warning");
// ダイアログの表示
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Select a Directory that has Images"), &Title);
} else // 成功
{
FNotificationInfo NotifyInfo(FText::FromString(FString::FromInt(counter) + " Assets were Stored."));
NotifyInfo.bUseLargeFont = true;
NotifyInfo.FadeOutDuration = 7.f;
// 処理数をNotificationに表示
FSlateNotificationManager::Get().AddNotification(NotifyInfo);
}
}
自動でデータを読み込むのは超便利
2. データアセットの作成
Content Browser右クリック > Miscellaneous > Data Asset
先ほど作ったデータアセットのデータ型(KawaiiAssetDataModel)を選択
データアセットが生成される
データセットにデータを読み込む
画像のあるディレクトリを指定して(1)、Load Data(2)でデータの読み込み ‐-今回の実装の場合
一瞬で読み込み完了
3. データアセットのデータを使う
データアセットへの参照
UseDataAsset.h
protected:
// Asset Data(BP_KawaiiData_CPP)へのファイルパス
UPROPERTY( EditAnywhere, meta = (AllowedClasses = "KawaiiAssetDataModel") )
FSoftObjectPath KawaiiDataAssetPath;
private:
UPROPERTY()
TSoftObjectPtr<class UKawaiiAssetDataModel> KawaiiAssetData;
BP_ListView->Class Defaults->Details->Kawaii List View->Kawaii Data Asset Path
データアセットのデータを使う。今回の例だとアセットの配列からランダムに1データ取り出し返す。
UseDataAsset.cpp
FKawaiiStruct KData;
if(KawaiiAssetData == nullptr)
{
UE_LOG(LogTemp, Warning, TEXT("KawaiiDataAssetPath: %s"), *KawaiiDataAssetPath.ToString());
if(KawaiiDataAssetPath.IsNull()) return KData;
KawaiiAssetData = Cast<UKawaiiAssetDataModel>(StaticLoadObject(UKawaiiAssetDataModel::StaticClass(), nullptr, *KawaiiDataAssetPath.ToString()));
if(KawaiiAssetData == nullptr) return KData;
}
const int32 Max = KawaiiAssetData->KawaiiData.Num() - 1;
KData = KawaiiAssetData->KawaiiData[FMath::RandRange(0, Max)];
return KData;
データアセットのプロパティとしてアクセスするだけなので超簡単。
コード全体
DataManager.h
#pragma once
#include "CoreMinimal.h"
#include "EditorAssetLibrary.h"
#include "Misc/MessageDialog.h"
#include "Widgets/Notifications/SNotificationList.h"
#include "Framework/Notifications/NotificationManager.h"
#include "KawaiiDataManager.generated.h"
// Kawaii Structure
USTRUCT() // BlueprintType
struct FKawaiiStruct //: public FTableRowBase <-for Datatable
{
GENERATED_BODY()
public:
FKawaiiStruct(){}
FKawaiiStruct(const FName Name, const FSlateBrush Image): IconName(Name), IconImage(Image){}
UPROPERTY(EditAnywhere)
FName IconName;
UPROPERTY(EditAnywhere)
FSlateBrush IconImage;
};
// Kawaii Data Entry
UCLASS() // Blueprintable
class LISTVIEW_CPP_API UKawaiiDataEntry : public UObject
{
GENERATED_BODY()
public:
UPROPERTY() // BlueprintReadWrite
FKawaiiStruct KawaiiData;
};
// Kawaii Data Asset Model
UCLASS() // BlueprintType
class LISTVIEW_CPP_API UKawaiiAssetDataModel : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere) // EditAnywhere, BlueprintReadOnly, Category="Data Setting"
TArray<FKawaiiStruct> KawaiiData;
UPROPERTY(EditAnywhere, Category="Data Setting", meta=(RelativeToGameContentDir))
FDirectoryPath ImagePath;
UFUNCTION(CallInEditor)
void LoadData();
};
// load asset into Asset Data
inline void UKawaiiAssetDataModel::LoadData()
{
KawaiiData.Empty();
const FString Path = FPaths::Combine("/Game/", ImagePath.Path);
TArray<FString> Assets = UEditorAssetLibrary::ListAssets(Path, false);
uint32 counter = 0;
for(FString &Asset:Assets)
{
FAssetData AssetData = UEditorAssetLibrary::FindAssetData(Asset);
if(AssetData.AssetClass.ToString() == "Texture2D")
{
FSlateBrush IconImage;
IconImage.ImageSize = FVector2d(100.f, 100.f);
IconImage.SetResourceObject(AssetData.GetAsset());
KawaiiData.Add(FKawaiiStruct(AssetData.AssetName, IconImage));
++counter;
UE_LOG(LogTemp, Warning, TEXT("Name: %s"), *AssetData.AssetClass.ToString());
}
}
if(counter == 0)
{
const FText Title = FText::FromString("Warning");
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Select a Directory that has Images"), &Title);
} else
{
FNotificationInfo NotifyInfo(FText::FromString(FString::FromInt(counter) + " Assets were Stored."));
NotifyInfo.bUseLargeFont = true;
NotifyInfo.FadeOutDuration = 7.f;
FSlateNotificationManager::Get().AddNotification(NotifyInfo);
}
}
KawaiiListView.h
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "KawaiiListView.generated.h"
UCLASS(Abstract)
class LISTVIEW_CPP_API UKawaiiListView : public UUserWidget
{
GENERATED_BODY()
protected:
UPROPERTY(meta=(BindWidget))
class UListView *ListView;
virtual void NativeConstruct() override;
UPROPERTY( EditAnywhere, meta = (AllowedClasses = "KawaiiAssetDataModel") )
FSoftObjectPath KawaiiDataAssetPath;
UPROPERTY(EditAnywhere)
int32 NumOfImage = 30;
private:
UPROPERTY()
TSoftObjectPtr<class UKawaiiAssetDataModel> KawaiiAssetData;
struct FKawaiiStruct GetRandomDataFromAsset();
};
KawaiiListView.cpp
#include "KawaiiListView.h"
#include "KawaiiDataManager.h"
#include "Components/ListView.h"
void UKawaiiListView::NativeConstruct()
{
Super::NativeConstruct();
if(KawaiiAssetData) UE_LOG(LogTemp, Warning, TEXT("KawaiiDataAsset is not null"));
for(int i = 0; i < NumOfImage; i++)
{
UKawaiiDataEntry* Entry = NewObject<UKawaiiDataEntry>();
Entry->KawaiiData = GetRandomDataFromAsset();
ListView->AddItem(Entry);
}
}
FKawaiiStruct UKawaiiListView::GetRandomDataFromAsset()
{
FKawaiiStruct KData;
if(KawaiiAssetData == nullptr)
{
UE_LOG(LogTemp, Warning, TEXT("KawaiiDataAssetPath: %s"), *KawaiiDataAssetPath.ToString());
if(KawaiiDataAssetPath.IsNull()) return KData;
KawaiiAssetData = Cast<UKawaiiAssetDataModel>(StaticLoadObject(UKawaiiAssetDataModel::StaticClass(), nullptr, *KawaiiDataAssetPath.ToString()));
if(KawaiiAssetData == nullptr) return KData;
}
const int32 Max = KawaiiAssetData->KawaiiData.Num() - 1;
KData = KawaiiAssetData->KawaiiData[FMath::RandRange(0, Max)];
return KData;
}