diff --git a/Common/DzRuntimePluginAction.cpp b/Common/DzRuntimePluginAction.cpp index 61f69a7..d9de683 100644 --- a/Common/DzRuntimePluginAction.cpp +++ b/Common/DzRuntimePluginAction.cpp @@ -49,10 +49,141 @@ DzRuntimePluginAction::~DzRuntimePluginAction() void DzRuntimePluginAction::Export() { - // FBX Export - Selection = dzScene->getPrimarySelection(); - if (!Selection) - return; + // FBX Export + Selection = dzScene->getPrimarySelection(); + if (!Selection) + return; + + QMap PropToInstance; + if (AssetType == "Environment") + { + // Store off the original export information + QString OriginalCharacterName = CharacterName; + DzNode* OriginalSelection = Selection; + + // Find all the different types of props in the scene + GetScenePropList(Selection, PropToInstance); + QMap::iterator iter; + for (iter = PropToInstance.begin(); iter != PropToInstance.end(); ++iter) + { + // Override the export info for exporting this prop + AssetType = "StaticMesh"; + CharacterName = iter.key(); + CharacterName = CharacterName.remove(QRegExp("[^A-Za-z0-9_]")); + CharacterFolder = ImportFolder + "\\" + CharacterName + "\\"; + CharacterFBX = CharacterFolder + CharacterName + ".fbx"; + DzNode* Node = iter.value(); + + // If this is a figure, send it as a skeletal mesh + if (DzSkeleton* Skeleton = Node->getSkeleton()) + { + if (DzFigure* Figure = qobject_cast(Skeleton)) + { + AssetType = "SkeletalMesh"; + } + } + + // Disconnect the asset being sent from everything else + QList AttachmentList; + DisconnectNode(Node, AttachmentList); + + // Set the selection so this will be the exported asset + Selection = Node; + + // Store the current transform and zero it out. + DzVec3 Location; + DzQuat Rotation; + DzMatrix3 Scale; + + Node->getWSTransform(Location, Rotation, Scale); + Node->setWSTransform(DzVec3(0.0f, 0.0f, 0.0f), DzQuat(), DzMatrix3(true)); + + // Export + ExportNode(Node); + + // Put the item back where it was + Node->setWSTransform(Location, Rotation, Scale); + + // Reconnect all the nodes + ReconnectNodes(AttachmentList); + } + + // After the props have been exported, export the environment + CharacterName = OriginalCharacterName; + CharacterFolder = ImportFolder + "\\" + CharacterName + "\\"; + CharacterFBX = CharacterFolder + CharacterName + ".fbx"; + Selection = OriginalSelection; + AssetType = "Environment"; + ExportNode(Selection); + } + else + { + DzNode* Selection = dzScene->getPrimarySelection(); + ExportNode(Selection); + } +} + +void DzRuntimePluginAction::DisconnectNode(DzNode* Node, QList& AttachmentList) +{ + AttachmentInfo ParentAttachment; + if (Node->getNodeParent()) + { + // Don't disconnect a figures bones + if (DzBone* Bone = qobject_cast(Node)) + { + + } + else + { + ParentAttachment.Parent = Node->getNodeParent(); + ParentAttachment.Child = Node; + AttachmentList.append(ParentAttachment); + Node->getNodeParent()->removeNodeChild(Node); + } + } + + QList ChildNodes; + for (int ChildIndex = Node->getNumNodeChildren() - 1; ChildIndex >= 0; ChildIndex--) + { + DzNode* ChildNode = Node->getNodeChild(ChildIndex); + if (DzBone* Bone = qobject_cast(ChildNode)) + { + + } + else + { + DzNode* ChildNode = Node->getNodeChild(ChildIndex); + AttachmentInfo ChildAttachment; + ChildAttachment.Parent = Node; + ChildAttachment.Child = ChildNode; + AttachmentList.append(ChildAttachment); + Node->removeNodeChild(ChildNode); + } + DisconnectNode(ChildNode, AttachmentList); + } +} + +void DzRuntimePluginAction::ReconnectNodes(QList& AttachmentList) +{ + foreach(AttachmentInfo Attachment, AttachmentList) + { + Attachment.Parent->addNodeChild(Attachment.Child); + } +} + + +void DzRuntimePluginAction::ExportNode(DzNode* Node) +{ + dzScene->selectAllNodes(false); + dzScene->setPrimarySelection(Node); + + if (AssetType == "Environment") + { + QDir dir; + dir.mkpath(CharacterFolder); + WriteConfiguration(); + return; + } DzExportMgr* ExportManager = dzApp->getExportMgr(); DzExporter* Exporter = ExportManager->findExporterByClassName("DzFbxExporter"); @@ -62,7 +193,7 @@ void DzRuntimePluginAction::Export() DzFileIOSettings ExportOptions; ExportOptions.setBoolValue("doSelected", true); ExportOptions.setBoolValue("doVisible", false); - if (AssetType == "SkeletalMesh" || AssetType == "StaticMesh") + if (AssetType == "SkeletalMesh" || AssetType == "StaticMesh" || AssetType == "Environment") { ExportOptions.setBoolValue("doFigures", true); ExportOptions.setBoolValue("doProps", true); @@ -100,10 +231,13 @@ void DzRuntimePluginAction::Export() ExportOptions.setBoolValue("doCollapseUVTiles", false); // get the top level node for things like clothing so we don't get dupe material names - DzNode* Parent = Selection; - while (Parent->getNodeParent() != NULL) + DzNode* Parent = Node; + if (AssetType != "Environment") { - Parent = Parent->getNodeParent(); + while (Parent->getNodeParent() != NULL) + { + Parent = Parent->getNodeParent(); + } } // rename duplicate material names @@ -164,4 +298,46 @@ void DzRuntimePluginAction::UndoRenameDuplicateMaterials(DzNode* Node, QList& Types) +{ + DzObject* Object = Node->getObject(); + DzShape* Shape = Object ? Object->getCurrentShape() : NULL; + DzGeometry* Geometry = Shape ? Shape->getGeometry() : NULL; + DzSkeleton* Skeleton = Node->getSkeleton(); + DzFigure* Figure = Skeleton ? qobject_cast(Skeleton) : NULL; + //QString AssetId = Node->getAssetId(); + //IDzSceneAsset::AssetType Type = Node->getAssetType(); + + // Use the FileName to generate a name for the prop to be exported + QString Path = Node->getAssetFileInfo().getUri().getFilePath(); + QFile File(Path); + QString FileName = File.fileName(); + QStringList Items = FileName.split("/"); + QStringList Parts = Items[Items.count() - 1].split("."); + QString Name = Parts[0].remove(QRegExp("[^A-Za-z0-9_]")); + + if (Figure) + { + QString FigureAssetId = Figure->getAssetId(); + if (!Types.contains(Name)) + { + Types.insert(Name, Node); + } + } + else if (Geometry) + { + if (!Types.contains(Name)) + { + Types.insert(Name, Node); + } + } + + // Looks through the child nodes for more props + for (int ChildIndex = 0; ChildIndex < Node->getNumNodeChildren(); ChildIndex++) + { + DzNode* ChildNode = Node->getNodeChild(ChildIndex); + GetScenePropList(ChildNode, Types); + } +} + #include "moc_DzRuntimePluginAction.cpp" diff --git a/Common/DzRuntimePluginAction.h b/Common/DzRuntimePluginAction.h index 5c0ebf7..b56ae5b 100644 --- a/Common/DzRuntimePluginAction.h +++ b/Common/DzRuntimePluginAction.h @@ -6,6 +6,13 @@ #include "QtCore/qfile.h" #include "QtCore/qtextstream.h" +// Struct to remember attachment info +struct AttachmentInfo +{ + DzNode* Parent; + DzNode* Child; +}; + class DzRuntimePluginAction : public DzAction { Q_OBJECT public: @@ -32,6 +39,7 @@ class DzRuntimePluginAction : public DzAction { virtual QString getDefaultMenuPath() const { return tr("&File/Send To"); } virtual void Export(); + virtual void ExportNode(DzNode* Node); virtual void WriteConfiguration() = 0; virtual void SetExportOptions(DzFileIOSettings &ExportOptions) = 0; @@ -39,4 +47,11 @@ class DzRuntimePluginAction : public DzAction { // Need to temporarily rename surfaces if there is a name collision void RenameDuplicateMaterials(DzNode* Node, QList& MaterialNames, QMap& OriginalMaterialNames); void UndoRenameDuplicateMaterials(DzNode* Node, QList& MaterialNames, QMap& OriginalMaterialNames); + + // Used to find all the unique props in a scene for Environment export + void GetScenePropList(DzNode* Node, QMap& Types); + + // During Environment export props need to get disconnected as they are exported. + void DisconnectNode(DzNode* Node, QList& AttachmentList); + void ReconnectNodes(QList& AttachmentList); }; \ No newline at end of file diff --git a/Unreal/DazStudioPlugin/DzUnrealAction.cpp b/Unreal/DazStudioPlugin/DzUnrealAction.cpp index f2d47b8..052b577 100644 --- a/Unreal/DazStudioPlugin/DzUnrealAction.cpp +++ b/Unreal/DazStudioPlugin/DzUnrealAction.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -14,6 +15,12 @@ #include #include #include +#include +#include +#include +//#include +#include "idzsceneasset.h" +#include "dzuri.h" #include "DzUnrealDialog.h" #include "DzUnrealAction.h" @@ -93,29 +100,43 @@ void DzUnrealAction::WriteConfiguration() writer.addMember("FBX File", CharacterFBX); writer.addMember("Import Folder", CharacterFolder); - writer.startMemberArray("Materials", true); - WriteMaterials(Selection, writer); - writer.finishArray(); - - writer.startMemberArray("Morphs", true); - if (ExportMorphs) + if (AssetType != "Environment") { - for (QMap::iterator i = MorphMapping.begin(); i != MorphMapping.end(); ++i) - { - writer.startObject(true); - writer.addMember("Name", i.key()); - writer.addMember("Label", i.value()); - writer.finishObject(); - } + writer.startMemberArray("Materials", true); + WriteMaterials(Selection, writer); + writer.finishArray(); + + writer.startMemberArray("Morphs", true); + if (ExportMorphs) + { + for (QMap::iterator i = MorphMapping.begin(); i != MorphMapping.end(); ++i) + { + writer.startObject(true); + writer.addMember("Name", i.key()); + writer.addMember("Label", i.value()); + writer.finishObject(); + } + } + + writer.finishArray(); + + + writer.startMemberArray("Subdivisions", true); + if (ExportSubdivisions) + SubdivisionDialog->WriteSubdivisions(writer); + + writer.finishArray(); } - writer.finishArray(); - - writer.startMemberArray("Subdivisions", true); - if (ExportSubdivisions) - SubdivisionDialog->WriteSubdivisions(writer); + if (AssetType == "Environment") + { + writer.startMemberArray("Instances", true); + QMap WritingInstances; + QList ExportedGeometry; + WriteInstances(Selection, writer, WritingInstances, ExportedGeometry); + writer.finishArray(); + } - writer.finishArray(); writer.finishObject(); DTUfile.close(); @@ -253,5 +274,61 @@ void DzUnrealAction::WriteMaterials(DzNode* Node, DzJsonWriter& Writer) } } +void DzUnrealAction::WriteInstances(DzNode* Node, DzJsonWriter& Writer, QMap& WritenInstances, QList& ExportedGeometry, QUuid ParentID) +{ + DzObject* Object = Node->getObject(); + DzShape* Shape = Object ? Object->getCurrentShape() : NULL; + DzGeometry* Geometry = Shape ? Shape->getGeometry() : NULL; + DzBone* Bone = qobject_cast(Node); + + if (Bone == nullptr && Geometry) + { + ExportedGeometry.append(Geometry); + ParentID = WriteInstance(Node, Writer, ParentID); + } + + for (int ChildIndex = 0; ChildIndex < Node->getNumNodeChildren(); ChildIndex++) + { + DzNode* ChildNode = Node->getNodeChild(ChildIndex); + WriteInstances(ChildNode, Writer, WritenInstances, ExportedGeometry, ParentID); + } +} + +QUuid DzUnrealAction::WriteInstance(DzNode* Node, DzJsonWriter& Writer, QUuid ParentID) +{ + QString Path = Node->getAssetFileInfo().getUri().getFilePath(); + QFile File(Path); + QString FileName = File.fileName(); + QStringList Items = FileName.split("/"); + QStringList Parts = Items[Items.count() - 1].split("."); + QString Name = Parts[0].remove(QRegExp("[^A-Za-z0-9_]")); + QUuid Uid = QUuid::createUuid(); + + Writer.startObject(true); + Writer.addMember("Version", 1); + Writer.addMember("InstanceLabel", Node->getLabel()); + Writer.addMember("InstanceAsset", Name); + Writer.addMember("ParentID", ParentID.toString()); + Writer.addMember("Guid", Uid.toString()); + Writer.addMember("TranslationX", Node->getWSPos().m_x); + Writer.addMember("TranslationY", Node->getWSPos().m_y); + Writer.addMember("TranslationZ", Node->getWSPos().m_z); + + DzQuat RotationQuat = Node->getWSRot(); + DzVec3 Rotation; + RotationQuat.getValue(Node->getRotationOrder(), Rotation); + Writer.addMember("RotationX", Rotation.m_x); + Writer.addMember("RotationY", Rotation.m_y); + Writer.addMember("RotationZ", Rotation.m_z); + + DzMatrix3 Scale = Node->getWSScale(); + + Writer.addMember("ScaleX", Scale.row(0).length()); + Writer.addMember("ScaleY", Scale.row(1).length()); + Writer.addMember("ScaleZ", Scale.row(2).length()); + Writer.finishObject(); + + return Uid; +} #include "moc_DzUnrealAction.cpp" diff --git a/Unreal/DazStudioPlugin/DzUnrealAction.h b/Unreal/DazStudioPlugin/DzUnrealAction.h index 9b0719e..f51abab 100644 --- a/Unreal/DazStudioPlugin/DzUnrealAction.h +++ b/Unreal/DazStudioPlugin/DzUnrealAction.h @@ -1,9 +1,12 @@ #pragma once #include #include +#include +#include #include #include #include +#include #include #include "DzUnrealSubdivisionDialog.h" @@ -18,6 +21,8 @@ class DzUnrealAction : public DzRuntimePluginAction { void executeAction(); void WriteMaterials(DzNode* Node, DzJsonWriter& Stream); + void WriteInstances(DzNode* Node, DzJsonWriter& Writer, QMap& WritenInstances, QList& ExportedGeometry, QUuid ParentID = QUuid()); + QUuid WriteInstance(DzNode* Node, DzJsonWriter& Writer, QUuid ParentID); void WriteConfiguration(); void SetExportOptions(DzFileIOSettings& ExportOptions); }; \ No newline at end of file diff --git a/Unreal/DazStudioPlugin/DzUnrealDialog.cpp b/Unreal/DazStudioPlugin/DzUnrealDialog.cpp index ea045d2..3aeee1f 100644 --- a/Unreal/DazStudioPlugin/DzUnrealDialog.cpp +++ b/Unreal/DazStudioPlugin/DzUnrealDialog.cpp @@ -82,6 +82,7 @@ DzUnrealDialog::DzUnrealDialog(QWidget *parent) : assetTypeCombo->addItem("Skeletal Mesh"); assetTypeCombo->addItem("Static Mesh"); assetTypeCombo->addItem("Animation"); + assetTypeCombo->addItem("Environment"); //assetTypeCombo->addItem("Pose"); // Morphs @@ -198,11 +199,11 @@ DzUnrealDialog::DzUnrealDialog(QWidget *parent) : if (dzScene->getFilename().length() > 0) { QFileInfo fileInfo = QFileInfo(dzScene->getFilename()); - assetNameEdit->setText(fileInfo.baseName().replace(" ", "_")); + assetNameEdit->setText(fileInfo.baseName().remove(QRegExp("[^A-Za-z0-9_]"))); } else if(dzScene->getPrimarySelection()) { - assetNameEdit->setText(Selection->getLabel().replace(" ", "_")); + assetNameEdit->setText(Selection->getLabel().remove(QRegExp("[^A-Za-z0-9_]"))); } if (qobject_cast(Selection)) diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnreal.cpp b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnreal.cpp index 063887c..657ca91 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnreal.cpp +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnreal.cpp @@ -5,6 +5,7 @@ #include "DazToUnrealMaterials.h" #include "DazToUnrealUtils.h" #include "DazToUnrealFbx.h" +#include "DazToUnrealEnvironment.h" #include "LevelEditor.h" #include "Widgets/Docking/SDockTab.h" @@ -304,13 +305,15 @@ UObject* FDazToUnrealModule::ImportFromDaz(TSharedPtr JsonObject) TMap> MaterialProperties; FString FBXPath = JsonObject->GetStringField(TEXT("FBX File")); - FString AssetName = JsonObject->GetStringField(TEXT("Asset Name")); + FString AssetName = FDazToUnrealUtils::SanitizeName(JsonObject->GetStringField(TEXT("Asset Name"))); FString ImportFolder = JsonObject->GetStringField(TEXT("Import Folder")); DazAssetType AssetType = DazAssetType::StaticMesh; if (JsonObject->GetStringField(TEXT("Asset Type")) == TEXT("SkeletalMesh")) AssetType = DazAssetType::SkeletalMesh; else if (JsonObject->GetStringField(TEXT("Asset Type")) == TEXT("Animation")) - AssetType = DazAssetType::Animation;; + AssetType = DazAssetType::Animation; + else if (JsonObject->GetStringField(TEXT("Asset Type")) == TEXT("Environment")) + AssetType = DazAssetType::Environment; // Set up the folder paths FString ImportDirectory = FPaths::ProjectDir() / TEXT("Import"); @@ -352,6 +355,12 @@ UObject* FDazToUnrealModule::ImportFromDaz(TSharedPtr JsonObject) if (!MakeDirectoryAndCheck(LocalCharacterTexturesFolder)) return false; if (!MakeDirectoryAndCheck(LocalCharacterMaterialFolder)) return false; + if (AssetType == DazAssetType::Environment) + { + FDazToUnrealEnvironment::ImportEnvironment(JsonObject); + return nullptr; + } + // If there isn't an FBX file, stop if (!FPaths::FileExists(FBXFile)) { @@ -383,7 +392,7 @@ UObject* FDazToUnrealModule::ImportFromDaz(TSharedPtr JsonObject) FString MaterialName = AssetName + TEXT("_") + material->GetStringField(TEXT("Material Name")); MaterialName = FDazToUnrealUtils::SanitizeName(MaterialName); FString TexturePath = material->GetStringField(TEXT("Texture")); - FString TextureName = FPaths::GetBaseFilename(TexturePath).Replace(TEXT(" "), TEXT("_")).Replace(TEXT("&"), TEXT("_")); + FString TextureName = FDazToUnrealUtils::SanitizeName(FPaths::GetBaseFilename(TexturePath)); if (!MaterialProperties.Contains(MaterialName)) { @@ -441,7 +450,7 @@ UObject* FDazToUnrealModule::ImportFromDaz(TSharedPtr JsonObject) FString MaterialName = AssetName + TEXT("_") + material->GetStringField(TEXT("Material Name")); MaterialName = FDazToUnrealUtils::SanitizeName(MaterialName); FString TexturePath = material->GetStringField(TEXT("Texture")); - FString TextureName = FPaths::GetBaseFilename(TexturePath).Replace(TEXT(" "), TEXT("_")).Replace(TEXT("&"), TEXT("_")).Replace(TEXT("("), TEXT("_")).Replace(TEXT(")"), TEXT("_")); + FString TextureName = FDazToUnrealUtils::SanitizeName(FPaths::GetBaseFilename(TexturePath)); if (!MaterialProperties.Contains(MaterialName)) { diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealEnvironment.cpp b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealEnvironment.cpp new file mode 100644 index 0000000..ed9ac8b --- /dev/null +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealEnvironment.cpp @@ -0,0 +1,67 @@ +#include "DazToUnrealEnvironment.h" +#include "DazToUnrealSettings.h" +#include "DazToUnrealUtils.h" +#include "Dom/JsonObject.h" +#include "EditorLevelLibrary.h" +#include "Math/UnrealMathUtility.h" + +void FDazToUnrealEnvironment::ImportEnvironment(TSharedPtr JsonObject) +{ + // Get the list of instances + const UDazToUnrealSettings* CachedSettings = GetDefault(); + TArray> InstanceList = JsonObject->GetArrayField(TEXT("Instances")); + TMap GuidToActor; + TMap ParentToChild; + for (int32 Index = 0; Index< InstanceList.Num(); Index++) + { + TSharedPtr Instance = InstanceList[Index]->AsObject(); + + // Get the instance details + int32 Version = Instance->GetIntegerField(TEXT("Version")); + FString InstanceAssetName = FDazToUnrealUtils::SanitizeName(Instance->GetStringField(TEXT("InstanceAsset"))); + double InstanceXPos = Instance->GetNumberField(TEXT("TranslationX")); + double InstanceYPos = Instance->GetNumberField(TEXT("TranslationZ")); + double InstanceZPos = Instance->GetNumberField(TEXT("TranslationY")); + + double InstanceXRot = FMath::RadiansToDegrees(Instance->GetNumberField(TEXT("RotationX"))); + double InstanceYRot = FMath::RadiansToDegrees(Instance->GetNumberField(TEXT("RotationY"))); + double InstanceZRot = FMath::RadiansToDegrees(Instance->GetNumberField(TEXT("RotationZ"))); + + double ScaleXPos = Instance->GetNumberField(TEXT("ScaleX")); + double ScaleYPos = Instance->GetNumberField(TEXT("ScaleZ")); + double ScaleZPos = Instance->GetNumberField(TEXT("ScaleY")); + + FString ParentId = Instance->GetStringField(TEXT("ParentID")); + FString InstanceId = Instance->GetStringField(TEXT("Guid")); + + // Find the asset for this instance + FString AssetPath = CachedSettings->ImportDirectory.Path / InstanceAssetName / InstanceAssetName + TEXT(".") + InstanceAssetName; + UObject* InstanceObject = LoadObject(NULL, *AssetPath, NULL, LOAD_None, NULL); + + // Spawn the object into the scene + if (InstanceObject) + { + FVector Location = FVector(InstanceXPos, InstanceYPos, InstanceZPos); + FRotator Rotation = FRotator(InstanceXRot, InstanceYRot, InstanceZRot); + AActor* NewActor = UEditorLevelLibrary::SpawnActorFromObject(InstanceObject, Location, Rotation); + if (NewActor) + { + NewActor->SetActorScale3D(FVector(ScaleXPos, ScaleYPos, ScaleZPos)); + GuidToActor.Add(InstanceId, NewActor); + ParentToChild.Add(ParentId, InstanceId); + } + } + } + + // Re-create the hierarchy from Daz Studio + for (auto Pair : ParentToChild) + { + if (GuidToActor.Contains(Pair.Key) && GuidToActor.Contains(Pair.Value)) + { + AActor* ParentActor = GuidToActor[Pair.Key]; + AActor* ChildActor = GuidToActor[Pair.Value]; + ChildActor->AttachToActor(ParentActor, FAttachmentTransformRules::KeepWorldTransform); + } + } + +} \ No newline at end of file diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnreal.h b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnreal.h index 76f76cf..7f4c378 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnreal.h +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnreal.h @@ -19,7 +19,8 @@ enum DazAssetType { SkeletalMesh, StaticMesh, - Animation + Animation, + Environment }; diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealEnvironment.h b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealEnvironment.h new file mode 100644 index 0000000..55e0744 --- /dev/null +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealEnvironment.h @@ -0,0 +1,15 @@ +#pragma once + +#include "CoreMinimal.h" +#include "DazToUnrealEnums.h" + +class FJsonObject; + +class FDazToUnrealEnvironment +{ +public: + static void ImportEnvironment(TSharedPtr JsonObject); + +private: + +}; \ No newline at end of file