diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7a9f59c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs +out +CMakeSettings.json diff --git a/Common/DzRuntimePluginAction.cpp b/Common/DzRuntimePluginAction.cpp index a08b93c..d94b82d 100644 --- a/Common/DzRuntimePluginAction.cpp +++ b/Common/DzRuntimePluginAction.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -41,6 +43,7 @@ DzRuntimePluginAction::DzRuntimePluginAction(const QString& text, const QString& ExportMorphs = false; ExportSubdivisions = false; ShowFbxDialog = false; + ControllersToDisconnect.append("facs_bs_MouthClose_div2"); } DzRuntimePluginAction::~DzRuntimePluginAction() @@ -116,6 +119,84 @@ void DzRuntimePluginAction::Export() AssetType = "Environment"; ExportNode(Selection); } + else if (AssetType == "Pose") + { + PoseList.clear(); + DzNode* Selection = dzScene->getPrimarySelection(); + int poseIndex = 0; + DzNumericProperty* previousProperty = nullptr; + for (int index = 0; index < Selection->getNumProperties(); index++) + { + DzProperty* property = Selection->getProperty(index); + DzNumericProperty* numericProperty = qobject_cast(property); + QString propName = property->getName(); + if (numericProperty) + { + QString propName = property->getName(); + if (MorphMapping.contains(propName)) + { + poseIndex++; + numericProperty->setDoubleValue(0.0f, 0.0f); + for (int frame = 0; frame < MorphMapping.count() + 1; frame++) + { + numericProperty->setDoubleValue(dzScene->getTimeStep() * double(frame), 0.0f); + } + numericProperty->setDoubleValue(dzScene->getTimeStep() * double(poseIndex),1.0f); + PoseList.append(propName); + } + } + } + + DzObject* Object = Selection->getObject(); + if (Object) + { + for (int index = 0; index < Object->getNumModifiers(); index++) + { + DzModifier* modifier = Object->getModifier(index); + DzMorph* mod = qobject_cast(modifier); + if (mod) + { + for (int propindex = 0; propindex < modifier->getNumProperties(); propindex++) + { + DzProperty* property = modifier->getProperty(propindex); + QString propName = property->getName(); + QString propLabel = property->getLabel(); + DzNumericProperty* numericProperty = qobject_cast(property); + if (numericProperty) + { + QString propName = property->getName(); + qDebug() << propName; + if (MorphMapping.contains(modifier->getName())) + { + poseIndex++; + numericProperty->setDoubleValue(0.0f, 0.0f); + for (int frame = 0; frame < MorphMapping.count() + 1; frame++) + { + numericProperty->setDoubleValue(dzScene->getTimeStep() * double(frame), 0.0f); + } + numericProperty->setDoubleValue(dzScene->getTimeStep() * double(poseIndex), 1.0f); + PoseList.append(modifier->getName()); + } + } + } + + } + + } + } + + dzScene->setAnimRange(DzTimeRange(0, poseIndex * dzScene->getTimeStep())); + dzScene->setPlayRange(DzTimeRange(0, poseIndex * dzScene->getTimeStep())); + + ExportNode(Selection); + } + else if (AssetType == "SkeletalMesh") + { + QList DisconnectedModifiers = DisconnectOverrideControllers(); + DzNode* Selection = dzScene->getPrimarySelection(); + ExportNode(Selection); + ReconnectOverrideControllers(DisconnectedModifiers); + } else { DzNode* Selection = dzScene->getPrimarySelection(); @@ -340,4 +421,111 @@ void DzRuntimePluginAction::GetScenePropList(DzNode* Node, QMap DzRuntimePluginAction::DisconnectOverrideControllers() +{ + QList ModifiedList; + DzNode* Selection = dzScene->getPrimarySelection(); + int poseIndex = 0; + DzNumericProperty* previousProperty = nullptr; + for (int index = 0; index < Selection->getNumProperties(); index++) + { + DzProperty* property = Selection->getProperty(index); + DzNumericProperty* numericProperty = qobject_cast(property); + QString propName = property->getName(); + if (numericProperty && !numericProperty->isOverridingControllers()) + { + QString propName = property->getName(); + if (MorphMapping.contains(propName) && ControllersToDisconnect.contains(propName)) + { + numericProperty->setOverrideControllers(true); + ModifiedList.append(propName); + } + } + } + + DzObject* Object = Selection->getObject(); + if (Object) + { + for (int index = 0; index < Object->getNumModifiers(); index++) + { + DzModifier* modifier = Object->getModifier(index); + DzMorph* mod = qobject_cast(modifier); + if (mod) + { + for (int propindex = 0; propindex < modifier->getNumProperties(); propindex++) + { + DzProperty* property = modifier->getProperty(propindex); + QString propName = property->getName(); + QString propLabel = property->getLabel(); + DzNumericProperty* numericProperty = qobject_cast(property); + if (numericProperty && !numericProperty->isOverridingControllers()) + { + QString propName = property->getName(); + if (MorphMapping.contains(modifier->getName()) && ControllersToDisconnect.contains(modifier->getName())) + { + numericProperty->setOverrideControllers(true); + ModifiedList.append(modifier->getName()); + } + } + } + + } + + } + } + + return ModifiedList; +} + +void DzRuntimePluginAction::ReconnectOverrideControllers(QList& DisconnetedControllers) +{ + DzNode* Selection = dzScene->getPrimarySelection(); + int poseIndex = 0; + DzNumericProperty* previousProperty = nullptr; + for (int index = 0; index < Selection->getNumProperties(); index++) + { + DzProperty* property = Selection->getProperty(index); + DzNumericProperty* numericProperty = qobject_cast(property); + QString propName = property->getName(); + if (numericProperty && numericProperty->isOverridingControllers()) + { + QString propName = property->getName(); + if (DisconnetedControllers.contains(propName)) + { + numericProperty->setOverrideControllers(false); + } + } + } + + DzObject* Object = Selection->getObject(); + if (Object) + { + for (int index = 0; index < Object->getNumModifiers(); index++) + { + DzModifier* modifier = Object->getModifier(index); + DzMorph* mod = qobject_cast(modifier); + if (mod) + { + for (int propindex = 0; propindex < modifier->getNumProperties(); propindex++) + { + DzProperty* property = modifier->getProperty(propindex); + QString propName = property->getName(); + QString propLabel = property->getLabel(); + DzNumericProperty* numericProperty = qobject_cast(property); + if (numericProperty && numericProperty->isOverridingControllers()) + { + QString propName = property->getName(); + if (DisconnetedControllers.contains(modifier->getName())) + { + numericProperty->setOverrideControllers(false); + } + } + } + + } + + } + } +} + #include "moc_DzRuntimePluginAction.cpp" diff --git a/Common/DzRuntimePluginAction.h b/Common/DzRuntimePluginAction.h index b56ae5b..5a6f360 100644 --- a/Common/DzRuntimePluginAction.h +++ b/Common/DzRuntimePluginAction.h @@ -29,10 +29,12 @@ class DzRuntimePluginAction : public DzAction { QString MorphString; QString FBXVersion; QMap MorphMapping; + QList PoseList; bool ExportMorphs; bool ExportSubdivisions; bool ShowFbxDialog; + bool ExportMaterialPropertiesCSV; DzNode* Selection; virtual QString getActionGroup() const { return tr("Bridges"); } @@ -54,4 +56,9 @@ class DzRuntimePluginAction : public DzAction { // During Environment export props need to get disconnected as they are exported. void DisconnectNode(DzNode* Node, QList& AttachmentList); void ReconnectNodes(QList& AttachmentList); + + // During Skeletal Mesh Export Disconnect Override Controllers + QList DisconnectOverrideControllers(); + void ReconnectOverrideControllers(QList& DisconnetedControllers); + QList ControllersToDisconnect; }; \ No newline at end of file diff --git a/Unreal/DazStudioPlugin/DzUnrealAction.cpp b/Unreal/DazStudioPlugin/DzUnrealAction.cpp index 88cd507..9abd1fb 100644 --- a/Unreal/DazStudioPlugin/DzUnrealAction.cpp +++ b/Unreal/DazStudioPlugin/DzUnrealAction.cpp @@ -81,6 +81,7 @@ void DzUnrealAction::executeAction() ExportSubdivisions = dlg->subdivisionEnabledCheckBox->isChecked(); MorphMapping = dlg->GetMorphMapping(); ShowFbxDialog = dlg->showFbxDialogCheckBox->isChecked(); + ExportMaterialPropertiesCSV = dlg->exportMaterialPropertyCSVCheckBox->isChecked(); SubdivisionDialog = DzUnrealSubdivisionDialog::Get(dlg); SubdivisionDialog->LockSubdivisionProperties(ExportSubdivisions); FBXVersion = dlg->fbxVersionCombo->currentText(); @@ -103,9 +104,28 @@ void DzUnrealAction::WriteConfiguration() if (AssetType != "Environment") { - writer.startMemberArray("Materials", true); - WriteMaterials(Selection, writer); - writer.finishArray(); + if (ExportMaterialPropertiesCSV) + { + QString filename = CharacterFolder + CharacterName + "_Maps.csv"; + QFile file(filename); + file.open(QIODevice::WriteOnly); + QTextStream stream(&file); + stream << "Version, Object, Material, Type, Color, Opacity, File" << endl; + + writer.startMemberArray("Materials", true); + WriteMaterials(Selection, writer, stream); + writer.finishArray(); + } + else + { + QString throwaway; + QTextStream stream(&throwaway); + writer.startMemberArray("Materials", true); + WriteMaterials(Selection, writer, stream); + writer.finishArray(); + } + + writer.startMemberArray("Morphs", true); if (ExportMorphs) @@ -129,6 +149,22 @@ void DzUnrealAction::WriteConfiguration() writer.finishArray(); } + if (AssetType == "Pose") + { + writer.startMemberArray("Poses", true); + + for (QList::iterator i = PoseList.begin(); i != PoseList.end(); ++i) + { + writer.startObject(true); + writer.addMember("Name", *i); + writer.addMember("Label", MorphMapping[*i]); + writer.finishObject(); + } + + writer.finishArray(); + + } + if (AssetType == "Environment") { writer.startMemberArray("Instances", true); @@ -157,7 +193,7 @@ void DzUnrealAction::SetExportOptions(DzFileIOSettings& ExportOptions) } // Write out all the surface properties -void DzUnrealAction::WriteMaterials(DzNode* Node, DzJsonWriter& Writer) +void DzUnrealAction::WriteMaterials(DzNode* Node, DzJsonWriter& Writer, QTextStream& Stream) { DzObject* Object = Node->getObject(); DzShape* Shape = Object ? Object->getCurrentShape() : NULL; @@ -183,7 +219,11 @@ void DzUnrealAction::WriteMaterials(DzNode* Node, DzJsonWriter& Writer) Writer.addMember("Data Type", QString("String")); Writer.addMember("Texture", QString("")); Writer.finishObject(); - //Stream << "2, " << Node->getLabel() << ", " << Material->getName() << ", " << Material->getMaterialName() << ", " << "Asset Type" << ", " << presentationType << ", " << "String" << ", " << "" << endl; + + if (ExportMaterialPropertiesCSV) + { + Stream << "2, " << Node->getLabel() << ", " << Material->getName() << ", " << Material->getMaterialName() << ", " << "Asset Type" << ", " << presentationType << ", " << "String" << ", " << "" << endl; + } } for (int propertyIndex = 0; propertyIndex < Material->getNumProperties(); propertyIndex++) @@ -210,8 +250,11 @@ void DzUnrealAction::WriteMaterials(DzNode* Node, DzJsonWriter& Writer) Writer.addMember("Data Type", QString("Texture")); Writer.addMember("Texture", TextureName); Writer.finishObject(); + if (ExportMaterialPropertiesCSV) + { + Stream << "2, " << Node->getLabel() << ", " << Material->getName() << ", " << Material->getMaterialName() << ", " << Name << ", " << Material->getDiffuseColor().name() << ", " << "Texture" << ", " << TextureName << endl; + } continue; - //Stream << "2, " << Node->getLabel() << ", " << Material->getName() << ", " << Material->getMaterialName() << ", " << Name << ", " << Material->getDiffuseColor().name() << ", " << "Texture" << ", " << TextureName << endl; } DzColorProperty* ColorProperty = qobject_cast(Property); @@ -235,7 +278,10 @@ void DzUnrealAction::WriteMaterials(DzNode* Node, DzJsonWriter& Writer) Writer.addMember("Data Type", QString("Color")); Writer.addMember("Texture", TextureName); Writer.finishObject(); - //Stream << "2, " << Node->getLabel() << ", " << Material->getName() << ", " << Material->getMaterialName() << ", " << Name << ", " << ColorProperty->getColorValue().name() << ", " << "Color" << ", " << TextureName << endl; + if (ExportMaterialPropertiesCSV) + { + Stream << "2, " << Node->getLabel() << ", " << Material->getName() << ", " << Material->getMaterialName() << ", " << Name << ", " << ColorProperty->getColorValue().name() << ", " << "Color" << ", " << TextureName << endl; + } continue; } @@ -260,7 +306,10 @@ void DzUnrealAction::WriteMaterials(DzNode* Node, DzJsonWriter& Writer) Writer.addMember("Data Type", QString("Double")); Writer.addMember("Texture", TextureName); Writer.finishObject(); - //Stream << "2, " << Node->getLabel() << ", " << Material->getName() << ", " << Material->getMaterialName() << ", " << Name << ", " << NumericProperty->getDoubleValue() << ", " << "Double" << ", " << TextureName << endl; + if (ExportMaterialPropertiesCSV) + { + Stream << "2, " << Node->getLabel() << ", " << Material->getName() << ", " << Material->getMaterialName() << ", " << Name << ", " << NumericProperty->getDoubleValue() << ", " << "Double" << ", " << TextureName << endl; + } } } } @@ -271,7 +320,7 @@ void DzUnrealAction::WriteMaterials(DzNode* Node, DzJsonWriter& Writer) while (Iterator.hasNext()) { DzNode* Child = Iterator.next(); - WriteMaterials(Child, Writer); + WriteMaterials(Child, Writer, Stream); } } diff --git a/Unreal/DazStudioPlugin/DzUnrealAction.h b/Unreal/DazStudioPlugin/DzUnrealAction.h index f51abab..f0b9e44 100644 --- a/Unreal/DazStudioPlugin/DzUnrealAction.h +++ b/Unreal/DazStudioPlugin/DzUnrealAction.h @@ -20,7 +20,7 @@ class DzUnrealAction : public DzRuntimePluginAction { DzUnrealSubdivisionDialog* SubdivisionDialog; void executeAction(); - void WriteMaterials(DzNode* Node, DzJsonWriter& Stream); + void WriteMaterials(DzNode* Node, DzJsonWriter& Writer, QTextStream& Stream); void WriteInstances(DzNode* Node, DzJsonWriter& Writer, QMap& WritenInstances, QList& ExportedGeometry, QUuid ParentID = QUuid()); QUuid WriteInstance(DzNode* Node, DzJsonWriter& Writer, QUuid ParentID); void WriteConfiguration(); diff --git a/Unreal/DazStudioPlugin/DzUnrealDialog.cpp b/Unreal/DazStudioPlugin/DzUnrealDialog.cpp index 3aeee1f..a5030fd 100644 --- a/Unreal/DazStudioPlugin/DzUnrealDialog.cpp +++ b/Unreal/DazStudioPlugin/DzUnrealDialog.cpp @@ -60,9 +60,15 @@ DzUnrealDialog::DzUnrealDialog(QWidget *parent) : // Set the dialog title setWindowTitle(tr("Daz To Unreal")); - + layout()->setSizeConstraint(QLayout::SetFixedSize); QFormLayout* mainLayout = new QFormLayout(this); + + + advancedWidget = new QWidget(); + QHBoxLayout* advancedLayoutOuter = new QHBoxLayout(this); + advancedLayoutOuter->addWidget(advancedWidget); QFormLayout* advancedLayout = new QFormLayout(this); + advancedWidget->setLayout(advancedLayout); // Asset Name assetNameEdit = new QLineEdit(this); @@ -127,29 +133,33 @@ DzUnrealDialog::DzUnrealDialog(QWidget *parent) : // Show FBX Dialog option showFbxDialogCheckBox = new QCheckBox("", this); + connect(showFbxDialogCheckBox, SIGNAL(stateChanged(int)), this, SLOT(HandleShowFbxDialogCheckBoxChange(int))); + + // Export Material Property CSV option + exportMaterialPropertyCSVCheckBox = new QCheckBox("", this); + connect(exportMaterialPropertyCSVCheckBox, SIGNAL(stateChanged(int)), this, SLOT(HandleExportMaterialPropertyCSVCheckBoxChange(int))); // Add the widget to the basic dialog mainLayout->addRow("Asset Name", assetNameEdit); mainLayout->addRow("Asset Type", assetTypeCombo); mainLayout->addRow("Enable Morphs", morphsLayout); mainLayout->addRow("Enable Subdivision", subdivisionLayout); - //mainLayout->addRow("Project", projectLayout); advancedLayout->addRow("Intermediate Folder", intermediateFolderLayout); advancedLayout->addRow("Port", portEdit); advancedLayout->addRow("FBX Version", fbxVersionCombo); advancedLayout->addRow("Show FBX Dialog", showFbxDialogCheckBox); + advancedLayout->addRow("Export Material CSV", exportMaterialPropertyCSVCheckBox); addLayout(mainLayout); // Advanced advancedSettingsGroupBox = new QGroupBox("Advanced Settings", this); - advancedSettingsGroupBox->setLayout(advancedLayout); + advancedSettingsGroupBox->setLayout(advancedLayoutOuter); + advancedSettingsGroupBox->setCheckable(true); + advancedSettingsGroupBox->setChecked(false); + advancedSettingsGroupBox->setFixedWidth(500); // This is what forces the whole forms width addWidget(advancedSettingsGroupBox); - - - // Make the dialog fit its contents, with a minimum width, and lock it down - resize(QSize(500, 0).expandedTo(minimumSizeHint())); - setFixedWidth(width()); - setFixedHeight(height()); + advancedWidget->setHidden(true); + connect(advancedSettingsGroupBox, SIGNAL(clicked(bool)), this, SLOT(HandleShowAdvancedSettingsCheckBoxChange(bool))); // Help assetNameEdit->setWhatsThis("This is the name the asset will use in Unreal."); @@ -158,6 +168,8 @@ DzUnrealDialog::DzUnrealDialog(QWidget *parent) : intermediateFolderButton->setWhatsThis("DazToUnreal will collect the assets in a subfolder under this folder. Unreal will import them from here."); portEdit->setWhatsThis("The UDP port used to talk to the DazToUnreal Unreal plugin.\nThis needs to match the port set in the Project Settings in Unreal.\nDefault is 32345."); fbxVersionCombo->setWhatsThis("The version of FBX to use when exporting assets."); + showFbxDialogCheckBox->setWhatsThis("Checking this will show the FBX Dialog for adjustments before export."); + exportMaterialPropertyCSVCheckBox->setWhatsThis("Checking this will write out a CSV of all the material properties. Useful for reference when changing materials."); // Load Settings if (!settings->value("IntermediatePath").isNull()) @@ -185,6 +197,15 @@ DzUnrealDialog::DzUnrealDialog(QWidget *parent) : { showFbxDialogCheckBox->setChecked(settings->value("ShowFBXDialog").toBool()); } + if (!settings->value("ExportMaterialPropertyCSV").isNull()) + { + exportMaterialPropertyCSVCheckBox->setChecked(settings->value("ExportMaterialPropertyCSV").toBool()); + } + if (!settings->value("ShowAdvancedSettings").isNull()) + { + advancedSettingsGroupBox->setChecked(settings->value("ShowAdvancedSettings").toBool()); + advancedWidget->setHidden(!advancedSettingsGroupBox->isChecked()); + } if (!settings->value("FBXExportVersion").isNull()) { int index = fbxVersionCombo->findText(settings->value("FBXExportVersion").toString()); @@ -273,4 +294,14 @@ void DzUnrealDialog::HandleShowFbxDialogCheckBoxChange(int state) { settings->setValue("ShowFBXDialog", state == Qt::Checked); } +void DzUnrealDialog::HandleExportMaterialPropertyCSVCheckBoxChange(int state) +{ + settings->setValue("ExportMaterialPropertyCSV", state == Qt::Checked); +} + +void DzUnrealDialog::HandleShowAdvancedSettingsCheckBoxChange(bool checked) +{ + settings->setValue("ShowAdvancedSettings", checked); + advancedWidget->setHidden(!checked); +} #include "moc_DzUnrealDialog.cpp" diff --git a/Unreal/DazStudioPlugin/DzUnrealDialog.h b/Unreal/DazStudioPlugin/DzUnrealDialog.h index 27c601f..9cd0e86 100644 --- a/Unreal/DazStudioPlugin/DzUnrealDialog.h +++ b/Unreal/DazStudioPlugin/DzUnrealDialog.h @@ -31,8 +31,10 @@ class DzUnrealDialog : public DzBasicDialog { QPushButton* subdivisionButton; QCheckBox* subdivisionEnabledCheckBox; QGroupBox* advancedSettingsGroupBox; + QWidget* advancedWidget; QComboBox* fbxVersionCombo; QCheckBox* showFbxDialogCheckBox; + QCheckBox* exportMaterialPropertyCSVCheckBox; // Pass so the DazTRoUnrealAction can access it from the morph dialog QString GetMorphString(); @@ -50,6 +52,8 @@ private slots: void HandleSubdivisionCheckBoxChange(int state); void HandleFBXVersionChange(const QString& fbxVersion); void HandleShowFbxDialogCheckBoxChange(int state); + void HandleExportMaterialPropertyCSVCheckBoxChange(int state); + void HandleShowAdvancedSettingsCheckBoxChange(bool checked); private: QSettings* settings; diff --git a/Unreal/DazStudioPlugin/DzUnrealMorphSelectionDialog.cpp b/Unreal/DazStudioPlugin/DzUnrealMorphSelectionDialog.cpp index 4e7eee9..47ff889 100644 --- a/Unreal/DazStudioPlugin/DzUnrealMorphSelectionDialog.cpp +++ b/Unreal/DazStudioPlugin/DzUnrealMorphSelectionDialog.cpp @@ -126,14 +126,17 @@ DzUnrealMorphSelectionDialog::DzUnrealMorphSelectionDialog(QWidget *parent) : QPushButton* ArmsJCMButton = new QPushButton("Arms"); QPushButton* LegsJCMButton = new QPushButton("Legs"); QPushButton* TorsoJCMButton = new QPushButton("Torso"); + QPushButton* ARKit81Button = new QPushButton("ARKit(Genesis8.1)"); ((QGridLayout*)JCMGroupBox->layout())->addWidget(ArmsJCMButton, 0, 0); ((QGridLayout*)JCMGroupBox->layout())->addWidget(LegsJCMButton, 0, 1); ((QGridLayout*)JCMGroupBox->layout())->addWidget(TorsoJCMButton, 0, 2); + ((QGridLayout*)JCMGroupBox->layout())->addWidget(ARKit81Button, 1, 0); connect(ArmsJCMButton, SIGNAL(released()), this, SLOT(HandleArmJCMMorphsButton())); connect(LegsJCMButton, SIGNAL(released()), this, SLOT(HandleLegJCMMorphsButton())); connect(TorsoJCMButton, SIGNAL(released()), this, SLOT(HandleTorsoJCMMorphsButton())); - + connect(ARKit81Button, SIGNAL(released()), this, SLOT(HandleARKitGenesis81MorphsButton())); + treeLayout->addWidget(JCMGroupBox); morphsLayout->addLayout(treeLayout); @@ -609,6 +612,69 @@ void DzUnrealMorphSelectionDialog::HandleTorsoJCMMorphsButton() RefreshExportMorphList(); } +// Hard coded list of morphs for Genesis 8.1 and ARKit +// It just adds them all, the other functions will ignore any that don't fit the character +void DzUnrealMorphSelectionDialog::HandleARKitGenesis81MorphsButton() +{ + QStringList MorphsToAdd; + + MorphsToAdd.append("facs_jnt_EyeWideLeft"); + MorphsToAdd.append("facs_jnt_EyeWideRight"); + MorphsToAdd.append("facs_jnt_EyeBlinkLeft"); + MorphsToAdd.append("facs_jnt_EyeBlinkRight"); + MorphsToAdd.append("facs_bs_EyeSquintLeft_div2"); + MorphsToAdd.append("facs_bs_EyeSquintRight_div2"); + MorphsToAdd.append("facs_jnt_JawForward"); + MorphsToAdd.append("facs_jnt_JawLeft"); + MorphsToAdd.append("facs_jnt_JawRight"); + MorphsToAdd.append("facs_jnt_JawOpen"); + MorphsToAdd.append("facs_bs_MouthClose_div2"); + MorphsToAdd.append("facs_bs_MouthFunnel_div2"); + MorphsToAdd.append("facs_bs_MouthPucker_div2"); + MorphsToAdd.append("facs_bs_MouthLeft_div2"); + MorphsToAdd.append("facs_bs_MouthRight_div2"); + MorphsToAdd.append("facs_bs_MouthSmileLeft_div2"); + MorphsToAdd.append("facs_bs_MouthSmileRight_div2"); + MorphsToAdd.append("facs_bs_MouthFrownLeft_div2"); + MorphsToAdd.append("facs_bs_MouthFrownRight_div2"); + MorphsToAdd.append("facs_bs_MouthDimpleLeft_div2"); + MorphsToAdd.append("facs_bs_MouthDimpleRight_div2"); + MorphsToAdd.append("facs_bs_MouthStretchLeft_div2"); + MorphsToAdd.append("facs_bs_MouthStretchRight_div2"); + MorphsToAdd.append("facs_bs_MouthRollLower_div2"); + MorphsToAdd.append("facs_bs_MouthRollUpper_div2"); + MorphsToAdd.append("facs_bs_MouthShrugLower_div2"); + MorphsToAdd.append("facs_bs_MouthShrugUpper_div2"); + MorphsToAdd.append("facs_bs_MouthPressLeft_div2"); + MorphsToAdd.append("facs_bs_MouthPressRight_div2"); + MorphsToAdd.append("facs_bs_MouthLowerDownLeft_div2"); + MorphsToAdd.append("facs_bs_MouthLowerDownRight_div2"); + MorphsToAdd.append("facs_bs_MouthUpperUpLeft_div2"); + MorphsToAdd.append("facs_bs_MouthUpperUpRight_div2"); + MorphsToAdd.append("facs_bs_BrowDownLeft_div2"); + MorphsToAdd.append("facs_bs_BrowDownRight_div2"); + MorphsToAdd.append("facs_ctrl_BrowInnerUp"); + MorphsToAdd.append("facs_bs_BrowOuterUpLeft_div2"); + MorphsToAdd.append("facs_bs_BrowOuterUpRight_div2"); + MorphsToAdd.append("facs_ctrl_CheekPuff"); + MorphsToAdd.append("facs_bs_CheekSquintLeft_div2"); + MorphsToAdd.append("facs_bs_CheekSquintRight_div2"); + MorphsToAdd.append("facs_bs_NoseSneerLeft_div2"); + MorphsToAdd.append("facs_bs_NoseSneerRight_div2"); + MorphsToAdd.append("facs_bs_TongueOut"); + + + // Add the list for export + foreach(QString MorphName, MorphsToAdd) + { + if (morphs.contains(MorphName) && !morphsToExport.contains(morphs[MorphName])) + { + morphsToExport.append(morphs[MorphName]); + } + } + RefreshExportMorphList(); +} + // Refresh the Right export list void DzUnrealMorphSelectionDialog::RefreshExportMorphList() { diff --git a/Unreal/DazStudioPlugin/DzUnrealMorphSelectionDialog.h b/Unreal/DazStudioPlugin/DzUnrealMorphSelectionDialog.h index 7f0c7ed..e5a888a 100644 --- a/Unreal/DazStudioPlugin/DzUnrealMorphSelectionDialog.h +++ b/Unreal/DazStudioPlugin/DzUnrealMorphSelectionDialog.h @@ -78,6 +78,7 @@ public slots: void HandleArmJCMMorphsButton(); void HandleLegJCMMorphsButton(); void HandleTorsoJCMMorphsButton(); + void HandleARKitGenesis81MorphsButton(); private: diff --git a/Unreal/DazStudioPlugin/version.h b/Unreal/DazStudioPlugin/version.h index 4c1804c..8c72d6e 100644 --- a/Unreal/DazStudioPlugin/version.h +++ b/Unreal/DazStudioPlugin/version.h @@ -3,7 +3,7 @@ // Version number for DazToUnreal #define PLUGIN_MAJOR 1 -#define PLUGIN_MINOR 0 +#define PLUGIN_MINOR 1 #define PLUGIN_REV 0 #define PLUGIN_BUILD 1 diff --git a/Unreal/UnrealPlugin/DazToUnreal/Content/BasePBRSkinMaterial.uasset b/Unreal/UnrealPlugin/DazToUnreal/Content/BasePBRSkinMaterial.uasset index ec7e50f..7037506 100644 Binary files a/Unreal/UnrealPlugin/DazToUnreal/Content/BasePBRSkinMaterial.uasset and b/Unreal/UnrealPlugin/DazToUnreal/Content/BasePBRSkinMaterial.uasset differ diff --git a/Unreal/UnrealPlugin/DazToUnreal/Content/PBRSkinParameters.uasset b/Unreal/UnrealPlugin/DazToUnreal/Content/PBRSkinParameters.uasset index 2ba4519..715b6af 100644 Binary files a/Unreal/UnrealPlugin/DazToUnreal/Content/PBRSkinParameters.uasset and b/Unreal/UnrealPlugin/DazToUnreal/Content/PBRSkinParameters.uasset differ diff --git a/Unreal/UnrealPlugin/DazToUnreal/DazToUnreal.uplugin b/Unreal/UnrealPlugin/DazToUnreal/DazToUnreal.uplugin index e09d97a..79e5430 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/DazToUnreal.uplugin +++ b/Unreal/UnrealPlugin/DazToUnreal/DazToUnreal.uplugin @@ -1,7 +1,7 @@ { "FileVersion": 3, "Version": 4, - "VersionName": "4.0", + "VersionName": "4.1.0", "FriendlyName": "DazToUnreal", "Description": "", "Category": "Importers", diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnreal.cpp b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnreal.cpp index f56e791..df7335b 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnreal.cpp +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnreal.cpp @@ -1031,7 +1031,14 @@ UObject* FDazToUnrealModule::ImportFromDaz(TSharedPtr JsonObject) MorphName.Split(TEXT("."), &Left, &MorphName); } - MorphMappings.Add(MorphName, MorphLabel); + if (CachedSettings->UseInternalMorphName) + { + MorphMappings.Add(MorphName, MorphName); + } + else + { + MorphMappings.Add(MorphName, MorphLabel); + } } // Get a list of morph name mappings @@ -1224,6 +1231,9 @@ UObject* FDazToUnrealModule::ImportFromDaz(TSharedPtr JsonObject) // Create Intermediate Materials if (AssetType == DazAssetType::SkeletalMesh || AssetType == DazAssetType::StaticMesh) { + // Create a default Master Subsurface Profile if needed + USubsurfaceProfile* MasterSubsurfaceProfile = FDazToUnrealMaterials::CreateSubsurfaceBaseProfileForCharacter(CharacterMaterialFolder, MaterialProperties); + for (FString IntermediateMaterialName : IntermediateMaterials) { TArray ChildMaterials; @@ -1253,47 +1263,49 @@ UObject* FDazToUnrealModule::ImportFromDaz(TSharedPtr JsonObject) //MaterialProperties[IntermediateMaterialName] = MaterialProperties[ChildMaterials[0]]; - // Create Material FSoftObjectPath BaseMaterialPath = FDazToUnrealMaterials::GetMostCommonBaseMaterial(ChildMaterials, MaterialProperties);//FDazToUnrealMaterials::GetBaseMaterial(ChildMaterials[0], MaterialProperties[IntermediateMaterialName]); UObject* BaseMaterial = BaseMaterialPath.TryLoad(); - UMaterialInstanceConstant* UnrealMaterialConstant = FDazToUnrealMaterials::CreateMaterial(CharacterMaterialFolder, CharacterTexturesFolder, IntermediateMaterialName, MaterialProperties, CharacterType, nullptr); + UMaterialInstanceConstant* UnrealMaterialConstant = FDazToUnrealMaterials::CreateMaterial(CharacterMaterialFolder, CharacterTexturesFolder, IntermediateMaterialName, MaterialProperties, CharacterType, nullptr, MasterSubsurfaceProfile); UnrealMaterialConstant->SetParentEditorOnly((UMaterial*)BaseMaterial); for (FString MaterialName : ChildMaterials) { - if (FDazToUnrealMaterials::GetBaseMaterial(MaterialName, MaterialProperties[MaterialName]) == BaseMaterialPath) - { - // Remove Identical Properties - //for (FString ChildMaterialNameForRemoval : ChildMaterials) + USubsurfaceProfile* SubsurfaceProfile = MasterSubsurfaceProfile; + if (!FDazToUnrealMaterials::SubsurfaceProfilesWouldBeIdentical(MasterSubsurfaceProfile, MaterialProperties[MaterialName])) + { + SubsurfaceProfile = FDazToUnrealMaterials::CreateSubsurfaceProfileForMaterial(MaterialName, ChildMaterialFolder, MaterialProperties[MaterialName]); + } + + if (FDazToUnrealMaterials::GetBaseMaterial(MaterialName, MaterialProperties[MaterialName]) == BaseMaterialPath) + { + + int32 Length = MaterialProperties[MaterialName].Num(); + for (int32 Index = Length - 1; Index >= 0; Index--) + { + FDUFTextureProperty ChildPropertyForRemoval = MaterialProperties[MaterialName][Index]; + if (ChildPropertyForRemoval.Name == TEXT("Asset Type")) continue; + for (FDUFTextureProperty ParentProperty : MaterialProperties[IntermediateMaterialName]) { - - int32 Length = MaterialProperties[MaterialName].Num(); - for (int32 Index = Length - 1; Index >= 0; Index--) - { - FDUFTextureProperty ChildPropertyForRemoval = MaterialProperties[MaterialName][Index]; - if (ChildPropertyForRemoval.Name == TEXT("Asset Type")) continue; - for (FDUFTextureProperty ParentProperty : MaterialProperties[IntermediateMaterialName]) - { - if (ParentProperty.Name == ChildPropertyForRemoval.Name && ParentProperty.Value == ChildPropertyForRemoval.Value) - { - MaterialProperties[MaterialName].RemoveAt(Index); - break; - } - } - } + if (ParentProperty.Name == ChildPropertyForRemoval.Name && ParentProperty.Value == ChildPropertyForRemoval.Value) + { + MaterialProperties[MaterialName].RemoveAt(Index); + break; + } } - - FDazToUnrealMaterials::CreateMaterial(ChildMaterialFolder, CharacterTexturesFolder, MaterialName, MaterialProperties, CharacterType, UnrealMaterialConstant); - } - else - { - FDazToUnrealMaterials::CreateMaterial(ChildMaterialFolder, CharacterTexturesFolder, MaterialName, MaterialProperties, CharacterType, nullptr); - } + } + + FDazToUnrealMaterials::CreateMaterial(ChildMaterialFolder, CharacterTexturesFolder, MaterialName, MaterialProperties, CharacterType, UnrealMaterialConstant, SubsurfaceProfile); + } + else + { + FDazToUnrealMaterials::CreateMaterial(ChildMaterialFolder, CharacterTexturesFolder, MaterialName, MaterialProperties, CharacterType, nullptr, SubsurfaceProfile); + } } } else if (ChildMaterials.Num() == 1) { - FDazToUnrealMaterials::CreateMaterial(CharacterMaterialFolder / IntermediateMaterialName, CharacterTexturesFolder, ChildMaterials[0], MaterialProperties, CharacterType, nullptr); + USubsurfaceProfile* SubsurfaceProfile = FDazToUnrealMaterials::CreateSubsurfaceProfileForMaterial(ChildMaterials[0], CharacterMaterialFolder / ChildMaterials[0], MaterialProperties[ChildMaterials[0]]); + FDazToUnrealMaterials::CreateMaterial(CharacterMaterialFolder / IntermediateMaterialName, CharacterTexturesFolder, ChildMaterials[0], MaterialProperties, CharacterType, nullptr, SubsurfaceProfile); } } @@ -1307,7 +1319,12 @@ UObject* FDazToUnrealModule::ImportFromDaz(TSharedPtr JsonObject) { if (UAnimSequence* AnimSequence = Cast(NewObject)) { - FDazToUnrealPoses::CreatePoseAsset(AnimSequence, PoseNameList); + UPoseAsset* NewPoseAsset = FDazToUnrealPoses::CreatePoseAsset(AnimSequence, PoseNameList); + + FContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked("ContentBrowser"); + TArray AssetsToSelect; + AssetsToSelect.Add((UObject*)NewPoseAsset); + ContentBrowserModule.Get().SyncBrowserToAssets(AssetsToSelect); } } @@ -1316,7 +1333,7 @@ UObject* FDazToUnrealModule::ImportFromDaz(TSharedPtr JsonObject) -bool FDazToUnrealModule::CreateMaterials(const FString CharacterMaterialFolder, const FString CharacterTexturesFolder, const TArray& MaterialNames, TMap> MaterialProperties, const DazCharacterType CharacterType) +/*bool FDazToUnrealModule::CreateMaterials(const FString CharacterMaterialFolder, const FString CharacterTexturesFolder, const TArray& MaterialNames, TMap> MaterialProperties, const DazCharacterType CharacterType) { const UDazToUnrealSettings* CachedSettings = GetDefault(); @@ -1328,7 +1345,7 @@ bool FDazToUnrealModule::CreateMaterials(const FString CharacterMaterialFolder, return true; -} +}*/ // Modified from the FColor::FromHex function @@ -1419,21 +1436,26 @@ UObject* FDazToUnrealModule::ImportFBXAsset(const FString& SourcePath, const FSt FbxFactory->AddToRoot(); USkeleton* Skeleton = nullptr; + FSoftObjectPath SkeletonPath; if (CharacterType == DazCharacterType::Genesis1) { Skeleton = (USkeleton*)CachedSettings->Genesis1Skeleton.TryLoad(); + SkeletonPath = CachedSettings->Genesis1Skeleton; } if (CharacterType == DazCharacterType::Genesis3Male || CharacterType == DazCharacterType::Genesis3Female) { Skeleton = (USkeleton*)CachedSettings->Genesis3Skeleton.TryLoad(); + SkeletonPath = CachedSettings->Genesis3Skeleton; } if (CharacterType == DazCharacterType::Genesis8Male || CharacterType == DazCharacterType::Genesis8Female) { Skeleton = (USkeleton*)CachedSettings->Genesis8Skeleton.TryLoad(); + SkeletonPath = CachedSettings->Genesis8Skeleton; } if (CharacterType == DazCharacterType::Unknown && CachedSettings->OtherSkeletons.Contains(CharacterTypeName)) { Skeleton = (USkeleton*)CachedSettings->OtherSkeletons[CharacterTypeName].TryLoad(); + SkeletonPath = CachedSettings->OtherSkeletons[CharacterTypeName]; } UFbxImportUI* ImportUI = NewObject(); @@ -1449,6 +1471,8 @@ UObject* FDazToUnrealModule::ImportFBXAsset(const FString& SourcePath, const FSt FbxFactory->ImportUI->SkeletalMeshImportData->bImportMorphTargets = true; FbxFactory->ImportUI->bImportAnimations = true; FbxFactory->ImportUI->SkeletalMeshImportData->bUseT0AsRefPose = CachedSettings->FrameZeroIsReferencePose; + FbxFactory->ImportUI->SkeletalMeshImportData->bConvertScene = true; + FbxFactory->ImportUI->SkeletalMeshImportData->bForceFrontXAxis = CachedSettings->ZeroRootRotationOnImport; FbxFactory->ImportUI->MeshTypeToImport = FBXIT_SkeletalMesh; } if (AssetType == DazAssetType::StaticMesh) @@ -1508,17 +1532,9 @@ UObject* FDazToUnrealModule::ImportFBXAsset(const FString& SourcePath, const FSt { if (USkeletalMesh* SkeletalMesh = Cast(ImportedAsset)) { - if (CharacterType == DazCharacterType::Genesis1) - { - SkeletalMesh->PostProcessAnimBlueprint = CachedSettings->Genesis1PostProcessAnimation.TryLoadClass(); - } - if (CharacterType == DazCharacterType::Genesis3Male || CharacterType == DazCharacterType::Genesis3Female) - { - SkeletalMesh->PostProcessAnimBlueprint = CachedSettings->Genesis3PostProcessAnimation.TryLoadClass(); - } - if (CharacterType == DazCharacterType::Genesis8Male || CharacterType == DazCharacterType::Genesis8Female) + if (CachedSettings->SkeletonPostProcessAnimation.Contains(SkeletonPath)) { - SkeletalMesh->PostProcessAnimBlueprint = CachedSettings->Genesis8PostProcessAnimation.TryLoadClass(); + SkeletalMesh->PostProcessAnimBlueprint = CachedSettings->SkeletonPostProcessAnimation[SkeletonPath].TryLoadClass(); } //Get the new skeleton diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealMaterials.cpp b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealMaterials.cpp index 0204ffa..a04cd3e 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealMaterials.cpp +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealMaterials.cpp @@ -4,7 +4,10 @@ #include "Materials/MaterialInstanceConstant.h" #include "Factories/MaterialInstanceConstantFactoryNew.h" +#include "Factories/SubsurfaceProfileFactory.h" +#include "Engine/SubsurfaceProfile.h" #include "AssetRegistryModule.h" +#include "AssetToolsModule.h" FSoftObjectPath FDazToUnrealMaterials::GetBaseMaterialForShader(FString ShaderName) { @@ -75,7 +78,7 @@ FSoftObjectPath FDazToUnrealMaterials::GetBaseMaterial(FString MaterialName, TAr else if (AssetType == TEXT("Follower/Attachment/Lower-Body/Hip/Front") && MaterialName.Contains(TEXT("_Genitalia"))) { - BaseMaterialAssetPath = CachedSettings->BaseSkinMaterial; + BaseMaterialAssetPath = GetSkinMaterialForShader(ShaderName); } else if (AssetType == TEXT("Actor/Character")) { @@ -130,7 +133,7 @@ FSoftObjectPath FDazToUnrealMaterials::GetBaseMaterial(FString MaterialName, TAr { BaseMaterialAssetPath = CachedSettings->BaseCorneaMaterial; } - else if (MaterialName.EndsWith(TEXT("_sclera"))) + /*else if (MaterialName.EndsWith(TEXT("_sclera"))) { BaseMaterialAssetPath = CachedSettings->BaseMaterial; } @@ -141,10 +144,10 @@ FSoftObjectPath FDazToUnrealMaterials::GetBaseMaterial(FString MaterialName, TAr else if (MaterialName.EndsWith(TEXT("_pupils"))) { BaseMaterialAssetPath = CachedSettings->BaseMaterial; - } + }*/ else { - BaseMaterialAssetPath = CachedSettings->BaseMaterial; + //BaseMaterialAssetPath = CachedSettings->BaseMaterial; for (FDUFTextureProperty Property : Properties) { @@ -184,7 +187,7 @@ FSoftObjectPath FDazToUnrealMaterials::GetBaseMaterial(FString MaterialName, TAr return BaseMaterialAssetPath; } -UMaterialInstanceConstant* FDazToUnrealMaterials::CreateMaterial(const FString CharacterMaterialFolder, const FString CharacterTexturesFolder, FString& MaterialName, TMap> MaterialProperties, const DazCharacterType CharacterType, UMaterialInstanceConstant* ParentMaterial) +UMaterialInstanceConstant* FDazToUnrealMaterials::CreateMaterial(const FString CharacterMaterialFolder, const FString CharacterTexturesFolder, FString& MaterialName, TMap> MaterialProperties, const DazCharacterType CharacterType, UMaterialInstanceConstant* ParentMaterial, USubsurfaceProfile* SubsurfaceProfile) { const UDazToUnrealSettings* CachedSettings = GetDefault(); @@ -211,21 +214,23 @@ UMaterialInstanceConstant* FDazToUnrealMaterials::CreateMaterial(const FString C } if (AssetType == TEXT("Follower/Attachment/Head/Face/Eyelashes") || - AssetType == TEXT("Follower/Attachment/Head/Face/Eyes")) + AssetType == TEXT("Follower/Attachment/Head/Face/Eyes") || + AssetType == TEXT("Follower/Attachment/Head/Face/Eyes/Tear") || + AssetType == TEXT("Follower/Attachment/Head/Face/Tears")) { if (MaterialName.Contains(TEXT("_EyeMoisture")) || MaterialName.EndsWith(TEXT("_EyeReflection"))) { //BaseMaterialAssetPath = CachedSettings->BaseEyeMoistureMaterial; SetMaterialProperty(MaterialName, TEXT("Metallic Weight"), TEXT("Double"), TEXT("1"), MaterialProperties); - SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), TEXT("0.05"), MaterialProperties); + SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), FString::SanitizeFloat(CachedSettings->DefaultEyeMoistureOpacity), MaterialProperties); SetMaterialProperty(MaterialName, TEXT("Diffuse Color"), TEXT("Color"), TEXT("#bababa"), MaterialProperties); SetMaterialProperty(MaterialName, TEXT("Index of Refraction"), TEXT("Double"), TEXT("1.0"), MaterialProperties); } - else if (MaterialName.EndsWith(TEXT("_Tear"))) + else if (MaterialName.EndsWith(TEXT("_Tear")) || MaterialName.EndsWith(TEXT("_Tears"))) { //BaseMaterialAssetPath = CachedSettings->BaseCorneaMaterial; SetMaterialProperty(MaterialName, TEXT("Metallic Weight"), TEXT("Double"), TEXT("1"), MaterialProperties); - SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), TEXT("0.05"), MaterialProperties); + SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), FString::SanitizeFloat(CachedSettings->DefaultEyeMoistureOpacity), MaterialProperties); SetMaterialProperty(MaterialName, TEXT("Index of Refraction"), TEXT("Double"), TEXT("1.0"), MaterialProperties); } else @@ -245,9 +250,11 @@ UMaterialInstanceConstant* FDazToUnrealMaterials::CreateMaterial(const FString C { // Check for skin materials if (MaterialName.EndsWith(TEXT("_Face")) || + MaterialName.EndsWith(TEXT("_Head")) || MaterialName.EndsWith(TEXT("_Lips")) || MaterialName.EndsWith(TEXT("_Legs")) || MaterialName.EndsWith(TEXT("_Torso")) || + MaterialName.EndsWith(TEXT("_Body")) || MaterialName.EndsWith(TEXT("_Arms")) || MaterialName.EndsWith(TEXT("_EyeSocket")) || MaterialName.EndsWith(TEXT("_Ears")) || @@ -256,20 +263,21 @@ UMaterialInstanceConstant* FDazToUnrealMaterials::CreateMaterial(const FString C MaterialName.EndsWith(TEXT("_Genitalia"))) { //BaseMaterialAssetPath = CachedSettings->BaseSkinMaterial; + SetMaterialProperty(MaterialName, TEXT("Diffuse Subsurface Color Weight"), TEXT("Double"), FString::SanitizeFloat(CachedSettings->DefaultSkinDiffuseSubsurfaceColorWeight), MaterialProperties); SetMaterialProperty(MaterialName, TEXT("Subsurface Alpha Texture"), TEXT("Texture"), FDazToUnrealTextures::GetSubSurfaceAlphaTexture(CharacterType, MaterialName), MaterialProperties); } else if (MaterialName.Contains(TEXT("_EyeMoisture"))) { //BaseMaterialAssetPath = CachedSettings->BaseEyeMoistureMaterial; SetMaterialProperty(MaterialName, TEXT("Metallic Weight"), TEXT("Double"), TEXT("1"), MaterialProperties); - SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), TEXT("0.05"), MaterialProperties); + SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), FString::SanitizeFloat(CachedSettings->DefaultEyeMoistureOpacity), MaterialProperties); SetMaterialProperty(MaterialName, TEXT("Index of Refraction"), TEXT("Double"), TEXT("1.0"), MaterialProperties); } - else if (MaterialName.EndsWith(TEXT("_EyeReflection")) || MaterialName.EndsWith(TEXT("_Tear"))) + else if (MaterialName.EndsWith(TEXT("_EyeReflection")) || MaterialName.EndsWith(TEXT("_Tear")) || MaterialName.EndsWith(TEXT("_Tears"))) { //BaseMaterialAssetPath = CachedSettings->BaseEyeMoistureMaterial; SetMaterialProperty(MaterialName, TEXT("Metallic Weight"), TEXT("Double"), TEXT("1"), MaterialProperties); - SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), TEXT("0.05"), MaterialProperties); + SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), FString::SanitizeFloat(CachedSettings->DefaultEyeMoistureOpacity), MaterialProperties); SetMaterialProperty(MaterialName, TEXT("Index of Refraction"), TEXT("Double"), TEXT("1.0"), MaterialProperties); } else if (MaterialName.EndsWith(TEXT("_EyeLashes")) || MaterialName.EndsWith(TEXT("_Eyelashes"))) @@ -283,7 +291,7 @@ UMaterialInstanceConstant* FDazToUnrealMaterials::CreateMaterial(const FString C { //BaseMaterialAssetPath = CachedSettings->BaseCorneaMaterial; SetMaterialProperty(MaterialName, TEXT("Metallic Weight"), TEXT("Double"), TEXT("1"), MaterialProperties); - SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), TEXT("0.05"), MaterialProperties); + SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), FString::SanitizeFloat(CachedSettings->DefaultEyeMoistureOpacity), MaterialProperties); SetMaterialProperty(MaterialName, TEXT("Index of Refraction"), TEXT("Double"), TEXT("1.0"), MaterialProperties); } else if (MaterialName.EndsWith(TEXT("_sclera"))) @@ -320,7 +328,7 @@ UMaterialInstanceConstant* FDazToUnrealMaterials::CreateMaterial(const FString C { //BaseMaterialAssetPath = CachedSettings->BaseEyeMoistureMaterial; SetMaterialProperty(MaterialName, TEXT("Metallic Weight"), TEXT("Double"), TEXT("1"), MaterialProperties); - SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), TEXT("0.05"), MaterialProperties); + SetMaterialProperty(MaterialName, TEXT("Opacity Strength"), TEXT("Double"), FString::SanitizeFloat(CachedSettings->DefaultEyeMoistureOpacity), MaterialProperties); SetMaterialProperty(MaterialName, TEXT("Index of Refraction"), TEXT("Double"), TEXT("1.0"), MaterialProperties); } else @@ -372,6 +380,19 @@ UMaterialInstanceConstant* FDazToUnrealMaterials::CreateMaterial(const FString C UnrealMaterialConstant->SetParentEditorOnly((UMaterial*)BaseMaterial); } + if (SubsurfaceProfile) + { + if (!ParentMaterial || ParentMaterial->SubsurfaceProfile != SubsurfaceProfile) + { + UnrealMaterialConstant->bOverrideSubsurfaceProfile = 1; + UnrealMaterialConstant->SubsurfaceProfile = SubsurfaceProfile; + } + else + { + UnrealMaterialConstant->bOverrideSubsurfaceProfile = 0; + } + } + // Set the MaterialInstance properties if (MaterialProperties.Contains(MaterialName)) { @@ -571,4 +592,126 @@ FDUFTextureProperty FDazToUnrealMaterials::GetMostCommonProperty(FString Propert MostCommonProperty.Name = TEXT(""); } return MostCommonProperty; +} + +bool FDazToUnrealMaterials::HasMaterialProperty(const FString& PropertyName, const TArray& MaterialProperties) +{ + for (FDUFTextureProperty MaterialProperty : MaterialProperties) + { + if (MaterialProperty.Name == PropertyName) + { + return true; + } + } + return false; +} +FString FDazToUnrealMaterials::GetMaterialProperty(const FString& PropertyName, const TArray& MaterialProperties) +{ + for (FDUFTextureProperty MaterialProperty : MaterialProperties) + { + if (MaterialProperty.Name == PropertyName) + { + return MaterialProperty.Value; + } + } + return FString(); +} + +USubsurfaceProfile* FDazToUnrealMaterials::CreateSubsurfaceBaseProfileForCharacter(const FString CharacterMaterialFolder, TMap>& MaterialProperties) +{ + // Find the torso material. + for (TPair> Pair : MaterialProperties) + { + FString AssetType; + for (FDUFTextureProperty Property : Pair.Value) + { + if (Property.Name == TEXT("Asset Type")) + { + AssetType = Property.Value; + } + } + + if (AssetType == TEXT("Actor/Character")) + { + if (Pair.Key.EndsWith(TEXT("_Torso")) || Pair.Key.EndsWith(TEXT("_Body"))) + { + return CreateSubsurfaceProfileForMaterial(Pair.Key, CharacterMaterialFolder, Pair.Value); + } + + } + } + return nullptr; +} + +USubsurfaceProfile* FDazToUnrealMaterials::CreateSubsurfaceProfileForMaterial(const FString MaterialName, const FString CharacterMaterialFolder, const TArray MaterialProperties) +{ + // Create the Material Instance + //auto SubsurfaceProfileFactory = NewObject(); + + //Only create for the PBRSkin base material + FString ShaderName; + for (FDUFTextureProperty Property : MaterialProperties) + { + if (Property.Name == TEXT("Asset Type")) + { + ShaderName = Property.ShaderName; + } + } + if (ShaderName != TEXT("PBRSkin")) + { + return nullptr; + } + + FString SubsurfaceProfileName = MaterialName + TEXT("_Profile"); + UPackage* Package = CreatePackage(nullptr, *(CharacterMaterialFolder / MaterialName)); + //USubsurfaceProfile* SubsurfaceProfile = (USubsurfaceProfile*)SubsurfaceProfileFactory->FactoryCreateNew(USubsurfaceProfile::StaticClass(), Package, *MaterialName, RF_Standalone | RF_Public, NULL, GWarn); + FAssetToolsModule& AssetToolsModule = FModuleManager::GetModuleChecked("AssetTools"); + USubsurfaceProfile* SubsurfaceProfile = Cast(AssetToolsModule.Get().CreateAsset(SubsurfaceProfileName, FPackageName::GetLongPackagePath(*(CharacterMaterialFolder / MaterialName)), USubsurfaceProfile::StaticClass(), NULL)); + if (HasMaterialProperty(TEXT("Specular Lobe 1 Roughness"), MaterialProperties)) + { + SubsurfaceProfile->Settings.Roughness0 = FCString::Atof(*GetMaterialProperty(TEXT("Specular Lobe 1 Roughness"), MaterialProperties)); + } + if (HasMaterialProperty(TEXT("Specular Lobe 2 Roughness Mult"), MaterialProperties)) + { + SubsurfaceProfile->Settings.Roughness1 = FCString::Atof(*GetMaterialProperty(TEXT("Specular Lobe 2 Roughness Mult"), MaterialProperties)); + } + if (HasMaterialProperty(TEXT("Dual Lobe Specular Ratio"), MaterialProperties)) + { + SubsurfaceProfile->Settings.LobeMix = FCString::Atof(*GetMaterialProperty(TEXT("Dual Lobe Specular Ratio"), MaterialProperties)); + } + if (HasMaterialProperty(TEXT("SSS Color"), MaterialProperties)) + { + SubsurfaceProfile->Settings.SubsurfaceColor = FColor::FromHex(*GetMaterialProperty(TEXT("SSS Color"), MaterialProperties)); + } + if (HasMaterialProperty(TEXT("SSS Color"), MaterialProperties)) + { + SubsurfaceProfile->Settings.SubsurfaceColor = FColor::FromHex(*GetMaterialProperty(TEXT("SSS Color"), MaterialProperties)); + } + if (HasMaterialProperty(TEXT("Transmitted Color"), MaterialProperties)) + { + SubsurfaceProfile->Settings.FalloffColor = FColor::FromHex(*GetMaterialProperty(TEXT("Transmitted Color"), MaterialProperties)); + } + return SubsurfaceProfile; +} + +bool FDazToUnrealMaterials::SubsurfaceProfilesAreIdentical(USubsurfaceProfile* A, USubsurfaceProfile* B) +{ + if (A == nullptr || B == nullptr) return false; + if (A->Settings.Roughness0 != B->Settings.Roughness0) return false; + if (A->Settings.Roughness1 != B->Settings.Roughness1) return false; + if (A->Settings.LobeMix != B->Settings.LobeMix) return false; + if (A->Settings.SubsurfaceColor != B->Settings.SubsurfaceColor) return false; + if (A->Settings.FalloffColor != B->Settings.FalloffColor) return false; + return true; +} + +bool FDazToUnrealMaterials::SubsurfaceProfilesWouldBeIdentical(USubsurfaceProfile* ExistingSubsurfaceProfile, const TArray MaterialProperties) +{ + if (ExistingSubsurfaceProfile == nullptr) return false; + if (ExistingSubsurfaceProfile->Settings.Roughness0 != FCString::Atof(*GetMaterialProperty(TEXT("Specular Lobe 1 Roughness"), MaterialProperties))) return false; + if (ExistingSubsurfaceProfile->Settings.Roughness1 != FCString::Atof(*GetMaterialProperty(TEXT("Specular Lobe 2 Roughness Mult"), MaterialProperties))) return false; + if (ExistingSubsurfaceProfile->Settings.LobeMix != FCString::Atof(*GetMaterialProperty(TEXT("Dual Lobe Specular Ratio"), MaterialProperties))) return false; + if (ExistingSubsurfaceProfile->Settings.SubsurfaceColor != FColor::FromHex(*GetMaterialProperty(TEXT("SSS Color"), MaterialProperties))) return false; + if (ExistingSubsurfaceProfile->Settings.FalloffColor != FColor::FromHex(*GetMaterialProperty(TEXT("Transmitted Color"), MaterialProperties))) return false; + return true; } \ No newline at end of file diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealPoses.cpp b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealPoses.cpp index 1f78131..7bcf729 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealPoses.cpp +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Private/DazToUnrealPoses.cpp @@ -14,7 +14,7 @@ #include "PackageTools.h" // Partially taken from UPoseAssetFactory::FactoryCreateNew -void FDazToUnrealPoses::CreatePoseAsset(UAnimSequence* SourceAnimation, TArray PoseNames) +UPoseAsset* FDazToUnrealPoses::CreatePoseAsset(UAnimSequence* SourceAnimation, TArray PoseNames) { if (SourceAnimation) { @@ -62,7 +62,10 @@ void FDazToUnrealPoses::CreatePoseAsset(UAnimSequence* SourceAnimation, TArrayCreatePoseFromAnimation(SourceAnimation, &InputPoseNames); PoseAsset->SetSkeleton(TargetSkeleton); PoseAsset->ConvertSpace(true, 0); + + return PoseAsset; } + return nullptr; //return NewPose; //UPoseAssetFactory* Factory = NewObject(); diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnreal.h b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnreal.h index eeb64fb..4c359e7 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnreal.h +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnreal.h @@ -98,7 +98,7 @@ class FDazToUnrealModule : public IModuleInterface UObject* ImportFBXAsset(const FString& SourcePath, const FString& ImportLocation, const DazAssetType& AssetType, const DazCharacterType& CharacterType, const FString& CharacterTypeName); /** Function for creating the Material Instances for the model*/ - bool CreateMaterials(const FString CharacterMaterialFolder, const FString CharacterTexturesFolder, const TArray& MaterialNames, TMap> MaterialProperties, const DazCharacterType CharacterType); + //bool CreateMaterials(const FString CharacterMaterialFolder, const FString CharacterTexturesFolder, const TArray& MaterialNames, TMap> MaterialProperties, const DazCharacterType CharacterType); /** Set material properties that will be set on the Material Instances*/ void SetMaterialProperty(const FString& MaterialName, const FString& PropertyName, const FString& PropertyType, const FString& PropertyValue, TMap>& MaterialProperties); diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealMaterials.h b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealMaterials.h index f15b879..c761f2a 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealMaterials.h +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealMaterials.h @@ -4,6 +4,7 @@ #include "DazToUnrealEnums.h" class UMaterialInstanceConstant; +class USubsurfaceProfile; // struct for holding material override settings struct FDUFTextureProperty { @@ -23,9 +24,10 @@ class FDazToUnrealMaterials { public: static FSoftObjectPath GetBaseMaterial(FString MaterialName, TArray MaterialProperties); - static UMaterialInstanceConstant* CreateMaterial(const FString CharacterMaterialFolder, const FString CharacterTexturesFolder, FString& MaterialName, TMap> MaterialProperties, const DazCharacterType CharacterType, UMaterialInstanceConstant* ParentMaterial); + static UMaterialInstanceConstant* CreateMaterial(const FString CharacterMaterialFolder, const FString CharacterTexturesFolder, FString& MaterialName, TMap> MaterialProperties, const DazCharacterType CharacterType, UMaterialInstanceConstant* ParentMaterial, USubsurfaceProfile* SubsurfaceProfile); static void SetMaterialProperty(const FString& MaterialName, const FString& PropertyName, const FString& PropertyType, const FString& PropertyValue, TMap>& MaterialProperties); - + static bool HasMaterialProperty(const FString& PropertyName, const TArray &MaterialProperties); + static FString GetMaterialProperty(const FString& PropertyName, const TArray& MaterialProperties); static FSoftObjectPath GetMostCommonBaseMaterial(TArray MaterialNames, TMap> MaterialProperties); static TArray GetMostCommonProperties(TArray MaterialNames, TMap> MaterialProperties); @@ -33,4 +35,9 @@ class FDazToUnrealMaterials static FSoftObjectPath GetBaseMaterialForShader(FString ShaderName); static FSoftObjectPath GetSkinMaterialForShader(FString ShaderName); + + static USubsurfaceProfile* CreateSubsurfaceBaseProfileForCharacter(const FString CharacterMaterialFolder, TMap>& MaterialProperties); + static USubsurfaceProfile* CreateSubsurfaceProfileForMaterial(const FString MaterialName, const FString CharacterMaterialFolder, const TArray MaterialProperties); + static bool SubsurfaceProfilesAreIdentical(USubsurfaceProfile* A, USubsurfaceProfile* B); + static bool SubsurfaceProfilesWouldBeIdentical(USubsurfaceProfile* ExistingSubsurfaceProfile, const TArray MaterialProperties); }; \ No newline at end of file diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealPoses.h b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealPoses.h index 02625b8..1a18081 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealPoses.h +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealPoses.h @@ -7,5 +7,5 @@ class FDazToUnrealPoses { public: - static void CreatePoseAsset(UAnimSequence* SourceAnimation, TArray PoseNames); + static UPoseAsset* CreatePoseAsset(UAnimSequence* SourceAnimation, TArray PoseNames); }; \ No newline at end of file diff --git a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealSettings.h b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealSettings.h index 93e6b1b..7661f39 100644 --- a/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealSettings.h +++ b/Unreal/UnrealPlugin/DazToUnreal/Source/DazToUnreal/Public/DazToUnrealSettings.h @@ -23,6 +23,7 @@ class DAZTOUNREAL_API UDazToUnrealSettings : public UDeveloperSettings ShowFBXImportDialog = false; FrameZeroIsReferencePose = false; FixBoneRotationsOnImport = false; + ZeroRootRotationOnImport = false; Genesis1Skeleton = FSoftObjectPath(TEXT("/DazToUnreal/Genesis1BaseSkeleton.Genesis1BaseSkeleton")); Genesis3Skeleton = FSoftObjectPath(TEXT("/DazToUnreal/Genesis3BaseSkeleton.Genesis3BaseSkeleton")); @@ -30,9 +31,8 @@ class DAZTOUNREAL_API UDazToUnrealSettings : public UDeveloperSettings OtherSkeletons.Add(TEXT("Genesis8_1Male"), FSoftObjectPath(TEXT("/DazToUnreal/Genesis8BaseSkeleton.Genesis8BaseSkeleton"))); OtherSkeletons.Add(TEXT("Genesis8_1Female"), FSoftObjectPath(TEXT("/DazToUnreal/Genesis8BaseSkeleton.Genesis8BaseSkeleton"))); - Genesis1PostProcessAnimation = FSoftClassPath(TEXT("/DazToUnreal/Genesis1JCMPostProcess.Genesis1JCMPostProcess_C")); - Genesis3PostProcessAnimation = FSoftClassPath(TEXT("/DazToUnreal/Genesis3JCMPostProcess.Genesis3JCMPostProcess_C")); - Genesis8PostProcessAnimation = FSoftClassPath(TEXT("/DazToUnreal/Genesis8JCMPostProcess.Genesis8JCMPostProcess_C")); + SkeletonPostProcessAnimation.Add(FSoftObjectPath(TEXT("/DazToUnreal/Genesis3BaseSkeleton.Genesis3BaseSkeleton")), FSoftClassPath(TEXT("/DazToUnreal/Genesis3JCMPostProcess.Genesis3JCMPostProcess_C"))); + SkeletonPostProcessAnimation.Add(FSoftObjectPath(TEXT("/DazToUnreal/Genesis8BaseSkeleton.Genesis8BaseSkeleton")), FSoftClassPath(TEXT("/DazToUnreal/Genesis8JCMPostProcess.Genesis8JCMPostProcess_C"))); BaseShaderMaterials.Add(TEXT("Daz Studio Default"), FSoftObjectPath(TEXT("/DazToUnreal/DSDBaseMaterial.DSDBaseMaterial"))); BaseShaderMaterials.Add(TEXT("omUberSurface"), FSoftObjectPath(TEXT("/DazToUnreal/omUberBaseMaterial.omUberBaseMaterial"))); @@ -56,6 +56,8 @@ class DAZTOUNREAL_API UDazToUnrealSettings : public UDeveloperSettings BaseCorneaMaterial = FSoftObjectPath(TEXT("/DazToUnreal/BaseAlphaMaterial.BaseAlphaMaterial")); NoDrawMaterial = FSoftObjectPath(TEXT("/DazToUnreal/NoDrawMaterial.NoDrawMaterial")); + UseInternalMorphName = false; + ArmsSubSurfaceOpacityGenesis1Texture = FSoftObjectPath(TEXT("/Engine/EngineResources/WhiteSquareTexture.WhiteSquareTexture")); FaceSubSurfaceOpacityGenesis1Texture = FSoftObjectPath(TEXT("/Engine/EngineResources/WhiteSquareTexture.WhiteSquareTexture")); LegsSubSurfaceOpacityGenesis1Texture = FSoftObjectPath(TEXT("/Engine/EngineResources/WhiteSquareTexture.WhiteSquareTexture")); @@ -85,6 +87,9 @@ class DAZTOUNREAL_API UDazToUnrealSettings : public UDeveloperSettings MaterialPropertyMapping.Add(TEXT("Specular Strength"), TEXT("Glossy Layered Weight")); MaterialPropertyMapping.Add(TEXT("Specular Strength Texture"), TEXT("Glossy Layered Weight Texture")); MaterialPropertyMapping.Add(TEXT("Specular Strength Texture Active"), TEXT("Glossy Layered Weight Texture Active")); + + DefaultSkinDiffuseSubsurfaceColorWeight = 0.5f; + DefaultEyeMoistureOpacity = 0.04f; } virtual FName GetCategoryName() const { return FName(TEXT("Plugins")); } @@ -117,6 +122,10 @@ class DAZTOUNREAL_API UDazToUnrealSettings : public UDeveloperSettings UPROPERTY(config, EditAnywhere, Category = PluginSettings) bool FixBoneRotationsOnImport; + /** Updates the bones to use a locale rotation. This currently breaks animations coming from Daz Studio. */ + UPROPERTY(config, EditAnywhere, Category = PluginSettings) + bool ZeroRootRotationOnImport; + /** Skeleton to use for Genesis 1 characters */ UPROPERTY(config, EditAnywhere, Category = SkeletonSettings, meta = (AllowedClasses = "Skeleton")) FSoftObjectPath Genesis1Skeleton; @@ -133,17 +142,9 @@ class DAZTOUNREAL_API UDazToUnrealSettings : public UDeveloperSettings UPROPERTY(config, EditAnywhere, Category = SkeletonSettings) TMap OtherSkeletons; - /** Post Process Animation Blueprint to use for Genesis 1 characters */ - UPROPERTY(config, EditAnywhere, Category = SkeletonSettings) - FSoftClassPath Genesis1PostProcessAnimation; - - /** Post Process Animation Blueprint to use for Genesis 3 characters */ + /** A mapping of default post process animations for different skeletons */ UPROPERTY(config, EditAnywhere, Category = SkeletonSettings) - FSoftClassPath Genesis3PostProcessAnimation; - - /** Post Process Animation Blueprint to use for Genesis 8 characters */ - UPROPERTY(config, EditAnywhere, Category = SkeletonSettings) - FSoftClassPath Genesis8PostProcessAnimation; + TMap SkeletonPostProcessAnimation; /** Used to set the default Material to use for a shader type from Daz Studio */ UPROPERTY(config, EditAnywhere, Category = MaterialSettings) @@ -193,6 +194,18 @@ class DAZTOUNREAL_API UDazToUnrealSettings : public UDeveloperSettings UPROPERTY(config, EditAnywhere, Category = MaterialSettings) TMap MaterialPropertyMapping; + /** Default Diffuse Subsurface Color Weight to use for Skin Materials */ + UPROPERTY(config, EditAnywhere, Category = MaterialSettings) + float DefaultSkinDiffuseSubsurfaceColorWeight; + + /** Default Opacity to use for EyeMoisture, Tears, etc */ + UPROPERTY(config, EditAnywhere, Category = MaterialSettings) + float DefaultEyeMoistureOpacity; + + /** Use the internal name rather than the display name when transfering morphs */ + UPROPERTY(config, EditAnywhere, Category = MorphSettings) + bool UseInternalMorphName; + /** Override for the sub surface scatter opacity texture for the arms and fingernails for Genesis 3 Male */ UPROPERTY(config, EditAnywhere, Category = SubSurfaceScatterGenesis, meta = (AllowedClasses = "Texture")) FSoftObjectPath ArmsSubSurfaceOpacityGenesis1Texture; diff --git a/enc_temp_folder/6a78368314534b289560b0c36b376e2d/DzUnrealMorphSelectionDialog.cpp b/enc_temp_folder/6a78368314534b289560b0c36b376e2d/DzUnrealMorphSelectionDialog.cpp deleted file mode 100644 index abc8e75..0000000 --- a/enc_temp_folder/6a78368314534b289560b0c36b376e2d/DzUnrealMorphSelectionDialog.cpp +++ /dev/null @@ -1,722 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dzapp.h" -#include "dzscene.h" -#include "dzstyle.h" -#include "dzmainwindow.h" -#include "dzactionmgr.h" -#include "dzaction.h" -#include "dzskeleton.h" -#include "dzfigure.h" -#include "dzobject.h" -#include "dzshape.h" -#include "dzmodifier.h" -#include "dzpresentation.h" -#include "dzassetmgr.h" -#include "dzproperty.h" -#include "dzsettings.h" -#include "dzmorph.h" -#include "DzUnrealMorphSelectionDialog.h" - -#include "QtGui/qlayout.h" -#include "QtGui/qlineedit.h" - -#include - -/***************************** -Local definitions -*****************************/ -#define DAZ_TO_UNREAL_PLUGIN_NAME "DazToUnreal" - - -DzUnrealMorphSelectionDialog* DzUnrealMorphSelectionDialog::singleton = nullptr; - -// For sorting the lists -class SortingListItem : public QListWidgetItem { - -public: - virtual bool operator< (const QListWidgetItem &otherItem) const - { - if (this->checkState() != otherItem.checkState()) - { - return (this->checkState() == Qt::Checked); - } - return QListWidgetItem::operator<(otherItem); - } -}; - -DzUnrealMorphSelectionDialog::DzUnrealMorphSelectionDialog(QWidget *parent) : - DzBasicDialog(parent, DAZ_TO_UNREAL_PLUGIN_NAME) -{ - morphListWidget = NULL; - morphExportListWidget = NULL; - morphTreeWidget = NULL; - filterEdit = NULL; - presetCombo = NULL; - fullBodyMorphTreeItem = NULL; - charactersTreeItem = NULL; - - // Set the dialog title - setWindowTitle(tr("Select Morphs")); - - // Setup folder - presetsFolder = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation) + QDir::separator() + "DazToUnreal" + QDir::separator() + "Presets"; - - - QVBoxLayout* mainLayout = new QVBoxLayout(this); - - // Left tree with morph structure - morphTreeWidget = new QTreeWidget(this); - morphTreeWidget->setHeaderHidden(true); - - // Center list showing morhps for selected tree items - morphListWidget = new QListWidget(this); - morphListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); - - // Right list showing morphs that will export - morphExportListWidget = new QListWidget(this); - morphExportListWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); - - // Quick filter box - QHBoxLayout* filterLayout = new QHBoxLayout(this); - filterLayout->addWidget(new QLabel("filter")); - filterEdit = new QLineEdit(); - connect(filterEdit, SIGNAL(textChanged(const QString &)), this, SLOT(FilterChanged(const QString &))); - filterLayout->addWidget(filterEdit); - - // Presets - QHBoxLayout* settingsLayout = new QHBoxLayout(this); - presetCombo = new QComboBox(this); - QPushButton* savePresetButton = new QPushButton("Save Preset", this); - connect(savePresetButton, SIGNAL(released()), this, SLOT(HandleSavePreset())); - settingsLayout->addWidget(new QLabel("Choose Preset")); - settingsLayout->addWidget(presetCombo); - settingsLayout->addWidget(savePresetButton); - settingsLayout->addStretch(); - - // All Morphs - QHBoxLayout* morphsLayout = new QHBoxLayout(this); - - // Left Tree - QVBoxLayout* treeLayout = new QVBoxLayout(this); - treeLayout->addWidget(new QLabel("Morph Groups")); - treeLayout->addWidget(new QLabel("Select to see available morphs")); - treeLayout->addWidget(morphTreeWidget); - - // Buttons for quickly adding certain JCMs - QGroupBox* JCMGroupBox = new QGroupBox("Add JCMs", this); - JCMGroupBox->setLayout(new QGridLayout(this)); - QPushButton* ArmsJCMButton = new QPushButton("Arms"); - QPushButton* LegsJCMButton = new QPushButton("Legs"); - QPushButton* TorsoJCMButton = new QPushButton("Torso"); - ((QGridLayout*)JCMGroupBox->layout())->addWidget(ArmsJCMButton, 0, 0); - ((QGridLayout*)JCMGroupBox->layout())->addWidget(LegsJCMButton, 0, 1); - ((QGridLayout*)JCMGroupBox->layout())->addWidget(TorsoJCMButton, 0, 2); - - connect(ArmsJCMButton, SIGNAL(released()), this, SLOT(HandleArmJCMMorphsButton())); - connect(LegsJCMButton, SIGNAL(released()), this, SLOT(HandleLegJCMMorphsButton())); - connect(TorsoJCMButton, SIGNAL(released()), this, SLOT(HandleTorsoJCMMorphsButton())); - - treeLayout->addWidget(JCMGroupBox); - morphsLayout->addLayout(treeLayout); - - - // Center List of morphs based on tree selection - QVBoxLayout* morphListLayout = new QVBoxLayout(this); - morphListLayout->addWidget(new QLabel("Morphs in Group")); - morphListLayout->addWidget(new QLabel("Select and click Add for Export")); - morphListLayout->addLayout(filterLayout); - morphListLayout->addWidget(morphListWidget); - - // Button for adding morphs - QPushButton* addMorphsButton = new QPushButton("Add For Export", this); - connect(addMorphsButton, SIGNAL(released()), this, SLOT(HandleAddMorphsButton())); - morphListLayout->addWidget(addMorphsButton); - morphsLayout->addLayout(morphListLayout); - - // Right List of morphs that will export - QVBoxLayout* selectedListLayout = new QVBoxLayout(this); - selectedListLayout->addWidget(new QLabel("Morphs to Export")); - selectedListLayout->addWidget(morphExportListWidget); - - // Button for clearing morphs from export - QPushButton* removeMorphsButton = new QPushButton("Remove From Export", this); - connect(removeMorphsButton, SIGNAL(released()), this, SLOT(HandleRemoveMorphsButton())); - selectedListLayout->addWidget(removeMorphsButton); - morphsLayout->addLayout(selectedListLayout); - - mainLayout->addLayout(settingsLayout); - mainLayout->addLayout(morphsLayout); - - this->addLayout(mainLayout); - resize(QSize(800, 800));//.expandedTo(minimumSizeHint())); - setFixedWidth(width()); - setFixedHeight(height()); - RefreshPresetsCombo(); - - connect(morphListWidget, SIGNAL(itemChanged(QListWidgetItem*)), - this, SLOT(ItemChanged(QListWidgetItem*))); - - connect(morphTreeWidget, SIGNAL(itemSelectionChanged()), - this, SLOT(ItemSelectionChanged())); - -} - -QSize DzUnrealMorphSelectionDialog::minimumSizeHint() const -{ - return QSize(800, 800); -} - -// Build out the Left morphs tree based on the current selection -void DzUnrealMorphSelectionDialog::PrepareDialog() -{ - DzNode* Selection = dzScene->getPrimarySelection(); - - DzNode* ParentFigureNode = Selection; - // If this is a figure, send it as a skeletal mesh - while (ParentFigureNode->getNodeParent()) - { - ParentFigureNode = ParentFigureNode->getNodeParent(); - if (DzSkeleton* Skeleton = ParentFigureNode->getSkeleton()) - { - if (DzFigure* Figure = qobject_cast(Skeleton)) - { - Selection = ParentFigureNode; - break; - } - } - } - - morphs.clear(); - morphList = GetAvailableMorphs(Selection); - for (int ChildIndex = 0; ChildIndex < Selection->getNumNodeChildren(); ChildIndex++) - { - DzNode* ChildNode = Selection->getNodeChild(ChildIndex); - morphList.append(GetAvailableMorphs(ChildNode)); - } - UpdateMorphsTree(); - HandlePresetChanged("LastUsed.csv"); -} - -// When the filter text is changed, update the center list -void DzUnrealMorphSelectionDialog::FilterChanged(const QString& filter) -{ - morphListWidget->clear(); - QString newFilter = filter; - morphListWidget->clear(); - foreach(MorphInfo morphInfo, selectedInTree) - { - if (newFilter == NULL || newFilter.isEmpty() || morphInfo.Label.contains(newFilter, Qt::CaseInsensitive)) - { - SortingListItem* item = new SortingListItem();// modLabel, morphListWidget); - item->setText(morphInfo.Label); - item->setData(Qt::UserRole, morphInfo.Name); - - morphListWidget->addItem(item); - } - } - - morphListWidget->sortItems(); -} - -// Build a list of availaboe morphs for the node -// TODO: This function evolved a lot as I figured out where to find the morphs. -// There may be dead code in here. -QStringList DzUnrealMorphSelectionDialog::GetAvailableMorphs(DzNode* Node) -{ - QStringList newMorphList; - - DzObject* Object = Node->getObject(); - DzShape* Shape = Object ? Object->getCurrentShape() : NULL; - - for (int index = 0; index < Node->getNumProperties(); index++) - { - DzProperty* property = Node->getProperty(index); - QString propName = property->getName(); - QString propLabel = property->getLabel(); - DzPresentation* presentation = property->getPresentation(); - if (presentation) - { - MorphInfo morphInfo; - morphInfo.Name = propName; - morphInfo.Label = propLabel; - morphInfo.Path = Node->getLabel() + "/" + property->getPath(); - morphInfo.Type = presentation->getType(); - if (!morphs.contains(morphInfo.Name)) - { - morphs.insert(morphInfo.Name, morphInfo); - } - //qDebug() << "Property Name " << propName << " Label " << propLabel << " Presentation Type:" << presentation->getType() << "Path: " << property->getPath(); - //qDebug() << "Path " << property->getGroupOnlyPath(); - } - if (presentation && presentation->getType() == "Modifier/Shape") - { - SortingListItem* item = new SortingListItem();// modLabel, morphListWidget); - item->setText(propLabel); - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - if (morphList.contains(propLabel)) - { - item->setCheckState(Qt::Checked); - newMorphList.append(propName); - } - else - { - item->setCheckState(Qt::Unchecked); - } - item->setData(Qt::UserRole, propName); - morphNameMapping.insert(propName, propLabel); - } - } - - if (Object) - { - for (int index = 0; index < Object->getNumModifiers(); index++) - { - DzModifier* modifier = Object->getModifier(index); - QString modName = modifier->getName(); - QString modLabel = modifier->getLabel(); - DzMorph* mod = qobject_cast(modifier); - if (mod) - { - for (int propindex = 0; propindex < modifier->getNumProperties(); propindex++) - { - DzProperty* property = modifier->getProperty(propindex); - QString propName = property->getName(); - QString propLabel = property->getLabel(); - DzPresentation* presentation = property->getPresentation(); - if (presentation) - { - MorphInfo morphInfoProp; - morphInfoProp.Name = modName; - morphInfoProp.Label = propLabel; - morphInfoProp.Path = Node->getLabel() + "/" + property->getPath(); - morphInfoProp.Type = presentation->getType(); - if (!morphs.contains(morphInfoProp.Name)) - { - morphs.insert(morphInfoProp.Name, morphInfoProp); - } - //qDebug() << "Modifier Name " << modName << " Label " << propLabel << " Presentation Type:" << presentation->getType() << " Path: " << property->getPath(); - //qDebug() << "Path " << property->getGroupOnlyPath(); - } - } - - } - - } - } - - return newMorphList; -} - -// Build out the left tree -void DzUnrealMorphSelectionDialog::UpdateMorphsTree() -{ - morphTreeWidget->clear(); - morphsForNode.clear(); - foreach(QString morph, morphs.keys()) - { - QString path = morphs[morph].Path; - QTreeWidgetItem* parentItem = nullptr; - foreach(QString pathPart, path.split("/")) - { - if (pathPart == "") continue; - parentItem = FindTreeItem(parentItem, pathPart); - - if (!morphsForNode.keys().contains(parentItem)) - { - morphsForNode.insert(parentItem, QList()); - } - morphsForNode[parentItem].append(morphs[morph]); - } - } -} - -// This function could be better named. It will find the node matching the property path -// but it will also create the structure of that path in the tree as needed as it searches -QTreeWidgetItem* DzUnrealMorphSelectionDialog::FindTreeItem(QTreeWidgetItem* parent, QString name) -{ - if (parent == nullptr) - { - for(int i = 0; i < morphTreeWidget->topLevelItemCount(); i++) - { - QTreeWidgetItem* item = morphTreeWidget->topLevelItem(i); - if (item->text(0) == name) - { - return item; - } - } - - QTreeWidgetItem* newItem = new QTreeWidgetItem(morphTreeWidget); - newItem->setText(0, name); - newItem->setExpanded(true); - morphTreeWidget->addTopLevelItem(newItem); - return newItem; - } - else - { - for (int i = 0; i < parent->childCount(); i++) - { - QTreeWidgetItem* item = parent->child(i); - if (item->text(0) == name) - { - return item; - } - } - - QTreeWidgetItem* newItem = new QTreeWidgetItem(parent); - newItem->setText(0, name); - newItem->setExpanded(true); - parent->addChild(newItem); - return newItem; - } -} - -// For selection changes in the Left Tree -void DzUnrealMorphSelectionDialog::ItemSelectionChanged() -{ - selectedInTree.clear(); - foreach(QTreeWidgetItem* selectedItem, morphTreeWidget->selectedItems()) - { - SelectMorphsInNode(selectedItem); - } - - FilterChanged(filterEdit->text()); -} - -// Updates the list of selected morphs in the Left Tree -// including any children -void DzUnrealMorphSelectionDialog::SelectMorphsInNode(QTreeWidgetItem* item) -{ - if (morphsForNode.keys().contains(item)) - { - selectedInTree.append(morphsForNode[item]); - } -} - -// Add Morphs for export -void DzUnrealMorphSelectionDialog::HandleAddMorphsButton() -{ - foreach(QListWidgetItem* selectedItem, morphListWidget->selectedItems()) - { - QString morphName = selectedItem->data(Qt::UserRole).toString(); - if (morphs.contains(morphName) && !morphsToExport.contains(morphs[morphName])) - { - morphsToExport.append(morphs[morphName]); - } - } - RefreshExportMorphList(); - RefreshPresetsCombo(); -} - -// Remove morph from export list -void DzUnrealMorphSelectionDialog::HandleRemoveMorphsButton() -{ - foreach(QListWidgetItem* selectedItem, morphExportListWidget->selectedItems()) - { - QString morphName = selectedItem->data(Qt::UserRole).toString(); - if (morphs.keys().contains(morphName)) - { - morphsToExport.removeAll(morphs[morphName]); - } - } - RefreshExportMorphList(); - RefreshPresetsCombo(); -} - -// Brings up a dialgo for choosing a preset name -void DzUnrealMorphSelectionDialog::HandleSavePreset() -{ - QString filters("CSV Files (*.csv)"); - QString defaultFilter("CSV Files (*.csv)"); - QDir dir; - dir.mkpath(presetsFolder); - - QString presetName = QFileDialog::getSaveFileName(this, QString("Save Preset"), - presetsFolder, - filters, - &defaultFilter); - - if (presetName != NULL) - { - SavePresetFile(presetName); - } -} - -// Saves out a preset. If the path isn't supplied, it's saved as the last selection -void DzUnrealMorphSelectionDialog::SavePresetFile(QString filePath) -{ - QDir dir; - dir.mkpath(presetsFolder); - if (filePath == NULL) - { - filePath = presetsFolder + QDir::separator() + "LastUsed.csv"; - } - - QFile file(filePath); - file.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream out(&file); - out << GetMorphCSVString(); - - // optional, as QFile destructor will already do it: - file.close(); - RefreshPresetsCombo(); - -} - -// Hard coded list of morphs for Genesis 3 and 8 -// It just adds them all, the other functions will ignore any that don't fit the character -void DzUnrealMorphSelectionDialog::HandleArmJCMMorphsButton() -{ - QStringList MorphsToAdd; - - MorphsToAdd.append("pJCMCollarTwist_n30_L"); - MorphsToAdd.append("pJCMCollarTwist_n30_R"); - MorphsToAdd.append("pJCMCollarTwist_p30_L"); - MorphsToAdd.append("pJCMCollarTwist_p30_R"); - MorphsToAdd.append("pJCMCollarUp_55_L"); - MorphsToAdd.append("pJCMCollarUp_55_R"); - MorphsToAdd.append("pJCMCollarUp_50_L"); - MorphsToAdd.append("pJCMCollarUp_50_R"); - MorphsToAdd.append("pJCMForeArmFwd_135_L"); - MorphsToAdd.append("pJCMForeArmFwd_135_R"); - MorphsToAdd.append("pJCMForeArmFwd_75_L"); - MorphsToAdd.append("pJCMForeArmFwd_75_R"); - MorphsToAdd.append("pJCMHandDwn_70_L"); - MorphsToAdd.append("pJCMHandDwn_70_R"); - MorphsToAdd.append("pJCMHandUp_80_L"); - MorphsToAdd.append("pJCMHandUp_80_R"); - MorphsToAdd.append("pJCMShldrDown_40_L"); - MorphsToAdd.append("pJCMShldrDown_40_R"); - MorphsToAdd.append("pJCMShldrDown_75_L"); - MorphsToAdd.append("pJCMShldrDown_75_R"); - MorphsToAdd.append("pJCMShldrDown2_75_L"); - MorphsToAdd.append("pJCMShldrDown2_75_R"); - MorphsToAdd.append("pJCMShldrFront_n110_Bend_n40_L"); - MorphsToAdd.append("pJCMShldrFront_n110_Bend_p90_L"); - MorphsToAdd.append("pJCMShldrFront_p110_Bend_n90_R"); - MorphsToAdd.append("pJCMShldrFront_p110_Bend_p40_R"); - MorphsToAdd.append("pJCMShldrFwdDwn_110_75_L"); - MorphsToAdd.append("pJCMShldrFwdDwn_110_75_R"); - MorphsToAdd.append("pJCMShldrFwd_110_L"); - MorphsToAdd.append("pJCMShldrFwd_110_R"); - MorphsToAdd.append("pJCMShldrFwd_95_L"); - MorphsToAdd.append("pJCMShldrFwd_95_R"); - MorphsToAdd.append("pJCMShldrUp_90_L"); - MorphsToAdd.append("pJCMShldrUp_90_R"); - MorphsToAdd.append("pJCMShldrUp_35_L"); - MorphsToAdd.append("pJCMShldrUp_35_R"); - - // Add the list for export - foreach(QString MorphName, MorphsToAdd) - { - if (morphs.contains(MorphName) && !morphsToExport.contains(morphs[MorphName])) - { - morphsToExport.append(morphs[MorphName]); - } - } - RefreshExportMorphList(); -} - -// Hard coded list of morphs for Genesis 3 and 8 -// It just adds them all, the other functions will ignore any that don't fit the character -void DzUnrealMorphSelectionDialog::HandleLegJCMMorphsButton() -{ - QStringList MorphsToAdd; - - MorphsToAdd.append("pJCMBigToeDown_45_L"); - MorphsToAdd.append("pJCMBigToeDown_45_R"); - MorphsToAdd.append("pJCMFootDwn_75_L"); - MorphsToAdd.append("pJCMFootDwn_75_R"); - MorphsToAdd.append("pJCMFootUp_40_L"); - MorphsToAdd.append("pJCMFootUp_40_R"); - MorphsToAdd.append("pJCMShinBend_155_L"); - MorphsToAdd.append("pJCMShinBend_155_R"); - MorphsToAdd.append("pJCMShinBend_90_L"); - MorphsToAdd.append("pJCMShinBend_90_R"); - MorphsToAdd.append("pJCMThighBack_35_L"); - MorphsToAdd.append("pJCMThighBack_35_R"); - MorphsToAdd.append("pJCMThighFwd_115_L"); - MorphsToAdd.append("pJCMThighFwd_115_R"); - MorphsToAdd.append("pJCMThighFwd_57_L"); - MorphsToAdd.append("pJCMThighFwd_57_R"); - MorphsToAdd.append("pJCMThighSide_85_L"); - MorphsToAdd.append("pJCMThighSide_85_R"); - MorphsToAdd.append("pJCMToesUp_60_L"); - MorphsToAdd.append("pJCMToesUp_60_R"); - - // Add the list for export - foreach(QString MorphName, MorphsToAdd) - { - if (morphs.contains(MorphName) && !morphsToExport.contains(morphs[MorphName])) - { - morphsToExport.append(morphs[MorphName]); - } - } - RefreshExportMorphList(); -} - -// Hard coded list of morphs for Genesis 3 and 8 -// It just adds them all, the other functions will ignore any that don't fit the character -void DzUnrealMorphSelectionDialog::HandleTorsoJCMMorphsButton() -{ - QStringList MorphsToAdd; - - MorphsToAdd.append("pJCMAbdomen2Fwd_40"); - MorphsToAdd.append("pJCMAbdomen2Side_24_L"); - MorphsToAdd.append("pJCMAbdomen2Side_24_R"); - MorphsToAdd.append("pJCMAbdomenFwd_35"); - MorphsToAdd.append("pJCMAbdomenLowerFwd_Navel"); - MorphsToAdd.append("pJCMAbdomenUpperFwd_Navel"); - MorphsToAdd.append("pJCMHeadBack_27"); - MorphsToAdd.append("pJCMHeadFwd_25"); - MorphsToAdd.append("pJCMNeckBack_27"); - MorphsToAdd.append("pJCMNeckFwd_35"); - MorphsToAdd.append("pJCMNeckLowerSide_40_L"); - MorphsToAdd.append("pJCMNeckLowerSide_40_R"); - MorphsToAdd.append("pJCMNeckTwist_22_L"); - MorphsToAdd.append("pJCMNeckTwist_22_R"); - MorphsToAdd.append("pJCMNeckTwist_Reverse"); - MorphsToAdd.append("pJCMPelvisFwd_25"); - MorphsToAdd.append("pJCMChestFwd_35"); - MorphsToAdd.append("pJCMChestSide_20_L"); - MorphsToAdd.append("pJCMChestSide_20_R"); - - // Add the list for export - foreach(QString MorphName, MorphsToAdd) - { - if (morphs.contains(MorphName) && !morphsToExport.contains(morphs[MorphName])) - { - morphsToExport.append(morphs[MorphName]); - } - } - RefreshExportMorphList(); -} - -// Refresh the Right export list -void DzUnrealMorphSelectionDialog::RefreshExportMorphList() -{ - morphExportListWidget->clear(); - foreach(MorphInfo morphInfo, morphsToExport) - { - SortingListItem* item = new SortingListItem(); - item->setText(morphInfo.Label); - item->setData(Qt::UserRole, morphInfo.Name); - - morphExportListWidget->addItem(item); - } - SavePresetFile(NULL); -} - -// Refresh the list of preset csvs from the files in the folder -void DzUnrealMorphSelectionDialog::RefreshPresetsCombo() -{ - disconnect(presetCombo, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(HandlePresetChanged(const QString &))); - - presetCombo->clear(); - presetCombo->addItem("None"); - - QDirIterator it(presetsFolder, QStringList() << "*.csv", QDir::NoFilter, QDirIterator::NoIteratorFlags); - while (it.hasNext()) - { - QString Path = it.next(); - QString NewPath = Path.right(Path.length() - presetsFolder.length() - 1); - presetCombo->addItem(NewPath); - } - connect(presetCombo, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(HandlePresetChanged(const QString &))); -} - -// Call when the preset combo is changed by the user -void DzUnrealMorphSelectionDialog::HandlePresetChanged(const QString& presetName) -{ - morphsToExport.clear(); - QString PresetFilePath = presetsFolder + QDir::separator() + presetName; - - QFile file(PresetFilePath); - if (!file.open(QIODevice::ReadOnly)) { - // TODO: should be an error dialog - return; - } - - // load the selected csv from disk into the export list on the right - QTextStream InStream(&file); - - while (!InStream.atEnd()) { - QString MorphLine = InStream.readLine(); - if (MorphLine.endsWith("\"Export\"")) - { - QStringList Items = MorphLine.split(","); - QString MorphName = Items[0].replace("\"", ""); - if (morphs.contains(MorphName)) - { - morphsToExport.append(morphs[MorphName]); - } - } - } - - RefreshExportMorphList(); - file.close(); -} - -// Get the morph string in the format for the Daz FBX Export -QString DzUnrealMorphSelectionDialog::GetMorphString() -{ - if (morphsToExport.length() == 0) - { - return ""; - } - QStringList morphNamesToExport; - foreach(MorphInfo exportMorph, morphsToExport) - { - morphNamesToExport.append(exportMorph.Name); - } - QString morphString = morphNamesToExport.join("\n1\n"); - morphString += "\n1\n.CTRLVS\n2\nAnything\n0"; - return morphString; -} - -// Get the morph string in the format used for presets -QString DzUnrealMorphSelectionDialog::GetMorphCSVString() -{ - morphList.clear(); - QString morphString; - foreach(MorphInfo exportMorph, morphsToExport) - { - morphList.append(exportMorph.Name); - morphString += "\"" + exportMorph.Name + "\",\"Export\"\n"; - } - morphString += "\".CTRLVS\", \"Ignore\"\n"; - morphString += "\"Anything\", \"Bake\"\n"; - return morphString; -} - -// Get the morph string in an internal name = friendly name format -// Used to rename them to the friendly name in Unreal -QMap DzUnrealMorphSelectionDialog::GetMorphRenaming() -{ - morphNameMapping.clear(); - foreach(MorphInfo exportMorph, morphsToExport) - { - morphNameMapping.insert(exportMorph.Name, exportMorph.Label); - } - - return morphNameMapping; -} - -#include "moc_DzUnrealMorphSelectionDialog.cpp"