From 363d6a7798a60be3397f35daa4cf2204b21ae993 Mon Sep 17 00:00:00 2001 From: Lukas Cone Date: Sun, 8 Dec 2019 15:16:17 +0100 Subject: [PATCH] Master update 2 LLVM Reformatting Moved to CMake project. Added support for global framed animations. Fixed some crash exceptions. Rearranged tab order for dialogs. Added key shortcuts for dialogs. Added support for 2020. --- .gitignore | 4 +- .vscode/launch.json | 19 + 3rd_party/xenolib | 2 +- CMakeLists.txt | 40 + README.md | 13 +- XenoMax.sln | 143 --- XenoMax.vcxproj | 150 --- XenoMax.vcxproj.filters | 44 - XenoMax.vcxproj.user | 8 - src/DllEntry.cpp | 156 ++- src/XenoImp.cpp | 2123 +++++++++++++++++++-------------------- src/XenoImp.rc | 31 +- src/XenoImport.cpp | 423 ++++---- src/XenoImport.h | 126 ++- src/XenoMax.h | 39 +- src/resource.h | 5 +- 16 files changed, 1452 insertions(+), 1874 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 CMakeLists.txt delete mode 100644 XenoMax.sln delete mode 100644 XenoMax.vcxproj delete mode 100644 XenoMax.vcxproj.filters delete mode 100644 XenoMax.vcxproj.user diff --git a/.gitignore b/.gitignore index 5efb97c..41e910e 100644 --- a/.gitignore +++ b/.gitignore @@ -31,7 +31,9 @@ *.out *.app *.vs/ -ObjDump/* +build/* [bB]in/* *.aps *.bat +project.h +*.7z diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..e9f26c2 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(Windows) Spustit", + "type": "cppvsdbg", + "request": "launch", + "program": "C:/Program Files/Autodesk/3ds Max 2017/3dsmax.exe", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false + } + ] +} \ No newline at end of file diff --git a/3rd_party/xenolib b/3rd_party/xenolib index 5719a47..2f14c0b 160000 --- a/3rd_party/xenolib +++ b/3rd_party/xenolib @@ -1 +1 @@ -Subproject commit 5719a470b6a7995f5004389db64d13a8714888b8 +Subproject commit 2f14c0bd3765ee4439e91034028c0acb0493f95f diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..42bfa9a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.3) + +project(XenoMax VERSION 1.2) + +set(TARGETEX_LOCATION 3rd_party/XenoLib/3rd_party/PreCore/cmake) +include(${TARGETEX_LOCATION}/3dsmax.cmake) + +set (XenoLibLibraryPath ../XenoLib_${CMAKE_GENERATOR_PLATFORM}_${CHAR_TYPE}) + +add_subdirectory(3rd_party/XenoLib ${XenoLibLibraryPath}) + +build_target( + TYPE SHARED + SOURCES + src/DllEntry.cpp + src/XenoImp.cpp + src/XenoImport.cpp + src/XenoImp.rc + src/XenoMax.def + ${MAX_EX_DIR}/win/About.rc + LINKS + gdiplus bmm core Morpher XenoLib flt mesh maxutil maxscrpt paramblk2 geom + DEFINITIONS + ${MaxDefinitions} + INCLUDES + ${MaxSDK}/include + 3rd_party/XenoLib/include + 3rd_party/XenoLib/3rd_party/PreCore + LINK_DIRS + ${MaxSDKLibrariesPath} + AUTHOR "Lukas Cone" + DESCR "Xenoblade Engine 3DS Max Plugin" + NAME "XenoMax" + START_YEAR 2017 + PROPERTIES + SUFFIX .dlu + ${MaxProperties} +) + +build_morpher() \ No newline at end of file diff --git a/README.md b/README.md index 616ef2e..9f10eb3 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,24 @@ # XenoMax + XenoMax is an importer for 3ds max for formats used by Xenoblade Engine.\ Builded with VS2015.\ -Supported 3ds max versions: **2012 - 2019**\ +Supported 3ds max versions: **2012 - 2020**\ Tested on 3ds max versions: **2017** ## Building -### Editing .vcxproj -All essential configurations are within **PropertyGroup Label="MAXConfigurations"** field. -- **MaxSDK**: changes path where is your MAX SDK installation. -If your MAX SDK installation is somewhere else than default path stated in this field, you can edit it here. -- **MaxDebugConfiguration**: changes 3ds max version and platform, so all necessary files are copied into plugin directory, this will enable post-build event. You must have set ***Working Directory*** under ***Debugging*** in ***Project Properties*** to location, where 3ds max is installed (where 3dsmax.exe is). + +Head to the [Building a 3ds max CMake projects](https://github.com/PredatorCZ/PreCore/wiki/Building-a-3ds-max-CMake-projects) wiki page. ## Installation + ### [Latest Release](https://github.com/PredatorCZ/XenoMax/releases/) + Move corresponding .dlu located in correct version folder into ***%3ds max installation directory%/plugins***. \ Versions must match!\ Additionally plugin will require **Visual C++ Redistributable for Visual Studio 2015** to be installed in order to work. ## License + This plugin is available under GPL v3 license. (See LICENSE.md) This plugin uses following libraries: diff --git a/XenoMax.sln b/XenoMax.sln deleted file mode 100644 index 979d450..0000000 --- a/XenoMax.sln +++ /dev/null @@ -1,143 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.28917.181 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XenoMax", "XenoMax.vcxproj", "{6671F0BA-6FB8-4F35-8392-0676D05113A8}" - ProjectSection(ProjectDependencies) = postProject - {C5759C7C-08EE-4D40-8D82-FF952A723CB0} = {C5759C7C-08EE-4D40-8D82-FF952A723CB0} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XenoLib", "3rd_party\xenolib\XenoLib.vcxproj", "{C5759C7C-08EE-4D40-8D82-FF952A723CB0}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - 2010|x64 = 2010|x64 - 2010|x86 = 2010|x86 - 2011|x64 = 2011|x64 - 2011|x86 = 2011|x86 - 2012|x64 = 2012|x64 - 2012|x86 = 2012|x86 - 2013|x64 = 2013|x64 - 2013|x86 = 2013|x86 - 2014|x64 = 2014|x64 - 2014|x86 = 2014|x86 - 2015|x64 = 2015|x64 - 2015|x86 = 2015|x86 - 2016|x64 = 2016|x64 - 2016|x86 = 2016|x86 - 2017|x64 = 2017|x64 - 2017|x86 = 2017|x86 - 2018|x64 = 2018|x64 - 2018|x86 = 2018|x86 - 2019|x64 = 2019|x64 - 2019|x86 = 2019|x86 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2010|x64.ActiveCfg = 2010|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2010|x64.Build.0 = 2010|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2010|x86.ActiveCfg = 2010|Win32 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2010|x86.Build.0 = 2010|Win32 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2011|x64.ActiveCfg = 2011|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2011|x64.Build.0 = 2011|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2011|x86.ActiveCfg = 2011|Win32 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2011|x86.Build.0 = 2011|Win32 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2012|x64.ActiveCfg = 2012|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2012|x64.Build.0 = 2012|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2012|x86.ActiveCfg = 2012|Win32 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2012|x86.Build.0 = 2012|Win32 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2013|x64.ActiveCfg = 2013|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2013|x64.Build.0 = 2013|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2013|x86.ActiveCfg = 2013|Win32 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2013|x86.Build.0 = 2013|Win32 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2014|x64.ActiveCfg = 2014|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2014|x64.Build.0 = 2014|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2014|x86.ActiveCfg = 2014|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2014|x86.Build.0 = 2014|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2015|x64.ActiveCfg = 2015|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2015|x64.Build.0 = 2015|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2015|x86.ActiveCfg = 2015|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2015|x86.Build.0 = 2015|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2016|x64.ActiveCfg = 2016|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2016|x64.Build.0 = 2016|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2016|x86.ActiveCfg = 2016|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2016|x86.Build.0 = 2016|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2017|x64.ActiveCfg = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2017|x64.Build.0 = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2017|x86.ActiveCfg = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2017|x86.Build.0 = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2018|x64.ActiveCfg = 2018|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2018|x64.Build.0 = 2018|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2018|x86.ActiveCfg = 2018|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2018|x86.Build.0 = 2018|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2019|x64.ActiveCfg = 2019|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2019|x64.Build.0 = 2019|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2019|x86.ActiveCfg = 2019|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.2019|x86.Build.0 = 2019|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.Debug|x64.ActiveCfg = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.Debug|x64.Build.0 = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.Debug|x86.ActiveCfg = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.Debug|x86.Build.0 = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.Release|x64.ActiveCfg = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.Release|x64.Build.0 = 2017|x64 - {6671F0BA-6FB8-4F35-8392-0676D05113A8}.Release|x86.ActiveCfg = 2017|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2010|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2010|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2010|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2010|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2011|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2011|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2011|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2011|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2012|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2012|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2012|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2012|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2013|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2013|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2013|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2013|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2014|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2014|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2014|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2014|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2015|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2015|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2015|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2015|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2016|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2016|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2016|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2016|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2017|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2017|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2017|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2017|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2018|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2018|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2018|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2018|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2019|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2019|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2019|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.2019|x86.Build.0 = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.Debug|x64.ActiveCfg = Debug|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.Debug|x64.Build.0 = Debug|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.Debug|x86.ActiveCfg = Debug|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.Debug|x86.Build.0 = Debug|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.Release|x64.ActiveCfg = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.Release|x64.Build.0 = Release|x64 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.Release|x86.ActiveCfg = Release|Win32 - {C5759C7C-08EE-4D40-8D82-FF952A723CB0}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {13D5B247-D27E-4D26-BB0A-2C52CDCD9775} - EndGlobalSection -EndGlobal diff --git a/XenoMax.vcxproj b/XenoMax.vcxproj deleted file mode 100644 index 59132db..0000000 --- a/XenoMax.vcxproj +++ /dev/null @@ -1,150 +0,0 @@ - - - - - 2010 - Win32 - - - 2010 - x64 - - - 2011 - Win32 - - - 2011 - x64 - - - 2012 - Win32 - - - 2012 - x64 - - - 2013 - Win32 - - - 2013 - x64 - - - 2014 - x64 - - - 2015 - x64 - - - 2016 - x64 - - - 2017 - x64 - - - 2019 - x64 - - - 2018 - x64 - - - - - - - - - - - - - - - - - - C:\Program Files\Autodesk\3ds Max $(Configuration) SDK\maxsdk - 2017|x64 - - - {6671F0BA-6FB8-4F35-8392-0676D05113A8} - XenoMax - DynamicLibrary - true - false - 10.0.17763.0 - - - /x64/lib - - - /lib - - - /lib/x64/Release - - - $(MaxSDK)$(MaxSDKLibsRPath) - - - - false - v140 - true - NotSet - Unicode - Bin\$(Platform)_$(Configuration)\ - ObjDump\$(Platform)_$(Configuration)\ - - - - - - - - - - - - - Level3 - MaxSpeed - true - true - true - _USRDLL;WINVER=0x0601;_WIN32_WINNT=0x0601;_WIN32_WINDOWS=0x0601;_WIN32_IE=0x0800;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_SCL_SECURE_NO_DEPRECATE;ISOLATION_AWARE_ENABLED=1;MODULE_NAME=$(TargetFileName);BUILDVERSION=$(Configuration);%(PreprocessorDefinitions) - $(MaxSDK)\include;3rd_party/XenoLib/3rd_party/precore;3rd_party/XenoLib/include;%(AdditionalIncludeDirectories) - /GR /w34996 /we4706 /we4390 /we4557 /we4546 /we4545 /we4295 /we4310 /we4130 /we4611 /we4213 /we4121 /we4715 /w34701 /w34265 /wd4244 /wd4018 /wd4819 - Fast - - - 3rd_party/XenoLib/lib/$(Platform)_Release;$(MaxSDKLibs);$(IntDir);%(AdditionalLibraryDirectories) - gdiplus.lib;XenoLib.lib;Morpher.lib;bmm.lib;core.lib;flt.lib;mesh.lib;maxutil.lib;maxscrpt.lib;paramblk2.lib;geom.lib;%(AdditionalDependencies) - true - true - Windows - src/XenoMax.def - $(IntDir)$(TargetName).lib - $(OutDir)$(TargetName).dlu - - - COPY /Y /V "$(OutDir)$(TargetName).dlu" /B "$(LocalDebuggerWorkingDirectory)Plugins\" /B - - - lib /def:3rd_party/XenoLib/3rd_party/PreCore/MAXEx/Morpher$(PlatformTarget).def /OUT:$(IntDir)Morpher.lib /MACHINE:$(PlatformTarget) - - - - - - \ No newline at end of file diff --git a/XenoMax.vcxproj.filters b/XenoMax.vcxproj.filters deleted file mode 100644 index bb7c49a..0000000 --- a/XenoMax.vcxproj.filters +++ /dev/null @@ -1,44 +0,0 @@ - - - - - {c43e6880-6404-4392-8eda-f20781f73db6} - - - {731c501f-a903-44ac-96cf-441b7ab33eed} - - - {ada31279-8f32-451b-897b-0098db7e1352} - - - - - Source - - - Source - - - Source - - - - - Headers - - - Headers - - - Headers - - - - - Resources - - - Resources - - - \ No newline at end of file diff --git a/XenoMax.vcxproj.user b/XenoMax.vcxproj.user deleted file mode 100644 index 9d4ba55..0000000 --- a/XenoMax.vcxproj.user +++ /dev/null @@ -1,8 +0,0 @@ - - - - C:\Program Files\Autodesk\3ds Max 2017\3dsmax.exe - C:\Program Files\Autodesk\3ds Max 2017\ - WindowsLocalDebugger - - \ No newline at end of file diff --git a/src/DllEntry.cpp b/src/DllEntry.cpp index 91805ab..1023132 100644 --- a/src/DllEntry.cpp +++ b/src/DllEntry.cpp @@ -1,26 +1,26 @@ -/* Xenoblade Tool for 3ds Max - Copyright(C) 2017-2019 Lukas Cone +/* Xenoblade Tool for 3ds Max + Copyright(C) 2017-2019 Lukas Cone - This program is free software : you can redistribute it and / or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software : you can redistribute it and / or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program.If not, see . + You should have received a copy of the GNU General Public License + along with this program.If not, see . */ #include "XenoMax.h" -#include -#include "datas/supercore.hpp" #include "datas/MasterPrinter.hpp" +#include "datas/supercore.hpp" +#include -ClassDesc2* GetXenoImpDesc(); +ClassDesc2 *GetXenoImpDesc(); HINSTANCE hInstance; int controlsInit = FALSE; @@ -28,109 +28,85 @@ Gdiplus::GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; TSTRING temporalLogStorage; -// This function is called by Windows when the DLL is loaded. This +// This function is called by Windows when the DLL is loaded. This // function may also be called many times during time critical operations // like rendering. Therefore developers need to be careful what they // do inside this function. In the code below, note how after the DLL is // loaded the first time only a few statements are executed. -BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID /*lpvReserved*/) -{ - if( fdwReason == DLL_PROCESS_ATTACH ) - { - //MaxSDK::Util::UseLanguagePackLocale(); - // Hang on to this DLL's instance handle. - hInstance = hinstDLL; - DisableThreadLibraryCalls(hInstance); - // DO NOT do any initialization here. Use LibInitialize() instead. - } - return(TRUE); +BOOL WINAPI DllMain(HINSTANCE hinstDLL, ULONG fdwReason, + LPVOID /*lpvReserved*/) { + if (fdwReason == DLL_PROCESS_ATTACH) { + // MaxSDK::Util::UseLanguagePackLocale(); + // Hang on to this DLL's instance handle. + hInstance = hinstDLL; + DisableThreadLibraryCalls(hInstance); + // DO NOT do any initialization here. Use LibInitialize() instead. + } + return (TRUE); } // This function returns a string that describes the DLL and where the user // could purchase the DLL if they don't have it. -__declspec( dllexport ) const TCHAR* LibDescription() -{ - return NULL; -} +__declspec(dllexport) const TCHAR *LibDescription() { return _T(XenoMax_DESC); } // This function returns the number of plug-in classes this DLL -//TODO: Must change this number when adding a new class -__declspec( dllexport ) int LibNumberClasses() -{ - return 1; -} +// TODO: Must change this number when adding a new class +__declspec(dllexport) int LibNumberClasses() { return 1; } // This function returns the number of plug-in classes this DLL -__declspec( dllexport ) ClassDesc* LibClassDesc(int i) -{ - switch(i) { - case 0: return GetXenoImpDesc(); - default: return 0; - } +__declspec(dllexport) ClassDesc *LibClassDesc(int i) { + switch (i) { + case 0: + return GetXenoImpDesc(); + default: + return 0; + } } -// This function returns a pre-defined constant indicating the version of +// This function returns a pre-defined constant indicating the version of // the system under which it was compiled. It is used to allow the system // to catch obsolete DLLs. -__declspec( dllexport ) ULONG LibVersion() -{ - return VERSION_3DSMAX; -} +__declspec(dllexport) ULONG LibVersion() { return VERSION_3DSMAX; } -void PrintLog(const TCHAR* msg) -{ - if (!IsWindowVisible(the_listener_window) || IsIconic(the_listener_window)) - show_listener(); +void PrintLog(const TCHAR *msg) { + if (!IsWindowVisible(the_listener_window) || IsIconic(the_listener_window)) + show_listener(); - MAXScript_TLS *tls = (MAXScript_TLS *)TlsGetValue(thread_locals_index); + MAXScript_TLS *tls = (MAXScript_TLS *)TlsGetValue(thread_locals_index); - if (!tls) - { - temporalLogStorage.append(msg); - return; - } + if (!tls) { + temporalLogStorage.append(msg); + return; + } - tls->current_stdout->printf(msg); - tls->current_stdout->flush(); + tls->current_stdout->printf(msg); + tls->current_stdout->flush(); } -void PrintOffThreadMessages() -{ - if (!temporalLogStorage.length()) - return; +void PrintOffThreadMessages() { + if (!temporalLogStorage.length()) + return; - PrintLog(temporalLogStorage.c_str()); - temporalLogStorage.~basic_string(); + PrintLog(temporalLogStorage.c_str()); + temporalLogStorage.~basic_string(); } -// This function is called once, right after your plugin has been loaded by 3ds Max. -// Perform one-time plugin initialization in this method. -// Return TRUE if you deem your plugin successfully loaded, or FALSE otherwise. If -// the function returns FALSE, the system will NOT load the plugin, it will then call FreeLibrary -// on your DLL, and send you a message. -__declspec( dllexport ) int LibInitialize(void) -{ - printer.AddPrinterFunction(PrintLog); - Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); - return TRUE; +// This function is called once, right after your plugin has been loaded by 3ds +// Max. Perform one-time plugin initialization in this method. Return TRUE if +// you deem your plugin successfully loaded, or FALSE otherwise. If the function +// returns FALSE, the system will NOT load the plugin, it will then call +// FreeLibrary on your DLL, and send you a message. +__declspec(dllexport) int LibInitialize(void) { + printer.AddPrinterFunction(PrintLog); + Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); + return TRUE; } -// This function is called once, just before the plugin is unloaded. +// This function is called once, just before the plugin is unloaded. // Perform one-time plugin un-initialization in this method." // The system doesn't pay attention to a return value. -__declspec( dllexport ) int LibShutdown(void) -{ - Gdiplus::GdiplusShutdown(gdiplusToken); - return TRUE; +__declspec(dllexport) int LibShutdown(void) { + Gdiplus::GdiplusShutdown(gdiplusToken); + return TRUE; } - -TCHAR *GetString(int id) -{ - static TCHAR buf[256]; - - if (hInstance) - return LoadString(hInstance, id, buf, _countof(buf)) ? buf : NULL; - return NULL; -} - diff --git a/src/XenoImp.cpp b/src/XenoImp.cpp index 49b0abd..6816cf1 100644 --- a/src/XenoImp.cpp +++ b/src/XenoImp.cpp @@ -1,1294 +1,1189 @@ -/* Xenoblade Tool for 3ds Max - Copyright(C) 2017-2019 Lukas Cone +/* Xenoblade Tool for 3ds Max + Copyright(C) 2017-2019 Lukas Cone - This program is free software : you can redistribute it and / or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software : you can redistribute it and / or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program.If not, see . + You should have received a copy of the GNU General Public License + along with this program.If not, see . */ #include -#include -#include +#include +#include #include +#include #include -#include <../samples/modifiers/morpher/include/MorpherApi.h> -#include #include -#include +#include #include "MAXex/Maps.h" +#include <../samples/modifiers/morpher/include/MorpherApi.h> -#include "XenoImport.h" -#include "XenoMax.h" +#include "BC.h" #include "MXMD.h" #include "SAR.h" -#include "BC.h" +#include "XenoImport.h" +#include "XenoMax.h" +#include "MAXex/NodeSuffix.h" #include "datas/esstring.h" -#include "datas/masterprinter.hpp" #include "datas/fileinfo.hpp" -#include "MAXex/NodeSuffix.h" +#include "datas/masterprinter.hpp" -#define XenoImp_CLASS_ID Class_ID(0xabe2469a, 0xa9eaf87a) -#define HavokImport_CLASS_ID Class_ID(0xad115395, 0x924c02c0) +#define XenoImp_CLASS_ID Class_ID(0xabe2469a, 0xa9eaf87a) +#define HavokImport_CLASS_ID Class_ID(0xad115395, 0x924c02c0) static const TCHAR _className[] = _T("XenoImp"); -class XenoImp : public SceneImport, XenoImport -{ +class XenoImp : public SceneImport, XenoImport { public: - //Constructor/Destructor - XenoImp(); - virtual ~XenoImp(); - - virtual int ExtCount(); // Number of extensions supported - virtual const TCHAR * Ext(int n); // Extension #n (i.e. "3DS") - virtual const TCHAR * LongDesc(); // Long ASCII description (i.e. "Autodesk 3D Studio File") - virtual const TCHAR * ShortDesc(); // Short ASCII description (i.e. "3D Studio") - virtual const TCHAR * AuthorName(); // ASCII Author name - virtual const TCHAR * CopyrightMessage(); // ASCII Copyright message - virtual const TCHAR * OtherMessage1(); // Other message #1 - virtual const TCHAR * OtherMessage2(); // Other message #2 - virtual unsigned int Version(); // Version number * 100 (i.e. v3.01 = 301) - virtual void ShowAbout(HWND hWnd); // Show DLL's "About..." box - virtual int DoImport(const TCHAR *name, ImpInterface *i, Interface *gi, BOOL suppressPrompts = FALSE); // Import file - - std::vector remapNodes; - std::vector outMats; - std::vector texmaps; - - void LoadSkeleton(BCSKEL *skel); - void LoadAnimation(BCANIM *anim); - void LoadModels(MXMD *model); - INodeTab LoadMeshes(MXMD *model, MXMDModel::Ptr &mdl, int curGroup); - int LoadTextures(MXMD *model); - void LoadMaterials(MXMD *model); - int LoadInstances(MXMD *model); - void LoadModelPose(MXMDModel::Ptr &model); - void ApplySkin(MXMDGeomBuffers::Ptr &buff, MXMDMeshObject::Ptr &mesh, INodeSuffixer &nde, Face *mfac, MXMDVertexDescriptor *skinDesc); - void ApplyMorph(MXMDMorphTargets::Ptr &morphs, INode *node, Mesh *mesh, MXMDMeshObject::Ptr &msh, MXMDModel::Ptr &mdl, MXMDGeomBuffers::Ptr &buff); - - int LoadARC(const TCHAR *name, BOOL suppressPrompts, bool subLoad = false); - int LoadSKL(const TCHAR *name, BOOL suppressPrompts, bool subLoad = false); - int LoadMOT(const TCHAR *name, BOOL suppressPrompts, bool subLoad = false); - int LoadANM(const TCHAR *name, BOOL suppressPrompts, bool subLoad = false); - int LoadMXMD(const TCHAR *name, ImpInterface *importerInt, Interface *ip, BOOL suppressPrompts); + // Constructor/Destructor + XenoImp(); + virtual ~XenoImp(); + + virtual int ExtCount(); // Number of extensions supported + virtual const TCHAR *Ext(int n); // Extension #n (i.e. "3DS") + virtual const TCHAR * + LongDesc(); // Long ASCII description (i.e. "Autodesk 3D Studio File") + virtual const TCHAR * + ShortDesc(); // Short ASCII description (i.e. "3D Studio") + virtual const TCHAR *AuthorName(); // ASCII Author name + virtual const TCHAR *CopyrightMessage(); // ASCII Copyright message + virtual const TCHAR *OtherMessage1(); // Other message #1 + virtual const TCHAR *OtherMessage2(); // Other message #2 + virtual unsigned int Version(); // Version number * 100 (i.e. v3.01 = 301) + virtual void ShowAbout(HWND hWnd); // Show DLL's "About..." box + virtual int DoImport(const TCHAR *name, ImpInterface *i, Interface *gi, + BOOL suppressPrompts = FALSE); // Import file + + std::vector remapNodes; + std::vector outMats; + std::vector texmaps; + + void LoadSkeleton(BCSKEL *skel); + void LoadAnimation(BCANIM *anim); + void LoadModels(MXMD *model); + INodeTab LoadMeshes(MXMD *model, MXMDModel::Ptr &mdl, int curGroup); + int LoadTextures(MXMD *model); + void LoadMaterials(MXMD *model); + int LoadInstances(MXMD *model); + void LoadModelPose(MXMDModel::Ptr &model); + void ApplySkin(MXMDGeomBuffers::Ptr &buff, MXMDMeshObject::Ptr &mesh, + INodeSuffixer &nde, Face *mfac, + MXMDVertexDescriptor *skinDesc); + void ApplyMorph(MXMDMorphTargets::Ptr &morphs, INode *node, Mesh *mesh, + MXMDMeshObject::Ptr &msh, MXMDModel::Ptr &mdl, + MXMDGeomBuffers::Ptr &buff); + + int LoadARC(const TCHAR *name, BOOL suppressPrompts, bool subLoad = false); + int LoadSKL(const TCHAR *name, BOOL suppressPrompts, bool subLoad = false); + int LoadMOT(const TCHAR *name, BOOL suppressPrompts, bool subLoad = false); + int LoadANM(const TCHAR *name, BOOL suppressPrompts, bool subLoad = false); + int LoadMXMD(const TCHAR *name, ImpInterface *importerInt, Interface *ip, + BOOL suppressPrompts); }; -static class : public ClassDesc2 -{ +static class : public ClassDesc2 { public: - virtual int IsPublic() { return TRUE; } - virtual void* Create(BOOL) { return new XenoImp(); } - virtual const TCHAR * ClassName() { return _className; } - virtual SClass_ID SuperClassID() { return SCENE_IMPORT_CLASS_ID; } - virtual Class_ID ClassID() { return XenoImp_CLASS_ID; } - virtual const TCHAR* Category() { return NULL; } - virtual const TCHAR* InternalName() { return _className; } // returns fixed parsable name (scripter-visible name) - virtual HINSTANCE HInstance() { return hInstance; } // returns owning module handle -}xenoImpDesc; + virtual int IsPublic() { return TRUE; } + virtual void *Create(BOOL) { return new XenoImp(); } + virtual const TCHAR *ClassName() { return _className; } + virtual SClass_ID SuperClassID() { return SCENE_IMPORT_CLASS_ID; } + virtual Class_ID ClassID() { return XenoImp_CLASS_ID; } + virtual const TCHAR *Category() { return NULL; } + virtual const TCHAR *InternalName() { + return _className; + } // returns fixed parsable name (scripter-visible name) + virtual HINSTANCE HInstance() { + return hInstance; + } // returns owning module handle +} xenoImpDesc; + +ClassDesc2 *GetXenoImpDesc() { return &xenoImpDesc; } +//--- ApexImp ------------------------------------------------------- +XenoImp::XenoImp() {} + +XenoImp::~XenoImp() {} + +int XenoImp::ExtCount() { return 6; } + +const TCHAR *XenoImp::Ext(int n) { + switch (n) { + case 1: + return _T("camdo"); + case 2: + return _T("arc"); + case 3: + return _T("skl"); + case 4: + return _T("mot"); + case 5: + return _T("anm"); + default: + break; + } + + return _T("wimdo"); +} -ClassDesc2* GetXenoImpDesc() { return &xenoImpDesc; } +const TCHAR *XenoImp::LongDesc() { return _T("Xenoblade Inport"); } -//--- ApexImp ------------------------------------------------------- -XenoImp::XenoImp() -{ +const TCHAR *XenoImp::ShortDesc() { return _T("Xenoblade Import"); } -} +const TCHAR *XenoImp::AuthorName() { return _T(XenoMax_AUTHOR); } -XenoImp::~XenoImp() -{ +const TCHAR *XenoImp::CopyrightMessage() { return _T(XenoMax_COPYRIGHT); } -} +const TCHAR *XenoImp::OtherMessage1() { return _T(""); } -int XenoImp::ExtCount() -{ - return 6; -} +const TCHAR *XenoImp::OtherMessage2() { return _T(""); } -const TCHAR *XenoImp::Ext(int n) -{ - switch (n) - { - case 1: - return _T("camdo"); - case 2: - return _T("arc"); - case 3: - return _T("skl"); - case 4: - return _T("mot"); - case 5: - return _T("anm"); - default: - break; - } - - return _T("wimdo"); -} +unsigned int XenoImp::Version() { return XENOMAX_VERSIONINT; } -const TCHAR *XenoImp::LongDesc() -{ - return _T("Xenoblade Inport"); -} - -const TCHAR *XenoImp::ShortDesc() -{ - return _T("Xenoblade Import"); -} +void XenoImp::ShowAbout(HWND hWnd) { ShowAboutDLG(hWnd); } -const TCHAR *XenoImp::AuthorName() -{ - return _T("Lukas Cone"); -} +void XenoImp::LoadSkeleton(BCSKEL *skel) { + BCSKEL::BoneData *boneData = skel->boneData.ptr; -const TCHAR *XenoImp::CopyrightMessage() -{ - return _T("Copyright (C) 2017-2019 Lukas Cone"); -} + std::vector nodes; -const TCHAR *XenoImp::OtherMessage1() -{ - return _T(""); -} + for (int b = 0; b < boneData->boneLinks.count; b++) { + const char *_boneName = boneData->boneNames.data[b].name; + TSTRING boneName = esString(_boneName); + INode *node = GetCOREInterface()->GetINodeByName(boneName.c_str()); -const TCHAR *XenoImp::OtherMessage2() -{ - return _T(""); -} + if (!node) { + Object *obj = static_cast( + CreateInstance(HELPER_CLASS_ID, Class_ID(DUMMY_CLASS_ID, 0))); + node = GetCOREInterface()->CreateObjectNode(obj); + node->ShowBone(2); + node->SetWireColor(0x80ff); + } -unsigned int XenoImp::Version() -{ - return XENOMAX_VERSIONINT; -} + BCSKEL::BoneTransform &boneTM = boneData->boneTransforms.data[b]; + Matrix3 nodeTM = {}; + nodeTM.SetRotate( + reinterpret_cast(boneTM.rotation).Conjugate()); + nodeTM.SetTrans(reinterpret_cast(boneTM.position) * + IDC_EDIT_SCALE_value); + nodeTM.Scale(reinterpret_cast(boneTM.scale)); -void XenoImp::ShowAbout(HWND hWnd) -{ - ShowAboutDLG(hWnd); -} + short parentID = boneData->boneLinks.data[b]; + if (parentID > -1) { + nodes[parentID]->AttachChild(node); + nodeTM *= nodes[parentID]->GetNodeTM(0); + } else + nodeTM *= corMat; -void XenoImp::LoadSkeleton(BCSKEL *skel) -{ - BCSKEL::BoneData *boneData = skel->boneData.ptr; - - std::vector nodes; - - for (int b = 0; b < boneData->boneLinks.count; b++) - { - const char *_boneName = boneData->boneNames.data[b].name; - TSTRING boneName = esString(_boneName); - INode *node = GetCOREInterface()->GetINodeByName(boneName.c_str()); - - if (!node) - { - Object *obj = static_cast(CreateInstance(HELPER_CLASS_ID, Class_ID(DUMMY_CLASS_ID, 0))); - node = GetCOREInterface()->CreateObjectNode(obj); - node->ShowBone(2); - node->SetWireColor(0x80ff); - } - - BCSKEL::BoneTransform &boneTM = boneData->boneTransforms.data[b]; - Matrix3 nodeTM = {}; - nodeTM.SetRotate(reinterpret_cast(boneTM.rotation).Conjugate()); - nodeTM.SetTrans(reinterpret_cast(boneTM.position) * IDC_EDIT_SCALE_value); - nodeTM.Scale(reinterpret_cast(boneTM.scale)); - - short parentID = boneData->boneLinks.data[b]; - if (parentID > -1) - { - nodes[parentID]->AttachChild(node); - nodeTM *= nodes[parentID]->GetNodeTM(0); - } - else - nodeTM *= corMat; - - node->SetNodeTM(0, nodeTM); - node->SetName(ToBoneName(boneName)); - node->SetUserPropInt(_T("XenoBone"), b); - nodes.push_back(node); - } + node->SetNodeTM(0, nodeTM); + node->SetName(ToBoneName(boneName)); + node->SetUserPropInt(_T("XenoBone"), b); + nodes.push_back(node); + } } -static class : public ITreeEnumProc -{ - const MSTR boneNameHint = _T("XenoBone"); -public: - std::vector bones; - - void RescanBones() - { - bones.clear(); - GetCOREInterface7()->GetScene()->EnumTree(this); - } +static class : public ITreeEnumProc { + const MSTR boneNameHint = _T("XenoBone"); - INode *LookupNode(int ID) - { - for (auto &b : bones) - if (b->UserPropExists(boneNameHint)) - { - int _ID; - b->GetUserPropInt(boneNameHint, _ID); +public: + std::vector bones; - if (_ID == ID) - return b; - } + void RescanBones() { + bones.clear(); + GetCOREInterface7()->GetScene()->EnumTree(this); + } - return nullptr; - } + INode *LookupNode(int ID) { + for (auto &b : bones) + if (b->UserPropExists(boneNameHint)) { + int _ID; + b->GetUserPropInt(boneNameHint, _ID); - int callback(INode *node) - { - if (node->UserPropExists(boneNameHint)) - bones.push_back(node); + if (_ID == ID) + return b; + } - return TREE_CONTINUE; - } -}iBoneScanner; + return nullptr; + } -void XenoImp::LoadAnimation(BCANIM *anim) -{ - iBoneScanner.RescanBones(); + int callback(INode *node) { + if (node->UserPropExists(boneNameHint)) + bones.push_back(node); - TimeValue numTicks = SecToTicks(anim->frameTime * anim->frameCount); - TimeValue ticksPerFrame = GetTicksPerFrame(); - TimeValue overlappingTicks = numTicks % ticksPerFrame; + return TREE_CONTINUE; + } +} iBoneScanner; - if (overlappingTicks > (ticksPerFrame / 2)) - numTicks += ticksPerFrame - overlappingTicks; - else - numTicks -= overlappingTicks; +void XenoImp::LoadAnimation(BCANIM *anim) { + iBoneScanner.RescanBones(); + TimeValue numTicks = SecToTicks(anim->frameTime * anim->frameCount); + TimeValue ticksPerFrame = GetTicksPerFrame(); + TimeValue overlappingTicks = numTicks % ticksPerFrame; - Interval aniRange(0, numTicks); - GetCOREInterface()->SetAnimRange(aniRange); + if (overlappingTicks > (ticksPerFrame / 2)) + numTicks += ticksPerFrame - overlappingTicks; + else + numTicks -= overlappingTicks; - std::vector frameTimes; + Interval aniRange(0, numTicks - ticksPerFrame); + GetCOREInterface()->SetAnimRange(aniRange); - for (TimeValue v = 0; v <= aniRange.End(); v += GetTicksPerFrame()) - frameTimes.push_back(TicksToSec(v)); + std::vector frameTimes; - const int numAniBones = anim->animData->boneCount; + for (TimeValue v = 0; v <= aniRange.End(); v += GetTicksPerFrame()) + frameTimes.push_back(TicksToSec(v)); - for (int a = 0; a < numAniBones; a++) - { - const short boneID = anim->animData->boneTableOffset[a]; + const int numAniBones = anim->animData->boneCount; - if (boneID < 0) - continue; + for (int a = 0; a < numAniBones; a++) { + const short boneID = anim->animData->boneTableOffset[a]; - INode *foundNode = iBoneScanner.LookupNode(a); + if (boneID < 0) + continue; - if (!foundNode) - { - printwarning("[Xeno] Couldn't find XenoBone: ", << a); - continue; - } + INode *foundNode = iBoneScanner.LookupNode(a); - Control *cnt = foundNode->GetTMController(); + if (!foundNode) { + printwarning("[Xeno] Couldn't find XenoBone: ", << a); + continue; + } - if (cnt->GetPositionController()->ClassID() != Class_ID(LININTERP_POSITION_CLASS_ID, 0)) - cnt->SetPositionController((Control *)CreateInstance(CTRL_POSITION_CLASS_ID, Class_ID(LININTERP_POSITION_CLASS_ID, 0))); + Control *cnt = foundNode->GetTMController(); - if (cnt->GetRotationController()->ClassID() != Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) - cnt->SetRotationController((Control *)CreateInstance(CTRL_ROTATION_CLASS_ID, Class_ID(LININTERP_ROTATION_CLASS_ID, 0))); + if (cnt->GetPositionController()->ClassID() != + Class_ID(LININTERP_POSITION_CLASS_ID, 0)) + cnt->SetPositionController((Control *)CreateInstance( + CTRL_POSITION_CLASS_ID, Class_ID(LININTERP_POSITION_CLASS_ID, 0))); - if (cnt->GetScaleController()->ClassID() != Class_ID(LININTERP_SCALE_CLASS_ID, 0)) - cnt->SetScaleController((Control *)CreateInstance(CTRL_SCALE_CLASS_ID, Class_ID(LININTERP_SCALE_CLASS_ID, 0))); + if (cnt->GetRotationController()->ClassID() != + Class_ID(LININTERP_ROTATION_CLASS_ID, 0)) + cnt->SetRotationController((Control *)CreateInstance( + CTRL_ROTATION_CLASS_ID, Class_ID(LININTERP_ROTATION_CLASS_ID, 0))); - SuspendAnimate(); - AnimateOn(); + if (cnt->GetScaleController()->ClassID() != + Class_ID(LININTERP_SCALE_CLASS_ID, 0)) + cnt->SetScaleController((Control *)CreateInstance( + CTRL_SCALE_CLASS_ID, Class_ID(LININTERP_SCALE_CLASS_ID, 0))); - for (auto &t : frameTimes) - { - BCANIM::TransformFrame evalTransform; + SuspendAnimate(); + AnimateOn(); - anim->tracks.data[boneID].GetTransform(t, evalTransform, anim); + cnt->AddNewKey(-ticksPerFrame, 0); - Matrix3 cMat; - Quat &rots = reinterpret_cast(evalTransform.rotation); - cMat.SetRotate(rots.Conjugate()); - cMat.SetTrans(reinterpret_cast(evalTransform.position) * IDC_EDIT_SCALE_value); - cMat.Scale(reinterpret_cast(evalTransform.scale)); + for (auto &t : frameTimes) { + BCANIM::TransformFrame evalTransform; - if (foundNode->GetParentNode()->IsRootNode()) - cMat *= corMat; + anim->tracks.data[boneID].GetTransform(t, evalTransform, anim); - SetXFormPacket packet(cMat); + Matrix3 cMat; + Quat &rots = reinterpret_cast(evalTransform.rotation); + cMat.SetRotate(rots.Conjugate()); + cMat.SetTrans(reinterpret_cast(evalTransform.position) * + IDC_EDIT_SCALE_value); + cMat.Scale(reinterpret_cast(evalTransform.scale)); - cnt->SetValue(SecToTicks(t), &packet); - } + if (!flags[IDC_CH_GLOBAL_FRAMES_checked]) { + if (foundNode->GetParentNode()->IsRootNode()) + cMat *= corMat; - AnimateOff(); + SetXFormPacket packet(cMat); + cnt->SetValue(SecToTicks(t), &packet); + } else { + foundNode->SetNodeTM(SecToTicks(t), cMat * corMat); + } + } - Control *rotControl = (Control *)CreateInstance(CTRL_ROTATION_CLASS_ID, Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)); - rotControl->Copy(cnt->GetRotationController()); - cnt->GetRotationController()->Copy(rotControl); - } + AnimateOff(); + Control *rotControl = (Control *)CreateInstance( + CTRL_ROTATION_CLASS_ID, Class_ID(HYBRIDINTERP_ROTATION_CLASS_ID, 0)); + rotControl->Copy(cnt->GetRotationController()); + cnt->GetRotationController()->Copy(rotControl); + } } -int XenoImp::LoadTextures(MXMD *model) -{ - MXMDTextures::Ptr textures = model->GetTextures(); - MXMDExternalTextures::Ptr exTextures = model->GetExternalTextures(); +int XenoImp::LoadTextures(MXMD *model) { + MXMDTextures::Ptr textures = model->GetTextures(); + MXMDExternalTextures::Ptr exTextures = model->GetExternalTextures(); - if (textures) - { - const int numTextures = textures->GetNumTextures(); + if (textures) { + const int numTextures = textures->GetNumTextures(); - for (int t = 0; t < numTextures; t++) - { - const char *_texName = textures->GetTextureName(t); - TSTRING texName = esStringConvert(_texName); + for (int t = 0; t < numTextures; t++) { + const char *_texName = textures->GetTextureName(t); + TSTRING texName = esStringConvert(_texName); - BitmapTex *maxBitmap = NewDefaultBitmapTex(); - maxBitmap->SetName(texName.c_str()); - texmaps.push_back(maxBitmap); - } + BitmapTex *maxBitmap = NewDefaultBitmapTex(); + maxBitmap->SetName(texName.c_str()); + texmaps.push_back(maxBitmap); + } - return 0; - } + return 0; + } - if (exTextures) - { - const int numTextures = exTextures->GetNumTextures(); + if (exTextures) { + const int numTextures = exTextures->GetNumTextures(); - for (int t = 0; t < numTextures; t++) - { - const int containerID = exTextures->GetContainerID(t); - const int textureID = exTextures->GetExTextureID(t); + for (int t = 0; t < numTextures; t++) { + const int containerID = exTextures->GetContainerID(t); + const int textureID = exTextures->GetExTextureID(t); - TSTRING texName; + TSTRING texName; - if (containerID > -1) - { - texName.append(ToTSTRING(containerID)); - texName.push_back('/'); - } + if (containerID > -1) { + texName.append(ToTSTRING(containerID)); + texName.push_back('/'); + } - if (textureID < 1000) - texName.push_back('0'); - if (textureID < 100) - texName.push_back('0'); - if (textureID < 10) - texName.push_back('0'); + if (textureID < 1000) + texName.push_back('0'); + if (textureID < 100) + texName.push_back('0'); + if (textureID < 10) + texName.push_back('0'); - texName.append(ToTSTRING(textureID)); + texName.append(ToTSTRING(textureID)); - BitmapTex *maxBitmap = NewDefaultBitmapTex(); - maxBitmap->SetName(texName.c_str()); - texmaps.push_back(maxBitmap); - } + BitmapTex *maxBitmap = NewDefaultBitmapTex(); + maxBitmap->SetName(texName.c_str()); + texmaps.push_back(maxBitmap); + } - return 1; - } + return 1; + } - return -1; + return -1; } -void XenoImp::LoadMaterials(MXMD *model) -{ - MXMDMaterials::Ptr mats = model->GetMaterials(); - - if (!mats) - return; - - const int numMats = mats->GetNumMaterials(); - - for (int m = 0; m < numMats; m++) - { - MXMDMaterial::Ptr cMat = mats->GetMaterial(m); - const char *matName = cMat->GetName(); - StdMat *stdMat = NewDefaultStdMat(); - - stdMat->SetName(esStringConvert(matName).c_str()); - - const int numTextures = cMat->GetNumTextures(); - CompositeTex cpTex; - cpTex.DeleteLayer(0); - - for (int t = 0; t < numTextures; t++) - { - const int texID = cMat->GetTextureIndex(t); - - if (texID >= texmaps.size()) - continue; - - BitmapTex *maxBitmap = texmaps[texID]; - TSTRING texName = maxBitmap->GetName(); - - if (texName.find(_T("_SPM")) != texName.npos) - { - if (stdMat->GetSubTexmap(ID_SP)) - { - cpTex.AddLayer(); - CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); - clay.Map(maxBitmap); - } - else - stdMat->SetSubTexmap(ID_SP, maxBitmap); - } - else if (texName.find(_T("_GLO")) != texName.npos) - { - if (stdMat->GetSubTexmap(ID_SI)) - { - cpTex.AddLayer(); - CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); - clay.Map(maxBitmap); - } - else - stdMat->SetSubTexmap(ID_SI, maxBitmap); - } - else if (texName.find(_T("_RFM")) != texName.npos) - { - if (stdMat->GetSubTexmap(ID_SS)) - { - cpTex.AddLayer(); - CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); - clay.Map(maxBitmap); - } - else - stdMat->SetSubTexmap(ID_SS, maxBitmap); - } - else if (texName.find(_T("_NRM")) != texName.npos) - { - if (stdMat->GetSubTexmap(ID_SS)) - { - cpTex.AddLayer(); - CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); - clay.Map(maxBitmap); - } - else - stdMat->SetSubTexmap(ID_SS, NormalBump(maxBitmap)); - } - else if (texName.find(_T("_COL")) != texName.npos) - { - if (stdMat->GetSubTexmap(ID_DI)) - { - cpTex.AddLayer(); - CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); - clay.Map(maxBitmap); - } - else - stdMat->SetSubTexmap(ID_DI, maxBitmap); - } - else - { - cpTex.AddLayer(); - CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); - clay.Map(maxBitmap); - } - - if (cpTex.NumLayers()) - stdMat->SetSubTexmap(ID_AM, cpTex); - - } - - outMats.push_back(stdMat); - } +void XenoImp::LoadMaterials(MXMD *model) { + MXMDMaterials::Ptr mats = model->GetMaterials(); + + if (!mats) + return; + + const int numMats = mats->GetNumMaterials(); + + for (int m = 0; m < numMats; m++) { + MXMDMaterial::Ptr cMat = mats->GetMaterial(m); + const char *matName = cMat->GetName(); + StdMat *stdMat = NewDefaultStdMat(); + + stdMat->SetName(esStringConvert(matName).c_str()); + + const int numTextures = cMat->GetNumTextures(); + CompositeTex cpTex; + + for (int t = 0; t < numTextures; t++) { + const int texID = cMat->GetTextureIndex(t); + + if (texID >= texmaps.size()) + continue; + + BitmapTex *maxBitmap = texmaps[texID]; + TSTRING texName = maxBitmap->GetName(); + + if (texName.find(_T("_SPM")) != texName.npos) { + if (stdMat->GetSubTexmap(ID_SP)) { + cpTex.AddLayer(); + CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); + clay.Map(maxBitmap); + } else + stdMat->SetSubTexmap(ID_SP, maxBitmap); + } else if (texName.find(_T("_GLO")) != texName.npos) { + if (stdMat->GetSubTexmap(ID_SI)) { + cpTex.AddLayer(); + CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); + clay.Map(maxBitmap); + } else + stdMat->SetSubTexmap(ID_SI, maxBitmap); + } else if (texName.find(_T("_RFM")) != texName.npos) { + if (stdMat->GetSubTexmap(ID_SS)) { + cpTex.AddLayer(); + CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); + clay.Map(maxBitmap); + } else + stdMat->SetSubTexmap(ID_SS, maxBitmap); + } else if (texName.find(_T("_NRM")) != texName.npos) { + if (stdMat->GetSubTexmap(ID_SS)) { + cpTex.AddLayer(); + CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); + clay.Map(maxBitmap); + } else + stdMat->SetSubTexmap(ID_SS, NormalBump(maxBitmap)); + } else if (texName.find(_T("_COL")) != texName.npos) { + if (stdMat->GetSubTexmap(ID_DI)) { + cpTex.AddLayer(); + CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); + clay.Map(maxBitmap); + } else + stdMat->SetSubTexmap(ID_DI, maxBitmap); + } else { + cpTex.AddLayer(); + CompositeTex::Layer clay = cpTex.GetLayer(cpTex.NumLayers() - 1); + clay.Map(maxBitmap); + } + + if (cpTex.NumLayers() > 1) + stdMat->SetSubTexmap(ID_AM, cpTex); + } + + outMats.push_back(stdMat); + } } -INodeTab XenoImp::LoadMeshes(MXMD *model, MXMDModel::Ptr &mdl, int curGroup) -{ - ILayerManager *manager = GetCOREInterface13()->GetLayerManager(); - TSTRING assName(_T("Group")); - INodeTab outNodes; - MXMDGeomBuffers::Ptr geom = model->GetGeometry(curGroup); - - if (!geom) - return {}; - - MXMDMeshGroup::Ptr group = mdl->GetMeshGroup(curGroup); - - MSTR curAssName = assName.c_str(); - curAssName.append(ToTSTRING(curGroup).c_str()); - - ILayer *currLayer = manager->GetLayer(curAssName); - - if (!currLayer) - currLayer = manager->CreateLayer(curAssName); - - int currentMesh = 0; - const int numMeshes = group->GetNumMeshObjects(); - outNodes.Resize(numMeshes); - - for (int m = 0; m < numMeshes; m++) - { - MXMDMeshObject::Ptr mObj = group->GetMeshObject(m); - - const int meshFacesID = mObj->GetUVFacesID(); - MXMDFaceBuffer::Ptr fBuffer = geom->GetFaceBuffer(meshFacesID); - MXMDVertexBuffer::Ptr vBuffer = geom->GetVertexBuffer(mObj->GetBufferID()); - const int numVerts = vBuffer->NumVertices(); - const int numFaces = fBuffer->GetNumIndices() / 3; - TriObject *obj = CreateNewTriObject(); - Mesh *msh = &obj->GetMesh(); - msh->setNumVerts(numVerts); - msh->setNumFaces(numFaces); - - const USVector *fBuff = fBuffer->GetBuffer(); - MXMDVertexBuffer::DescriptorCollection descs = vBuffer->GetDescriptors(); - INodeSuffixer suff; - int currentMap = 1; - MXMDVertexDescriptor *skinDesc = nullptr; - - for (auto &d : descs) - switch (d->Type()) - { - case MXMD_POSITION: - { - for (int v = 0; v < numVerts; v++) - { - Point3 temp; - d->Evaluate(v, &temp); - temp *= IDC_EDIT_SCALE_value; - msh->setVert(v, corMat.VectorTransform(temp)); - } - break; - } - case MXMD_UV1: - case MXMD_UV2: - case MXMD_UV3: - { - msh->setMapSupport(currentMap, 1); - msh->setNumMapVerts(currentMap, numVerts); - msh->setNumMapFaces(currentMap, numFaces); - suff.AddChannel(currentMap); - - for (int v = 0; v < numVerts; v++) - { - Vector2 temp; - d->Evaluate(v, &temp); - msh->Map(currentMap).tv[v] = { temp.X, 1.f - temp.Y, 0.f }; - } - - currentMap++; - break; - } - case MXMD_NORMAL: - case MXMD_NORMAL2: - case MXMD_NORMAL32: - { - suff.UseNormals(); - MeshNormalSpec *normalSpec; - msh->SpecifyNormals(); - normalSpec = msh->GetSpecifiedNormals(); - normalSpec->ClearNormals(); - normalSpec->SetNumNormals(numVerts); - normalSpec->SetNumFaces(numFaces); - - for (int v = 0; v < numVerts; v++) - { - Point3 temp; - d->Evaluate(v, &temp); - normalSpec->Normal(v) = corMat.VectorTransform(temp); - normalSpec->SetNormalExplicit(v, true); - } - - for (int f = 0; f < numFaces; f++) - { - MeshNormalFace &normalFace = normalSpec->Face(f); - const USVector &tmp = fBuff[f]; - normalFace.SpecifyAll(); - normalFace.SetNormalID(0, tmp.X); - normalFace.SetNormalID(1, tmp.Y); - normalFace.SetNormalID(2, tmp.Z); - } - break; - } - case MXMD_VERTEXCOLOR: - { - msh->setMapSupport(-2, 1); - msh->setNumMapVerts(-2, numVerts); - msh->setNumMapFaces(-2, numFaces); - msh->setMapSupport(0, 1); - msh->setNumMapVerts(0, numVerts); - msh->setNumMapFaces(0, numFaces); - suff.AddChannel(0); - suff.AddChannel(-2); - - for (int v = 0; v < numVerts; v++) - { - Vector4 temp; - d->Evaluate(v, &temp); - msh->Map(0).tv[v] = reinterpret_cast(temp); - msh->Map(-2).tv[v] = { temp.W, temp.W, temp.W }; - } - break; - } - case MXMD_WEIGHTID: - skinDesc = d.get(); - break; - default: - break; - } - - MXMDMorphTargets::Ptr morphs = geom->GetVertexBufferMorphTargets(mObj->GetBufferID()); - - if (morphs) - { - suff.UseMorph(); - MXMDVertexBuffer::DescriptorCollection morphDescs = morphs->GetBaseMorph(); - - for (auto &d : morphDescs) - switch (d->Type()) - { - case MXMD_POSITION: - { - for (int v = 0; v < numVerts; v++) - { - Point3 temp; - d->Evaluate(v, &temp); - temp *= IDC_EDIT_SCALE_value; - msh->setVert(v, corMat.VectorTransform(temp)); - } - break; - } - - case MXMD_NORMALMORPH: - { - suff.UseNormals(); - MeshNormalSpec *normalSpec; - msh->SpecifyNormals(); - normalSpec = msh->GetSpecifiedNormals(); - normalSpec->ClearNormals(); - normalSpec->SetNumNormals(numVerts); - normalSpec->SetNumFaces(numFaces); - - for (int v = 0; v < numVerts; v++) - { - Point3 temp; - d->Evaluate(v, &temp); - normalSpec->Normal(v) = corMat.VectorTransform(temp); - normalSpec->SetNormalExplicit(v, true); - } - - for (int f = 0; f < numFaces; f++) - { - MeshNormalFace &normalFace = normalSpec->Face(f); - const USVector &tmp = fBuff[f]; - normalFace.SpecifyAll(); - normalFace.SetNormalID(0, tmp.X); - normalFace.SetNormalID(1, tmp.Y); - normalFace.SetNormalID(2, tmp.Z); - } - break; - } - } - } - - for (int f = 0; f < numFaces; f++) - { - Face &face = msh->faces[f]; - face.setEdgeVisFlags(1, 1, 1); - const USVector &tmp = fBuff[f]; - face.v[0] = tmp.X; - face.v[1] = tmp.Y; - face.v[2] = tmp.Z; - - for (int &i : suff) - msh->Map(i).tf[f].setTVerts(tmp.X, tmp.Y, tmp.Z); - } - - msh->DeleteIsoVerts(); - msh->DeleteIsoMapVerts(); - msh->InvalidateGeomCache(); - msh->InvalidateTopologyCache(); - - INode *nde = GetCOREInterface()->CreateObjectNode(obj); - int gibid = mObj->GetGibID(); - TSTRING nodeName; - - if (gibid) - { - nodeName.append(_T("Part")); - nodeName.append(ToTSTRING(gibid)); - } - else - { - nodeName.append(_T("Object")); - nodeName.append(ToTSTRING(currentMesh)); - currentMesh++; - } - - int LOD = mObj->GetLODID(); - - if (LOD > 0) - { - MSTR curAssName = assName.c_str(); - curAssName.append(ToTSTRING(curGroup).c_str()); - curAssName.append(_T("_LOD")).append(ToTSTRING(LOD).c_str()); - - ILayer *currLODLayer = manager->GetLayer(curAssName); - - if (!currLODLayer) - currLODLayer = manager->CreateLayer(curAssName); - - currLODLayer->AddToLayer(nde); - } - else - currLayer->AddToLayer(nde); - - suff.node = nde; - - if (morphs) - ApplyMorph(morphs, nde, msh, mObj, mdl, geom); - - if (skinDesc) - ApplySkin(geom, mObj, suff, msh->faces, skinDesc); - - if (flags[IDC_CH_DEBUGNAME_checked]) - nodeName.append(suff.Generate()); - - nde->SetName(ToBoneName(nodeName)); - - const int matID = mObj->GetMaterialID(); - - if (matID < outMats.size()) - nde->SetMtl(outMats[matID]); - - outNodes.AppendNode(nde); - } - - return outNodes; +INodeTab XenoImp::LoadMeshes(MXMD *model, MXMDModel::Ptr &mdl, int curGroup) { + ILayerManager *manager = GetCOREInterface13()->GetLayerManager(); + TSTRING assName(_T("Group")); + INodeTab outNodes; + MXMDGeomBuffers::Ptr geom = model->GetGeometry(curGroup); + + if (!geom) + return {}; + + MXMDMeshGroup::Ptr group = mdl->GetMeshGroup(curGroup); + + MSTR curAssName = assName.c_str(); + curAssName.append(ToTSTRING(curGroup).c_str()); + + ILayer *currLayer = manager->GetLayer(curAssName); + + if (!currLayer) + currLayer = manager->CreateLayer(curAssName); + + int currentMesh = 0; + const int numMeshes = group->GetNumMeshObjects(); + outNodes.Resize(numMeshes); + + for (int m = 0; m < numMeshes; m++) { + MXMDMeshObject::Ptr mObj = group->GetMeshObject(m); + + const int meshFacesID = mObj->GetUVFacesID(); + MXMDFaceBuffer::Ptr fBuffer = geom->GetFaceBuffer(meshFacesID); + MXMDVertexBuffer::Ptr vBuffer = geom->GetVertexBuffer(mObj->GetBufferID()); + const int numVerts = vBuffer->NumVertices(); + const int numFaces = fBuffer->GetNumIndices() / 3; + TriObject *obj = CreateNewTriObject(); + Mesh *msh = &obj->GetMesh(); + msh->setNumVerts(numVerts); + msh->setNumFaces(numFaces); + + const USVector *fBuff = fBuffer->GetBuffer(); + MXMDVertexBuffer::DescriptorCollection descs = vBuffer->GetDescriptors(); + INodeSuffixer suff; + int currentMap = 1; + MXMDVertexDescriptor *skinDesc = nullptr; + + for (auto &d : descs) + switch (d->Type()) { + case MXMD_POSITION: { + for (int v = 0; v < numVerts; v++) { + Point3 temp; + d->Evaluate(v, &temp); + temp *= IDC_EDIT_SCALE_value; + msh->setVert(v, corMat.VectorTransform(temp)); + } + break; + } + case MXMD_UV1: + case MXMD_UV2: + case MXMD_UV3: { + msh->setMapSupport(currentMap, 1); + msh->setNumMapVerts(currentMap, numVerts); + msh->setNumMapFaces(currentMap, numFaces); + suff.AddChannel(currentMap); + + for (int v = 0; v < numVerts; v++) { + Vector2 temp; + d->Evaluate(v, &temp); + msh->Map(currentMap).tv[v] = {temp.X, 1.f - temp.Y, 0.f}; + } + + currentMap++; + break; + } + case MXMD_NORMAL: + case MXMD_NORMAL2: + case MXMD_NORMAL32: { + suff.UseNormals(); + MeshNormalSpec *normalSpec; + msh->SpecifyNormals(); + normalSpec = msh->GetSpecifiedNormals(); + normalSpec->ClearNormals(); + normalSpec->SetNumNormals(numVerts); + normalSpec->SetNumFaces(numFaces); + + for (int v = 0; v < numVerts; v++) { + Point3 temp; + d->Evaluate(v, &temp); + normalSpec->Normal(v) = corMat.VectorTransform(temp); + normalSpec->SetNormalExplicit(v, true); + } + + for (int f = 0; f < numFaces; f++) { + MeshNormalFace &normalFace = normalSpec->Face(f); + const USVector &tmp = fBuff[f]; + normalFace.SpecifyAll(); + normalFace.SetNormalID(0, tmp.X); + normalFace.SetNormalID(1, tmp.Y); + normalFace.SetNormalID(2, tmp.Z); + } + break; + } + case MXMD_VERTEXCOLOR: { + msh->setMapSupport(-2, 1); + msh->setNumMapVerts(-2, numVerts); + msh->setNumMapFaces(-2, numFaces); + msh->setMapSupport(0, 1); + msh->setNumMapVerts(0, numVerts); + msh->setNumMapFaces(0, numFaces); + suff.AddChannel(0); + suff.AddChannel(-2); + + for (int v = 0; v < numVerts; v++) { + Vector4 temp; + d->Evaluate(v, &temp); + msh->Map(0).tv[v] = reinterpret_cast(temp); + msh->Map(-2).tv[v] = {temp.W, temp.W, temp.W}; + } + break; + } + case MXMD_WEIGHTID: + skinDesc = d.get(); + break; + default: + break; + } + + MXMDMorphTargets::Ptr morphs = + geom->GetVertexBufferMorphTargets(mObj->GetBufferID()); + + if (morphs) { + suff.UseMorph(); + MXMDVertexBuffer::DescriptorCollection morphDescs = + morphs->GetBaseMorph(); + + for (auto &d : morphDescs) + switch (d->Type()) { + case MXMD_POSITION: { + for (int v = 0; v < numVerts; v++) { + Point3 temp; + d->Evaluate(v, &temp); + temp *= IDC_EDIT_SCALE_value; + msh->setVert(v, corMat.VectorTransform(temp)); + } + break; + } + + case MXMD_NORMALMORPH: { + suff.UseNormals(); + MeshNormalSpec *normalSpec; + msh->SpecifyNormals(); + normalSpec = msh->GetSpecifiedNormals(); + normalSpec->ClearNormals(); + normalSpec->SetNumNormals(numVerts); + normalSpec->SetNumFaces(numFaces); + + for (int v = 0; v < numVerts; v++) { + Vector4 temp; + d->Evaluate(v, &temp); + normalSpec->Normal(v) = + corMat.VectorTransform(reinterpret_cast(temp)); + normalSpec->SetNormalExplicit(v, true); + } + + for (int f = 0; f < numFaces; f++) { + MeshNormalFace &normalFace = normalSpec->Face(f); + const USVector &tmp = fBuff[f]; + normalFace.SpecifyAll(); + normalFace.SetNormalID(0, tmp.X); + normalFace.SetNormalID(1, tmp.Y); + normalFace.SetNormalID(2, tmp.Z); + } + break; + } + } + } + + for (int f = 0; f < numFaces; f++) { + Face &face = msh->faces[f]; + face.setEdgeVisFlags(1, 1, 1); + const USVector &tmp = fBuff[f]; + face.v[0] = tmp.X; + face.v[1] = tmp.Y; + face.v[2] = tmp.Z; + + for (int &i : suff) + msh->Map(i).tf[f].setTVerts(tmp.X, tmp.Y, tmp.Z); + } + + msh->DeleteIsoVerts(); + msh->DeleteIsoMapVerts(); + msh->InvalidateGeomCache(); + msh->InvalidateTopologyCache(); + + INode *nde = GetCOREInterface()->CreateObjectNode(obj); + int gibid = mObj->GetGibID(); + TSTRING nodeName; + + if (gibid) { + nodeName.append(_T("Part")); + nodeName.append(ToTSTRING(gibid)); + } else { + nodeName.append(_T("Object")); + nodeName.append(ToTSTRING(currentMesh)); + currentMesh++; + } + + int LOD = mObj->GetLODID(); + + if (LOD > 0) { + MSTR curAssName = assName.c_str(); + curAssName.append(ToTSTRING(curGroup).c_str()); + curAssName.append(_T("_LOD")).append(ToTSTRING(LOD).c_str()); + + ILayer *currLODLayer = manager->GetLayer(curAssName); + + if (!currLODLayer) + currLODLayer = manager->CreateLayer(curAssName); + + currLODLayer->AddToLayer(nde); + } else + currLayer->AddToLayer(nde); + + suff.node = nde; + + if (morphs) + ApplyMorph(morphs, nde, msh, mObj, mdl, geom); + + if (skinDesc) + ApplySkin(geom, mObj, suff, msh->faces, skinDesc); + + if (flags[IDC_CH_DEBUGNAME_checked]) + nodeName.append(suff.Generate()); + + nde->SetName(ToBoneName(nodeName)); + + const int matID = mObj->GetMaterialID(); + + if (matID < outMats.size()) + nde->SetMtl(outMats[matID]); + + outNodes.AppendNode(nde); + } + + return outNodes; } -void XenoImp::LoadModels(MXMD *model) -{ - MXMDModel::Ptr mdl = model->GetModel(); +void XenoImp::LoadModels(MXMD *model) { + MXMDModel::Ptr mdl = model->GetModel(); - if (!mdl) - return; + if (!mdl) + return; - LoadModelPose(mdl); + LoadModelPose(mdl); - const int numMeshGroups = mdl->GetNumMeshGroups(); + const int numMeshGroups = mdl->GetNumMeshGroups(); - for (int g = 0; g < numMeshGroups; g++) - LoadMeshes(model, mdl, g); + for (int g = 0; g < numMeshGroups; g++) + LoadMeshes(model, mdl, g); } -void XenoImp::LoadModelPose(MXMDModel::Ptr &model) -{ - const int numBones = model->GetNumSkinBones(); - - for (int b = 0; b < numBones; b++) - { - MXMDBone::Ptr cBone = model->GetSkinBone(b); - - const char *_boneName = cBone->GetName(); - TSTRING boneName = esString(_boneName); - INode *node = GetCOREInterface()->GetINodeByName(boneName.c_str()); - - if (!node) - { - Object *obj = static_cast(CreateInstance(HELPER_CLASS_ID, Class_ID(DUMMY_CLASS_ID, 0))); - node = GetCOREInterface()->CreateObjectNode(obj); - node->ShowBone(2); - node->SetWireColor(0x80ff); - node->SetName(ToBoneName(boneName)); - - Matrix3 nodeTM = {}; - const MXMDTransformMatrix *bneMat = cBone->GetAbsTransform(); - - nodeTM.SetRow(0, reinterpret_cast(bneMat->m[0])); - nodeTM.SetRow(1, reinterpret_cast(bneMat->m[1])); - nodeTM.SetRow(2, reinterpret_cast(bneMat->m[2])); - nodeTM.SetRow(3, reinterpret_cast(bneMat->m[3]) * IDC_EDIT_SCALE_value); - nodeTM.Invert(); - node->SetNodeTM(0, nodeTM * corMat); - } - - remapNodes.push_back(node); - } - - for (int b = 0; b < numBones; b++) - { - MXMDBone::Ptr cBone = model->GetSkinBone(b); - int parentID = cBone->GetParentID(); - - if (parentID > -1) - { - MXMDBone::Ptr pBone = model->GetBone(parentID); - const char *_pboneName = pBone->GetName(); - TSTRING pBoneName = esString(_pboneName); - INode *pNode = GetCOREInterface()->GetINodeByName(pBoneName.c_str()); - - if (pNode) - pNode->AttachChild(remapNodes[b]); - } - } +void XenoImp::LoadModelPose(MXMDModel::Ptr &model) { + const int numBones = model->GetNumSkinBones(); + + for (int b = 0; b < numBones; b++) { + MXMDBone::Ptr cBone = model->GetSkinBone(b); + + const char *_boneName = cBone->GetName(); + TSTRING boneName = esString(_boneName); + INode *node = GetCOREInterface()->GetINodeByName(boneName.c_str()); + + if (!node) { + Object *obj = static_cast( + CreateInstance(HELPER_CLASS_ID, Class_ID(DUMMY_CLASS_ID, 0))); + node = GetCOREInterface()->CreateObjectNode(obj); + node->ShowBone(2); + node->SetWireColor(0x80ff); + node->SetName(ToBoneName(boneName)); + + Matrix3 nodeTM = {}; + const MXMDTransformMatrix *bneMat = cBone->GetAbsTransform(); + + nodeTM.SetRow(0, reinterpret_cast(bneMat->m[0])); + nodeTM.SetRow(1, reinterpret_cast(bneMat->m[1])); + nodeTM.SetRow(2, reinterpret_cast(bneMat->m[2])); + nodeTM.SetRow(3, reinterpret_cast(bneMat->m[3]) * + IDC_EDIT_SCALE_value); + nodeTM.Invert(); + node->SetNodeTM(0, nodeTM * corMat); + } + + remapNodes.push_back(node); + } + + for (int b = 0; b < numBones; b++) { + MXMDBone::Ptr cBone = model->GetSkinBone(b); + int parentID = cBone->GetParentID(); + + if (parentID > -1) { + MXMDBone::Ptr pBone = model->GetBone(parentID); + const char *_pboneName = pBone->GetName(); + TSTRING pBoneName = esString(_pboneName); + INode *pNode = GetCOREInterface()->GetINodeByName(pBoneName.c_str()); + + if (pNode) + pNode->AttachChild(remapNodes[b]); + } + } } -void XenoImp::ApplySkin(MXMDGeomBuffers::Ptr &buff, MXMDMeshObject::Ptr &mesh, INodeSuffixer &nde, Face *mfac, MXMDVertexDescriptor *skinDesc) -{ - if (!remapNodes.size()) - return; - else if (remapNodes.size() == 1) - { - remapNodes[0]->AttachChild(nde); - return; - } - - const int skindesc = ((mesh->GetLODID() << 8) & 0xff00) | mesh->GetSkinDesc() & 0xff; - - MXMDGeomVertexWeightBuffer::Ptr wtBuff = buff->GetWeightsBuffer(skindesc); - - if (!buff) - return; - - nde.UseSkin(); - - Modifier *cmod = (Modifier *)GetCOREInterface()->CreateInstance(OSM_CLASS_ID, SKIN_CLASSID); - GetCOREInterface7()->AddModifier(*nde, *cmod); - ISkinImportData *cskin = (ISkinImportData *)cmod->GetInterface(I_SKINIMPORTDATA); - - for (auto &r : remapNodes) - cskin->AddBoneEx(r, false); - - static_cast(nde)->EvalWorldState(0); - - const int meshFacesID = mesh->GetUVFacesID(); - MXMDVertexBuffer::Ptr vBuffer = buff->GetVertexBuffer(mesh->GetBufferID()); - MXMDFaceBuffer::Ptr fBuffer = buff->GetFaceBuffer(meshFacesID); - const int numVerts = vBuffer->NumVertices(); - const int numFaces = fBuffer->GetNumIndices() / 3; - const USVector *fBuff = fBuffer->GetBuffer(); - BitArray btarr(numVerts); - - for (int f = 0; f < numFaces; f++) - { - const USVector &cFaceBegin = fBuff[f]; - for (int s = 0; s < 3; s++) - { - const int &cfseg = mfac[f].v[s]; - if (!btarr[cfseg]) - { - ushort vtid = 0; - skinDesc->Evaluate(cFaceBegin[s], &vtid); - - MXMDVertexWeight cWtOut = wtBuff->GetVertexWeight(vtid); - Tab cbn; - Tab cwt; - cbn.SetCount(4); - cwt.SetCount(4); - for (int u = 0; u < 4; u++) - { - cbn[u] = remapNodes[cWtOut.boneids[u]]; - cwt[u] = cWtOut.weights[u]; - } - cskin->AddWeights(nde, cfseg, cbn, cwt); - - btarr.Set(cfseg); - } - } - } - +void XenoImp::ApplySkin(MXMDGeomBuffers::Ptr &buff, MXMDMeshObject::Ptr &mesh, + INodeSuffixer &nde, Face *mfac, + MXMDVertexDescriptor *skinDesc) { + if (!remapNodes.size()) + return; + else if (remapNodes.size() == 1) { + remapNodes[0]->AttachChild(nde); + return; + } + + const int skindesc = + ((mesh->GetLODID() << 8) & 0xff00) | mesh->GetSkinDesc() & 0xff; + + MXMDGeomVertexWeightBuffer::Ptr wtBuff = buff->GetWeightsBuffer(skindesc); + + if (!buff) + return; + + nde.UseSkin(); + + Modifier *cmod = (Modifier *)GetCOREInterface()->CreateInstance(OSM_CLASS_ID, + SKIN_CLASSID); + GetCOREInterface7()->AddModifier(*nde, *cmod); + ISkinImportData *cskin = + (ISkinImportData *)cmod->GetInterface(I_SKINIMPORTDATA); + + for (auto &r : remapNodes) + cskin->AddBoneEx(r, false); + + static_cast(nde)->EvalWorldState(0); + + const int meshFacesID = mesh->GetUVFacesID(); + MXMDVertexBuffer::Ptr vBuffer = buff->GetVertexBuffer(mesh->GetBufferID()); + MXMDFaceBuffer::Ptr fBuffer = buff->GetFaceBuffer(meshFacesID); + const int numVerts = vBuffer->NumVertices(); + const int numFaces = fBuffer->GetNumIndices() / 3; + const USVector *fBuff = fBuffer->GetBuffer(); + BitArray btarr(numVerts); + + for (int f = 0; f < numFaces; f++) { + const USVector &cFaceBegin = fBuff[f]; + for (int s = 0; s < 3; s++) { + const int &cfseg = mfac[f].v[s]; + if (!btarr[cfseg]) { + ushort vtid = 0; + skinDesc->Evaluate(cFaceBegin[s], &vtid); + + MXMDVertexWeight cWtOut = wtBuff->GetVertexWeight(vtid); + Tab cbn; + Tab cwt; + cbn.SetCount(4); + cwt.SetCount(4); + for (int u = 0; u < 4; u++) { + cbn[u] = remapNodes[cWtOut.boneids[u]]; + cwt[u] = cWtOut.weights[u]; + } + cskin->AddWeights(nde, cfseg, cbn, cwt); + + btarr.Set(cfseg); + } + } + } } -void XenoImp::ApplyMorph(MXMDMorphTargets::Ptr &morphs, INode *node, Mesh *mesh, MXMDMeshObject::Ptr &msh, MXMDModel::Ptr &mdl, MXMDGeomBuffers::Ptr &buff) -{ - Modifier *cmod = (Modifier *)GetCOREInterface()->CreateInstance(OSM_CLASS_ID, MR3_CLASS_ID); - GetCOREInterface7()->AddModifier(*node, *cmod); - - MaxMorphModifier morpher = {}; - morpher.Init(cmod); - - const int targetcount = morphs->GetNumMorphs(); - const int meshFacesID = msh->GetUVFacesID(); - MXMDVertexBuffer::Ptr vBuffer = buff->GetVertexBuffer(msh->GetBufferID()); - MXMDFaceBuffer::Ptr fBuffer = buff->GetFaceBuffer(meshFacesID); - const int numVerts = vBuffer->NumVertices(); - const int numFaces = fBuffer->GetNumIndices() / 3; - const USVector *fBuff = fBuffer->GetBuffer(); - BitArray btarr(numVerts); - int currentChannel = 0; - - for (int m = 0; m < targetcount; m++) - { - MXMDVertexBuffer::DescriptorCollection morph = morphs->GetDeltaMorph(m); - - MaxMorphChannel &chan = morpher.GetMorphChannel(currentChannel); - chan.Reset(true, true, mesh->numVerts); - - TSTRING morphName = esString(mdl->GetMorphName(morphs->GetMorphNameID(m))); - - if (!morphName.size()) - morphName = _T("Morph ") + ToTSTRING(currentChannel); - - chan.SetName(morphName.c_str()); - - for (int v = 0; v < mesh->numVerts; v++) - chan.SetMorphPointDelta(v, Point3{ 0,0,0 }); - - btarr.ClearAll(); - - std::vector IDS; - - for (auto &m : morph) - switch (m->Type()) - { - case MXMD_MORPHVERTEXID: - { - const int numItems = m->Size(); - IDS.resize(numItems); - - for (int i = 0; i < numItems; i++) - m->Evaluate(i, &IDS[i]); - - break; - } - case MXMD_POSITION: - { - int currentNumberOfChannelVertices = 0; - - for (int f = 0; f < numFaces; f++) - { - const USVector &cFaceBegin = fBuff[f]; - - for (int s = 0; s < 3; s++) - { - const int &cfseg = mesh->faces[f].v[s]; - - if (!btarr[cfseg]) - { - int currentMorphVertID = 0; - - for (auto &cid : IDS) - { - if (cFaceBegin[s] == cid) - { - Point3 pos; - m->Evaluate(currentMorphVertID, &pos); - chan.SetMorphPointDelta(cfseg, corMat.VectorTransform(pos)); - currentNumberOfChannelVertices++; - } - currentMorphVertID++; - } - btarr.Set(cfseg); - } - } - } - - if (currentNumberOfChannelVertices) - currentChannel++; - - break; - } - } - } +void XenoImp::ApplyMorph(MXMDMorphTargets::Ptr &morphs, INode *node, Mesh *mesh, + MXMDMeshObject::Ptr &msh, MXMDModel::Ptr &mdl, + MXMDGeomBuffers::Ptr &buff) { + Modifier *cmod = (Modifier *)GetCOREInterface()->CreateInstance(OSM_CLASS_ID, + MR3_CLASS_ID); + GetCOREInterface7()->AddModifier(*node, *cmod); + + MaxMorphModifier morpher = {}; + morpher.Init(cmod); + + const int targetcount = morphs->GetNumMorphs(); + const int meshFacesID = msh->GetUVFacesID(); + MXMDVertexBuffer::Ptr vBuffer = buff->GetVertexBuffer(msh->GetBufferID()); + MXMDFaceBuffer::Ptr fBuffer = buff->GetFaceBuffer(meshFacesID); + const int numVerts = vBuffer->NumVertices(); + const int numFaces = fBuffer->GetNumIndices() / 3; + const USVector *fBuff = fBuffer->GetBuffer(); + BitArray btarr(numVerts); + int currentChannel = 0; + + for (int m = 0; m < targetcount; m++) { + MXMDVertexBuffer::DescriptorCollection morph = morphs->GetDeltaMorph(m); + + MaxMorphChannel &chan = morpher.GetMorphChannel(currentChannel); + chan.Reset(true, true, mesh->numVerts); + + TSTRING morphName = esString(mdl->GetMorphName(morphs->GetMorphNameID(m))); + + if (!morphName.size()) + morphName = _T("Morph ") + ToTSTRING(currentChannel); + + chan.SetName(morphName.c_str()); + + for (int v = 0; v < mesh->numVerts; v++) + chan.SetMorphPointDelta(v, Point3{0, 0, 0}); + + btarr.ClearAll(); + + std::vector IDS; + + for (auto &m : morph) + switch (m->Type()) { + case MXMD_MORPHVERTEXID: { + const int numItems = m->Size(); + IDS.resize(numItems); + + for (int i = 0; i < numItems; i++) + m->Evaluate(i, &IDS[i]); + + break; + } + case MXMD_POSITION: { + int currentNumberOfChannelVertices = 0; + + for (int f = 0; f < numFaces; f++) { + const USVector &cFaceBegin = fBuff[f]; + + for (int s = 0; s < 3; s++) { + const int &cfseg = mesh->faces[f].v[s]; + + if (!btarr[cfseg]) { + int currentMorphVertID = 0; + + for (auto &cid : IDS) { + if (cFaceBegin[s] == cid) { + Point3 pos; + m->Evaluate(currentMorphVertID, &pos); + chan.SetMorphPointDelta(cfseg, corMat.VectorTransform(pos)); + currentNumberOfChannelVertices++; + } + currentMorphVertID++; + } + btarr.Set(cfseg); + } + } + } + + if (currentNumberOfChannelVertices) + currentChannel++; + + break; + } + } + } } -int XenoImp::LoadInstances(MXMD *model) -{ - MXMDModel::Ptr mdl = model->GetModel(); - MXMDInstances::Ptr insts = model->GetInstances(); - - if (!mdl || !insts) - return 1; - - const int numInstances = insts->GetNumInstances(); - const int numGroups = mdl->GetNumMeshGroups(); - std::vector instances(numGroups); - - for (int i = 0; i < numInstances; i++) - { - const MXMDTransformMatrix *mtx = insts->GetTransform(i); - - int groupBegin = insts->GetStartingGroup(i); - const int groupEnd = groupBegin + insts->GetNumGroups(i); - - for (groupBegin; groupBegin < groupEnd; groupBegin++) - { - int meshGroupID = insts->GetMeshGroup(groupBegin); - - if (meshGroupID > numGroups || meshGroupID < 0) - continue; - - INodeTab meshes; - - if (!instances[meshGroupID].Count()) - { - meshes = LoadMeshes(model, mdl, meshGroupID); - instances[meshGroupID] = meshes; - } - else - GetCOREInterface()->CloneNodes(instances[meshGroupID], Point3(), false, NODE_INSTANCE, nullptr, &meshes); - - for (int m = 0; m < meshes.Count(); m++) - { - INode *node = meshes[m]; - Matrix3 nodeTM = {}; - nodeTM.SetRow(0, reinterpret_cast(mtx->m[0])); - nodeTM.SetRow(1, reinterpret_cast(mtx->m[1])); - nodeTM.SetRow(2, reinterpret_cast(mtx->m[2])); - nodeTM.SetRow(3, reinterpret_cast(mtx->m[3]) * IDC_EDIT_SCALE_value); - Matrix3 nodeTM2 = corMat; - nodeTM2.Invert(); - nodeTM2 *= nodeTM; - node->SetNodeTM(0, nodeTM2 * corMat); - } - } - } - - return 0; +int XenoImp::LoadInstances(MXMD *model) { + MXMDModel::Ptr mdl = model->GetModel(); + MXMDInstances::Ptr insts = model->GetInstances(); + + if (!mdl || !insts) + return 1; + + const int numInstances = insts->GetNumInstances(); + const int numGroups = mdl->GetNumMeshGroups(); + std::vector instances(numGroups); + + for (int i = 0; i < numInstances; i++) { + const MXMDTransformMatrix *mtx = insts->GetTransform(i); + + int groupBegin = insts->GetStartingGroup(i); + const int groupEnd = groupBegin + insts->GetNumGroups(i); + + for (groupBegin; groupBegin < groupEnd; groupBegin++) { + int meshGroupID = insts->GetMeshGroup(groupBegin); + + if (meshGroupID > numGroups || meshGroupID < 0) + continue; + + INodeTab meshes; + + if (!instances[meshGroupID].Count()) { + meshes = LoadMeshes(model, mdl, meshGroupID); + instances[meshGroupID] = meshes; + } else + GetCOREInterface()->CloneNodes(instances[meshGroupID], Point3(), false, + NODE_INSTANCE, nullptr, &meshes); + + for (int m = 0; m < meshes.Count(); m++) { + INode *node = meshes[m]; + Matrix3 nodeTM = {}; + nodeTM.SetRow(0, reinterpret_cast(mtx->m[0])); + nodeTM.SetRow(1, reinterpret_cast(mtx->m[1])); + nodeTM.SetRow(2, reinterpret_cast(mtx->m[2])); + nodeTM.SetRow(3, reinterpret_cast(mtx->m[3]) * + IDC_EDIT_SCALE_value); + Matrix3 nodeTM2 = corMat; + nodeTM2.Invert(); + nodeTM2 *= nodeTM; + node->SetNodeTM(0, nodeTM2 * corMat); + } + } + } + + return 0; } -int XenoImp::LoadSKL(const TCHAR *filename, BOOL suppressPrompts, bool subLoad) -{ - BC sklFile; - int loadResult = sklFile.Load(filename, !subLoad); +int XenoImp::LoadSKL(const TCHAR *filename, BOOL suppressPrompts, + bool subLoad) { + BC sklFile; + int loadResult = sklFile.Load(filename, !subLoad); - if (loadResult) - return loadResult; + if (loadResult) + return loadResult; - BCSKEL *skl = sklFile.GetClass(); + BCSKEL *skl = sklFile.GetClass(); - if (!skl) - return -1; + if (!skl) + return -1; - if (!suppressPrompts) - if (!SpawnANIDialog()) - return 0; + if (!suppressPrompts) + if (!SpawnANIDialog()) + return 0; - LoadSkeleton(skl); + LoadSkeleton(skl); - return 0; + return 0; } -int XenoImp::LoadARC(const TCHAR *filename, BOOL suppressPrompts, bool subLoad) -{ - SAR arcFile; - int loadResult = arcFile.Load(filename, !subLoad); +int XenoImp::LoadARC(const TCHAR *filename, BOOL suppressPrompts, + bool subLoad) { + SAR arcFile; + int loadResult = arcFile.Load(filename, !subLoad); - if (loadResult) - return loadResult; + if (loadResult) + return loadResult; - int ext = arcFile.FileIndexFromExtension(".skl"); + int ext = arcFile.FileIndexFromExtension(".skl"); - if (ext < 0) - return ext; + if (ext < 0) + return ext; - BC sklFile; - loadResult = sklFile.Link(arcFile.GetFile(ext)); + BC sklFile; + loadResult = sklFile.Link(arcFile.GetFile(ext)); - if (loadResult) - return loadResult; + if (loadResult) + return loadResult; - BCSKEL *skl = sklFile.GetClass(); + BCSKEL *skl = sklFile.GetClass(); - if (!skl) - return -1; - - if (!suppressPrompts) - if (!SpawnANIDialog()) - return 0; + if (!skl) + return -1; - LoadSkeleton(skl); + if (!suppressPrompts) + if (!SpawnANIDialog()) + return 0; - return 0; + LoadSkeleton(skl); + + return 0; } -int XenoImp::LoadANM(const TCHAR *filename, BOOL suppressPrompts, bool subLoad) -{ - BC anmFile; - int loadResult = anmFile.Load(filename, !subLoad); +int XenoImp::LoadANM(const TCHAR *filename, BOOL suppressPrompts, + bool subLoad) { + BC anmFile; + int loadResult = anmFile.Load(filename, !subLoad); - if (loadResult) - return loadResult; + if (loadResult) + return loadResult; - BCANIM *anm = anmFile.GetClass(); + BCANIM *anm = anmFile.GetClass(); - if (!anm) - return -1; + if (!anm) + return -1; - if (!suppressPrompts) - if (!SpawnANIDialog()) - return 0; + if (!suppressPrompts) + if (!SpawnANIDialog()) + return 0; - LoadAnimation(anm); + LoadAnimation(anm); - return 0; + return 0; } -int XenoImp::LoadMOT(const TCHAR *filename, BOOL suppressPrompts, bool subLoad) -{ - SAR arcFile; - int loadResult = arcFile.Load(filename, !subLoad); +int XenoImp::LoadMOT(const TCHAR *filename, BOOL suppressPrompts, + bool subLoad) { + SAR arcFile; + int loadResult = arcFile.Load(filename, !subLoad); - if (loadResult) - return loadResult; + if (loadResult) + return loadResult; - for (int f = 0; f < arcFile.NumFiles(); f++) - { - AFileInfo fleInfo(arcFile.GetFileName(f)); + for (int f = 0; f < arcFile.NumFiles(); f++) { + AFileInfo fleInfo(arcFile.GetFileName(f)); - if (fleInfo.GetExtension().compare(".anm")) - continue; + if (fleInfo.GetExtension().compare(".anm")) + continue; - BC anmFile; + BC anmFile; - if (anmFile.Link(arcFile.GetFile(f))) - continue; + if (anmFile.Link(arcFile.GetFile(f))) + continue; - BCANIM *anm = anmFile.GetClass(); + BCANIM *anm = anmFile.GetClass(); - if (!anm) - continue; + if (!anm) + continue; - XenoImp::MotionPair mtPair; - mtPair.name = fleInfo.GetFileName().c_str(); - mtPair.ID = f; + XenoImp::MotionPair mtPair; + mtPair.name = fleInfo.GetFileName().c_str(); + mtPair.ID = f; - motions.push_back(mtPair); - } + motions.push_back(mtPair); + } - if (!suppressPrompts) - if (!SpawnANIDialog()) - return 0; + if (!suppressPrompts) + if (!SpawnANIDialog()) + return 0; - BC anmFile; - anmFile.Link(arcFile.GetFile(motions[IDC_CB_MOTIONINDEX_index].ID)); + BC anmFile; + anmFile.Link(arcFile.GetFile(motions[IDC_CB_MOTIONINDEX_index].ID)); - BCANIM *anm = anmFile.GetClass(); + BCANIM *anm = anmFile.GetClass(); - LoadAnimation(anm); + LoadAnimation(anm); - return 0; + return 0; } -int XenoImp::LoadMXMD(const TCHAR *filename, ImpInterface *importerInt, Interface *ip, BOOL suppressPrompts) -{ - - TFileInfo fleInfo(filename); - TSTRING baseFilePath = fleInfo.GetPath() + fleInfo.GetFileName(); - TSTRING arcFilepath = baseFilePath + _T(".arc"); +int XenoImp::LoadMXMD(const TCHAR *filename, ImpInterface *importerInt, + Interface *ip, BOOL suppressPrompts) { - if (!suppressPrompts) - if (!SpawnMXMDDialog()) - return 0; + TFileInfo fleInfo(filename); + TSTRING baseFilePath = fleInfo.GetPath() + fleInfo.GetFileName(); + TSTRING arcFilepath = baseFilePath + _T(".arc"); - if (DoesFileExist(arcFilepath.c_str(), false)) - { - LoadARC(arcFilepath.c_str(), TRUE, true); - } - else - { - TSTRING hkcfgpath = IPathConfigMgr::GetPathConfigMgr()->GetDir(APP_PLUGCFG_DIR); - hkcfgpath.append(_T("\\HavokImpSettings.ini")); - WriteText(_T("HK_PRESETS_HEADER"), _T("Xenoblade"), hkcfgpath.c_str(), _T("currentPresetName")); + if (!suppressPrompts) + if (!SpawnMXMDDialog()) + return 0; - SceneImport *hkImportInterface = static_cast(CreateInstance(SCENE_IMPORT_CLASS_ID, HavokImport_CLASS_ID)); + if (DoesFileExist(arcFilepath.c_str(), false)) { + LoadARC(arcFilepath.c_str(), TRUE, true); + } else { + TSTRING hkcfgpath = + IPathConfigMgr::GetPathConfigMgr()->GetDir(APP_PLUGCFG_DIR); + hkcfgpath.append(_T("\\HavokImpSettings.ini")); + WriteText(_T("HK_PRESETS_HEADER"), _T("Xenoblade"), hkcfgpath.c_str(), + _T("currentPresetName")); - if (hkImportInterface) - { - TSTRING sklFilePath = baseFilePath + _T("_ev_rig.hkt"); + SceneImport *hkImportInterface = static_cast( + CreateInstance(SCENE_IMPORT_CLASS_ID, HavokImport_CLASS_ID)); - if (!DoesFileExist(sklFilePath.c_str(), false)) - sklFilePath = baseFilePath + _T("_rig.hkt"); + if (hkImportInterface) { + TSTRING sklFilePath = baseFilePath + _T("_ev_rig.hkt"); - if (DoesFileExist(sklFilePath.c_str(), false)) - { - hkImportInterface->DoImport(sklFilePath.c_str(), importerInt, ip, TRUE); - } + if (!DoesFileExist(sklFilePath.c_str(), false)) + sklFilePath = baseFilePath + _T("_rig.hkt"); - } + if (DoesFileExist(sklFilePath.c_str(), false)) { + hkImportInterface->DoImport(sklFilePath.c_str(), importerInt, ip, TRUE); + } + } + } - } + MXMD mainModel; - MXMD mainModel; + if (mainModel.Load(filename)) + return 1; - if (mainModel.Load(filename)) - return 1; + TSTRING folderPath = fleInfo.GetPath() + fleInfo.GetFileName() + _T("/"); - TSTRING folderPath = fleInfo.GetPath() + fleInfo.GetFileName() + _T("/"); + std::thread texThread; - std::thread texThread; + if (flags[IDC_CH_TEXTURES_checked]) + texThread = std::thread([&] { + MXMDTextures::Ptr textures = mainModel.GetTextures(); - if (flags[IDC_CH_TEXTURES_checked]) - texThread = std::thread([&] - { - MXMDTextures::Ptr textures = mainModel.GetTextures(); + if (!textures) + return; - if (!textures) - return; + TextureConversionParams params; + params.allowBC5ZChan = !flags[IDC_CH_BC5BCHAN_checked]; + params.uncompress = flags[IDC_CH_TOPNG_checked]; - TextureConversionParams params; - params.allowBC5ZChan = !flags[IDC_CH_BC5BCHAN_checked]; - params.uncompress = flags[IDC_CH_TOPNG_checked]; + _tmkdir(folderPath.c_str()); - _tmkdir(folderPath.c_str()); + textures->ExtractAllTextures(folderPath.c_str(), params); + }); - textures->ExtractAllTextures(folderPath.c_str(), params); - }); + int textureLocation = LoadTextures(&mainModel); + LoadMaterials(&mainModel); - int textureLocation = LoadTextures(&mainModel); - LoadMaterials(&mainModel); + if (LoadInstances(&mainModel)) + LoadModels(&mainModel); - if (LoadInstances(&mainModel)) - LoadModels(&mainModel); + if (texThread.joinable()) + texThread.join(); - if (texThread.joinable()) - texThread.join(); + for (auto &t : texmaps) { + const TCHAR *texName = t->GetName(); + TSTRING texFullPath; - for (auto &t : texmaps) - { - const TCHAR *texName = t->GetName(); - TSTRING texFullPath; - - if (textureLocation) - { - texFullPath = fleInfo.GetPath(); - texFullPath.pop_back(); + if (textureLocation) { + texFullPath = fleInfo.GetPath(); + texFullPath.pop_back(); - TFileInfo tfle(texFullPath); + TFileInfo tfle(texFullPath); - texFullPath = tfle.GetPath() + _T("textures/") + texName; - } - else - texFullPath = folderPath + texName; + texFullPath = tfle.GetPath() + _T("textures/") + texName; + } else + texFullPath = folderPath + texName; - if (DoesFileExist((texFullPath + _T(".png")).c_str(), false)) - texFullPath.append(_T(".png")); - else - texFullPath.append(_T(".dds")); + if (DoesFileExist((texFullPath + _T(".png")).c_str(), false)) + texFullPath.append(_T(".png")); + else + texFullPath.append(_T(".dds")); - t->SetMapName(texFullPath.c_str()); - } + t->SetMapName(texFullPath.c_str()); + } - return 0; + return 0; } -int XenoImp::DoImport(const TCHAR* filename, ImpInterface* importerInt, Interface* ip, BOOL suppressPrompts) -{ - char *oldLocale = setlocale(LC_NUMERIC, NULL); - setlocale(LC_NUMERIC, "en-US"); - int result = FALSE; - - TFileInfo fleInfo(filename); - TSTRING extension = fleInfo.GetExtension(); - - if (!extension.compare(_T(".arc"))) - result = !LoadARC(filename, suppressPrompts); - else if (!extension.compare(_T(".skl"))) - result = !LoadSKL(filename, suppressPrompts); - else if (!extension.compare(_T(".mot"))) - result = !LoadMOT(filename, suppressPrompts); - else if (!extension.compare(_T(".anm"))) - result = !LoadANM(filename, suppressPrompts); - else - result = !LoadMXMD(filename, importerInt, ip, suppressPrompts); - - setlocale(LC_NUMERIC, oldLocale); - PrintOffThreadMessages(); - return result; +int XenoImp::DoImport(const TCHAR *filename, ImpInterface *importerInt, + Interface *ip, BOOL suppressPrompts) { + char *oldLocale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "en-US"); + int result = FALSE; + + TFileInfo fleInfo(filename); + TSTRING extension = fleInfo.GetExtension(); + + if (!extension.compare(_T(".arc"))) + result = !LoadARC(filename, suppressPrompts); + else if (!extension.compare(_T(".skl"))) + result = !LoadSKL(filename, suppressPrompts); + else if (!extension.compare(_T(".mot"))) + result = !LoadMOT(filename, suppressPrompts); + else if (!extension.compare(_T(".anm"))) + result = !LoadANM(filename, suppressPrompts); + else + result = !LoadMXMD(filename, importerInt, ip, suppressPrompts); + + setlocale(LC_NUMERIC, oldLocale); + PrintOffThreadMessages(); + return result; } diff --git a/src/XenoImp.rc b/src/XenoImp.rc index fcf1c66..abaaec4 100644 --- a/src/XenoImp.rc +++ b/src/XenoImp.rc @@ -39,18 +39,19 @@ END // Dialog // -IDD_ANIMSKEL DIALOGEX 0, 0, 159, 67 +IDD_ANIMSKEL DIALOGEX 0, 0, 159, 71 STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME EXSTYLE WS_EX_TOOLWINDOW FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - CONTROL "",IDC_EDIT_SCALE,"CustEdit",WS_TABSTOP,30,8,35,10 + PUSHBUTTON "&Import",IDOK,63,52,44,14 + PUSHBUTTON "&Cancel",IDCANCEL,111,52,44,14 + PUSHBUTTON "&About",IDC_BT_ABOUT,3,52,36,14 + COMBOBOX IDC_CB_MOTIONINDEX,3,32,147,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + CONTROL "&S",IDC_EDIT_SCALE,"CustEdit",WS_TABSTOP,30,8,35,10 CONTROL "",IDC_SPIN_SCALE,"SpinnerControl",0x0,66,8,7,10 LTEXT "Scale",IDC_STATIC,6,8,19,8 - PUSHBUTTON "Import",IDC_BT_DONE,63,48,44,14 - PUSHBUTTON "Cancel",IDC_BT_CANCEL,111,48,44,14 - PUSHBUTTON "About",IDC_BT_ABOUT,3,48,36,14 - COMBOBOX IDC_CB_MOTIONINDEX,6,24,147,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP + CONTROL "&Global frames",IDC_CH_GLOBAL_FRAMES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,20,59,10 END @@ -67,7 +68,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 152 TOPMARGIN, 7 - BOTTOMMARGIN, 60 + BOTTOMMARGIN, 64 END END #endif // APSTUDIO_INVOKED @@ -124,16 +125,16 @@ STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSME EXSTYLE WS_EX_TOOLWINDOW | WS_EX_CONTEXTHELP FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - CONTROL "",IDC_EDIT_SCALE,"CustEdit",WS_TABSTOP,33,60,35,10 + PUSHBUTTON "&Import",IDOK,6,80,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,81,80,50,14 + PUSHBUTTON "?",IDC_BT_ABOUT,60,80,18,14 + CONTROL "&s",IDC_EDIT_SCALE,"CustEdit",WS_TABSTOP,33,60,35,10 + CONTROL "Keep &debug info in name",IDC_CH_DEBUGNAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,8,95,10 + CONTROL "Export &textures",IDC_CH_TEXTURES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,20,63,10 + CONTROL "Convert textures to &PNG",IDC_CH_TOPNG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,32,93,10 + CONTROL "2 channel &Normal Maps",IDC_CH_BC5BCHAN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,44,91,10 CONTROL "",IDC_SPIN_SCALE,"SpinnerControl",0x0,69,60,7,10 LTEXT "Scale",IDC_STATIC,9,60,19,8 - CONTROL "Keep debug info in name",IDC_CH_DEBUGNAME,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,8,95,10 - CONTROL "Export textures",IDC_CH_TEXTURES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,20,63,10 - CONTROL "Convert textures to PNG",IDC_CH_TOPNG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,32,93,10 - CONTROL "2 channel Normal Maps",IDC_CH_BC5BCHAN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,44,91,10 - PUSHBUTTON "Import",IDC_BT_DONE,6,80,50,14 - PUSHBUTTON "Cancel",IDC_BT_CANCEL,81,80,50,14 - PUSHBUTTON "?",IDC_BT_ABOUT,60,80,18,14 END diff --git a/src/XenoImport.cpp b/src/XenoImport.cpp index 6fdf651..190da10 100644 --- a/src/XenoImport.cpp +++ b/src/XenoImport.cpp @@ -1,239 +1,238 @@ -/* Xenoblade Tool for 3ds Max - Copyright(C) 2017-2019 Lukas Cone +/* Xenoblade Tool for 3ds Max + Copyright(C) 2017-2019 Lukas Cone - This program is free software : you can redistribute it and / or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software : you can redistribute it and / or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program.If not, see . + You should have received a copy of the GNU General Public License + along with this program.If not, see . */ #include "XenoImport.h" -#include +#include "datas/esstring.h" #include <3dsmaxport.h> +#include #include -#include "datas/esstring.h" - -#define QUOTE(x) #x -#define CATTEDTEXT(...) StaticFor(QUOTE, __VA_ARGS__) extern HINSTANCE hInstance; const TCHAR _name[] = _T("Xenoblade Tool"); -const TCHAR _info[] = _T(CATTEDTEXT(\nCopyright(C) 2017-2019 Lukas Cone\nVersion\x20 , XENOMAX_VERSION)); -const TCHAR _license[] = _T("Xenoblade Tool uses XenoLib, Copyright(C) 2017-2019 Lukas Cone."); -const TCHAR _homePage[] = _T("https://lukascone.wordpress.com/2019/06/04/xenoblade-chronicles-3ds-max-plugin/"); +const TCHAR _info[] = + _T("\n" XenoMax_COPYRIGHT "\nVersion " XenoMax_VERSION); +const TCHAR _license[] = + _T("Xenoblade Tool uses XenoLib, Copyright(C) 2017-2019 Lukas Cone."); +const TCHAR _homePage[] = _T("https://lukascone.wordpress.com/2019/06/04/") + _T("xenoblade-chronicles-3ds-max-plugin/"); #include "MAXex/win/AboutDlg.h" -XenoImport::XenoImport(): CFGFile(nullptr), hWnd(nullptr), -IDConfigValue(IDC_EDIT_SCALE)(145.f), flags(IDC_CH_DEBUGNAME_checked) -{ - LoadCFG(); +XenoImport::XenoImport() + : CFGFile(nullptr), hWnd(nullptr), IDConfigValue(IDC_EDIT_SCALE)(145.f), + flags(IDC_CH_DEBUGNAME_checked) { + LoadCFG(); } -void XenoImport::LoadCFG() -{ - BuildCFG(); - TCHAR buffer[CFGBufferSize]; - - GetCFGValue(IDC_EDIT_SCALE); - GetCFGIndex(IDC_CB_MOTIONINDEX); - GetCFGChecked(IDC_CH_DEBUGNAME); - GetCFGChecked(IDC_CH_BC5BCHAN); - GetCFGChecked(IDC_CH_TEXTURES); - GetCFGChecked(IDC_CH_TOPNG); - GetCFGEnabled(IDC_CH_BC5BCHAN); - GetCFGEnabled(IDC_CH_TOPNG); +void XenoImport::LoadCFG() { + BuildCFG(); + TCHAR buffer[CFGBufferSize]; + + GetCFGValue(IDC_EDIT_SCALE); + GetCFGIndex(IDC_CB_MOTIONINDEX); + GetCFGChecked(IDC_CH_DEBUGNAME); + GetCFGChecked(IDC_CH_BC5BCHAN); + GetCFGChecked(IDC_CH_TEXTURES); + GetCFGChecked(IDC_CH_TOPNG); + GetCFGChecked(IDC_CH_GLOBAL_FRAMES); + GetCFGEnabled(IDC_CH_BC5BCHAN); + GetCFGEnabled(IDC_CH_TOPNG); } -void XenoImport::BuildCFG() -{ - cfgpath = IPathConfigMgr::GetPathConfigMgr()->GetDir(APP_PLUGCFG_DIR); - cfgpath.append(_T("\\XenoImpSettings.ini")); - CFGFile = cfgpath.c_str(); +void XenoImport::BuildCFG() { + cfgpath = IPathConfigMgr::GetPathConfigMgr()->GetDir(APP_PLUGCFG_DIR); + cfgpath.append(_T("\\XenoImpSettings.ini")); + CFGFile = cfgpath.c_str(); } -void XenoImport::SaveCFG() -{ - BuildCFG(); - - TCHAR buffer[CFGBufferSize]; - SetCFGValue(IDC_EDIT_SCALE); - SetCFGIndex(IDC_CB_MOTIONINDEX); - SetCFGChecked(IDC_CH_DEBUGNAME); - SetCFGChecked(IDC_CH_BC5BCHAN); - SetCFGChecked(IDC_CH_TEXTURES); - SetCFGChecked(IDC_CH_TOPNG); - SetCFGEnabled(IDC_CH_BC5BCHAN); - SetCFGEnabled(IDC_CH_TOPNG); - - WriteText(hkpresetgroup, _T("Xenoblade"), CFGFile, _T("Name")); - WriteValue(hkpresetgroup, IDConfigValue(IDC_EDIT_SCALE), CFGFile, buffer, _T("Scale")); - WriteCorrectionMatrix(corMat, CFGFile, buffer); +void XenoImport::SaveCFG() { + BuildCFG(); + + TCHAR buffer[CFGBufferSize]; + SetCFGValue(IDC_EDIT_SCALE); + SetCFGIndex(IDC_CB_MOTIONINDEX); + SetCFGChecked(IDC_CH_DEBUGNAME); + SetCFGChecked(IDC_CH_BC5BCHAN); + SetCFGChecked(IDC_CH_TEXTURES); + SetCFGChecked(IDC_CH_GLOBAL_FRAMES); + SetCFGChecked(IDC_CH_TOPNG); + SetCFGEnabled(IDC_CH_BC5BCHAN); + SetCFGEnabled(IDC_CH_TOPNG); + + WriteText(hkpresetgroup, _T("Xenoblade"), CFGFile, _T("Name")); + WriteValue(hkpresetgroup, IDConfigValue(IDC_EDIT_SCALE), CFGFile, buffer, + _T("Scale")); + WriteCorrectionMatrix(corMat, CFGFile, buffer); } -static INT_PTR CALLBACK DialogCallbacks(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - XenoImport *imp = DLGetWindowLongPtr(hWnd); - - switch (message) { - case WM_INITDIALOG: - { - CenterWindow(hWnd, GetParent(hWnd)); - imp = reinterpret_cast(lParam); - DLSetWindowLongPtr(hWnd, lParam); - imp->hWnd = hWnd; - imp->LoadCFG(); - SetupIntSpinner(hWnd, IDC_SPIN_SCALE, IDC_EDIT_SCALE, 0, 5000, imp->IDC_EDIT_SCALE_value); - SetWindowText(hWnd, _T(CATTEDTEXT(Xenoblade Import v, XENOMAX_VERSION))); - - HWND butt = GetDlgItem(hWnd, IDC_BT_DONE); - RECT buttRect; - RECT rekt; - - GetWindowRect(hWnd, &rekt); - imp->windowSize = rekt.right - rekt.left; - GetClientRect(hWnd, &rekt); - - GetWindowRect(butt, &buttRect); - MapWindowPoints(HWND_DESKTOP, hWnd, (LPPOINT)& buttRect, 2); - - imp->button1Distance = rekt.right - buttRect.left; - - butt = GetDlgItem(hWnd, IDC_BT_CANCEL); - GetWindowRect(butt, &buttRect); - MapWindowPoints(HWND_DESKTOP, hWnd, (LPPOINT)& buttRect, 2); - imp->button2Distance = rekt.right - buttRect.left; - - imp->comboHandle = GetDlgItem(hWnd, IDC_CB_MOTIONINDEX); - - for (auto &p : imp->motions) - SendMessage(imp->comboHandle, CB_ADDSTRING, 0, (LPARAM)esString(p.name).ToTString().c_str()); - - SendMessage(imp->comboHandle, CB_SETCURSEL, imp->IDC_CB_MOTIONINDEX_index >= imp->motions.size() ? 0 : imp->IDC_CB_MOTIONINDEX_index, 0); - - return TRUE; - } - - case WM_SIZE: - { - HWND butt = GetDlgItem(hWnd, IDC_BT_DONE); - RECT buttRect; - RECT rekt; - - GetClientRect(hWnd, &rekt); - GetWindowRect(butt, &buttRect); - MapWindowPoints(HWND_DESKTOP, hWnd, (LPPOINT)& buttRect, 2); - - SetWindowPos(butt, 0, rekt.right - imp->button1Distance, buttRect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOOWNERZORDER); - - butt = GetDlgItem(hWnd, IDC_BT_CANCEL); - SetWindowPos(butt, 0, rekt.right - imp->button2Distance, buttRect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOOWNERZORDER); - - butt = GetDlgItem(hWnd, IDC_CB_MOTIONINDEX); - GetClientRect(butt, &buttRect); - - SetWindowPos(butt, 0, 0, 0, rekt.right - rekt.left - 15, buttRect.bottom, SWP_NOZORDER | SWP_NOMOVE | SWP_NOOWNERZORDER); - - break; - } - - case WM_GETMINMAXINFO: - { - LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; - lpMMI->ptMinTrackSize.x = imp->windowSize; - break; - } - - case WM_NCHITTEST: - { - LRESULT lRes = DefWindowProc(hWnd, message, wParam, lParam); - - if (lRes == HTBOTTOMLEFT || lRes == HTBOTTOMRIGHT - || lRes == HTTOPLEFT || lRes == HTTOPRIGHT || lRes == HTTOP - || lRes == HTBOTTOM || lRes == HTSIZE) - return TRUE; - - return FALSE; - } - - case WM_CLOSE: - EndDialog(hWnd, 0); - imp->SaveCFG(); - return 1; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_BT_DONE: - EndDialog(hWnd, 1); - imp->SaveCFG(); - return 1; - case IDC_BT_ABOUT: - ShowAboutDLG(hWnd); - return 1; - case IDC_BT_CANCEL: - EndDialog(hWnd, 0); - imp->SaveCFG(); - return 1; - - MSGCheckbox(IDC_CH_DEBUGNAME); break; - MSGCheckbox(IDC_CH_TEXTURES); - MSGEnable(IDC_CH_TEXTURES, IDC_CH_TOPNG); - MSGEnableEnabled(IDC_CH_TOPNG, IDC_CH_BC5BCHAN); - break; - - MSGCheckbox(IDC_CH_BC5BCHAN); break; - - MSGCheckbox(IDC_CH_TOPNG); - MSGEnable(IDC_CH_TOPNG, IDC_CH_BC5BCHAN); - break; - - } - - case CC_SPINNER_CHANGE: - switch (LOWORD(wParam)) - { - case IDC_SPIN_SCALE: - imp->IDC_EDIT_SCALE_value = reinterpret_cast(lParam)->GetFVal(); - break; - } - case IDC_CB_MOTIONINDEX: - { - switch (HIWORD(wParam)) - { - case CBN_SELCHANGE: - { - const LRESULT curSel = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); - imp->IDC_CB_MOTIONINDEX_index = curSel; - return TRUE; - } - break; - } - break; - } - } - return 0; +static INT_PTR CALLBACK DialogCallbacks(HWND hWnd, UINT message, WPARAM wParam, + LPARAM lParam) { + XenoImport *imp = DLGetWindowLongPtr(hWnd); + + switch (message) { + case WM_INITDIALOG: { + CenterWindow(hWnd, GetParent(hWnd)); + imp = reinterpret_cast(lParam); + DLSetWindowLongPtr(hWnd, lParam); + imp->hWnd = hWnd; + imp->LoadCFG(); + SetupIntSpinner(hWnd, IDC_SPIN_SCALE, IDC_EDIT_SCALE, 0, 5000, + imp->IDC_EDIT_SCALE_value); + SetWindowText(hWnd, _T("Xenoblade Import v" XenoMax_VERSION)); + + HWND butt = GetDlgItem(hWnd, IDC_BT_DONE); + RECT buttRect; + RECT rekt; + + GetWindowRect(hWnd, &rekt); + imp->windowSize = rekt.right - rekt.left; + GetClientRect(hWnd, &rekt); + + GetWindowRect(butt, &buttRect); + MapWindowPoints(HWND_DESKTOP, hWnd, (LPPOINT)&buttRect, 2); + + imp->button1Distance = rekt.right - buttRect.left; + + butt = GetDlgItem(hWnd, IDC_BT_CANCEL); + GetWindowRect(butt, &buttRect); + MapWindowPoints(HWND_DESKTOP, hWnd, (LPPOINT)&buttRect, 2); + imp->button2Distance = rekt.right - buttRect.left; + + imp->comboHandle = GetDlgItem(hWnd, IDC_CB_MOTIONINDEX); + + for (auto &p : imp->motions) + SendMessage(imp->comboHandle, CB_ADDSTRING, 0, + (LPARAM)esString(p.name).ToTString().c_str()); + + SendMessage(imp->comboHandle, CB_SETCURSEL, + imp->IDC_CB_MOTIONINDEX_index >= imp->motions.size() + ? 0 + : imp->IDC_CB_MOTIONINDEX_index, + 0); + + return TRUE; + } + + case WM_SIZE: { + HWND butt = GetDlgItem(hWnd, IDC_BT_DONE); + RECT buttRect; + RECT rekt; + + GetClientRect(hWnd, &rekt); + GetWindowRect(butt, &buttRect); + MapWindowPoints(HWND_DESKTOP, hWnd, (LPPOINT)&buttRect, 2); + + SetWindowPos(butt, 0, rekt.right - imp->button1Distance, buttRect.top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_NOOWNERZORDER); + + butt = GetDlgItem(hWnd, IDC_BT_CANCEL); + SetWindowPos(butt, 0, rekt.right - imp->button2Distance, buttRect.top, 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_NOOWNERZORDER); + + butt = GetDlgItem(hWnd, IDC_CB_MOTIONINDEX); + GetClientRect(butt, &buttRect); + + SetWindowPos(butt, 0, 0, 0, rekt.right - rekt.left - 15, buttRect.bottom, + SWP_NOZORDER | SWP_NOMOVE | SWP_NOOWNERZORDER); + + break; + } + + case WM_GETMINMAXINFO: { + LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; + lpMMI->ptMinTrackSize.x = imp->windowSize; + break; + } + + case WM_NCHITTEST: { + LRESULT lRes = DefWindowProc(hWnd, message, wParam, lParam); + + if (lRes == HTBOTTOMLEFT || lRes == HTBOTTOMRIGHT || lRes == HTTOPLEFT || + lRes == HTTOPRIGHT || lRes == HTTOP || lRes == HTBOTTOM || + lRes == HTSIZE) + return TRUE; + + return FALSE; + } + + case WM_CLOSE: + EndDialog(hWnd, 0); + imp->SaveCFG(); + return 1; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + EndDialog(hWnd, 1); + imp->SaveCFG(); + return 1; + case IDC_BT_ABOUT: + ShowAboutDLG(hWnd); + return 1; + case IDCANCEL: + EndDialog(hWnd, 0); + imp->SaveCFG(); + return 1; + + MSGCheckbox(IDC_CH_DEBUGNAME); + break; + MSGCheckbox(IDC_CH_TEXTURES); + MSGEnable(IDC_CH_TEXTURES, IDC_CH_TOPNG); + MSGEnableEnabled(IDC_CH_TOPNG, IDC_CH_BC5BCHAN); + break; + + MSGCheckbox(IDC_CH_BC5BCHAN); + break; + + MSGCheckbox(IDC_CH_GLOBAL_FRAMES); + break; + + MSGCheckbox(IDC_CH_TOPNG); + MSGEnable(IDC_CH_TOPNG, IDC_CH_BC5BCHAN); + break; + } + + case CC_SPINNER_CHANGE: + switch (LOWORD(wParam)) { + case IDC_SPIN_SCALE: + imp->IDC_EDIT_SCALE_value = + reinterpret_cast(lParam)->GetFVal(); + break; + } + case IDC_CB_MOTIONINDEX: { + switch (HIWORD(wParam)) { + case CBN_SELCHANGE: { + const LRESULT curSel = SendMessage((HWND)lParam, CB_GETCURSEL, 0, 0); + imp->IDC_CB_MOTIONINDEX_index = curSel; + return TRUE; + } break; + } + break; + } + } + return 0; } -int XenoImport::SpawnMXMDDialog() -{ - return DialogBoxParam(hInstance, - MAKEINTRESOURCE(IDD_MXMD), - GetActiveWindow(), - DialogCallbacks, (LPARAM)this); +int XenoImport::SpawnMXMDDialog() { + return DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MXMD), GetActiveWindow(), + DialogCallbacks, (LPARAM)this); } -int XenoImport::SpawnANIDialog() -{ - return DialogBoxParam(hInstance, - MAKEINTRESOURCE(IDD_ANIMSKEL), - GetActiveWindow(), - DialogCallbacks, (LPARAM)this); +int XenoImport::SpawnANIDialog() { + return DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ANIMSKEL), + GetActiveWindow(), DialogCallbacks, (LPARAM)this); } \ No newline at end of file diff --git a/src/XenoImport.h b/src/XenoImport.h index 1e17200..e548f8a 100644 --- a/src/XenoImport.h +++ b/src/XenoImport.h @@ -1,84 +1,76 @@ -/* Xenoblade Tool for 3ds Max - Copyright(C) 2017-2019 Lukas Cone +/* Xenoblade Tool for 3ds Max + Copyright(C) 2017-2019 Lukas Cone - This program is free software : you can redistribute it and / or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software : you can redistribute it and / or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program.If not, see . + You should have received a copy of the GNU General Public License + along with this program.If not, see . */ #pragma once #include "resource.h" -#include +#include #include +#include +#include #include -#include + #include "MAXex/win/CFGMacros.h" -#include +#include "../project.h" -#define XENOMAX_VERSION 1.1 -#define XENOMAX_VERSIONINT 110 +static constexpr int XENOMAX_VERSIONINT = XenoMax_VERSION_MAJOR * 100 + XenoMax_VERSION_MINOR; -class XenoImport -{ +class XenoImport { public: - TSTRING cfgpath; - const TCHAR *CFGFile; - HWND hWnd; - HWND comboHandle; - - NewIDConfigValue(IDC_EDIT_SCALE); - NewIDConfigIndex(IDC_CB_MOTIONINDEX); - - int windowSize, - button1Distance, - button2Distance; - - enum ConfigBoolean - { - IDConfigBool(IDC_CH_DEBUGNAME), - IDConfigBool(IDC_CH_BC5BCHAN), - IDConfigBool(IDC_CH_TEXTURES), - IDConfigBool(IDC_CH_TOPNG), - IDConfigVisible(IDC_CH_BC5BCHAN), - IDConfigVisible(IDC_CH_TOPNG), - }; - - EnumFlags flags; - - struct MotionPair - { - std::string name; - int ID; - }; - - std::vector motions; - - XenoImport(); - ~XenoImport() {} - - void BuildCFG(); - void SaveCFG(); - void LoadCFG(); - - int SpawnMXMDDialog(); - int SpawnANIDialog(); + TSTRING cfgpath; + const TCHAR *CFGFile; + HWND hWnd; + HWND comboHandle; + + NewIDConfigValue(IDC_EDIT_SCALE); + NewIDConfigIndex(IDC_CB_MOTIONINDEX); + + int windowSize, button1Distance, button2Distance; + + enum ConfigBoolean { + IDConfigBool(IDC_CH_DEBUGNAME), + IDConfigBool(IDC_CH_BC5BCHAN), + IDConfigBool(IDC_CH_TEXTURES), + IDConfigBool(IDC_CH_TOPNG), + IDConfigBool(IDC_CH_GLOBAL_FRAMES), + IDConfigVisible(IDC_CH_BC5BCHAN), + IDConfigVisible(IDC_CH_TOPNG), + }; + + EnumFlags flags; + + struct MotionPair { + std::string name; + int ID; + }; + + std::vector motions; + + XenoImport(); + ~XenoImport() {} + + void BuildCFG(); + void SaveCFG(); + void LoadCFG(); + + int SpawnMXMDDialog(); + int SpawnANIDialog(); }; void ShowAboutDLG(HWND hWnd); -static const Matrix3 corMat = -{ - { 1.f,0.f,0.f }, - { 0.f,0.f,1.f }, - { 0.f,-1.f, 0.f }, - { 0.f, 0.f, 0.f } -}; \ No newline at end of file +static const Matrix3 corMat = { + {1.f, 0.f, 0.f}, {0.f, 0.f, 1.f}, {0.f, -1.f, 0.f}, {0.f, 0.f, 0.f}}; \ No newline at end of file diff --git a/src/XenoMax.h b/src/XenoMax.h index ebf6ad9..92b07a9 100644 --- a/src/XenoMax.h +++ b/src/XenoMax.h @@ -1,37 +1,34 @@ -/* Xenoblade Tool for 3ds Max - Copyright(C) 2017-2019 Lukas Cone +/* Xenoblade Tool for 3ds Max + Copyright(C) 2017-2019 Lukas Cone - This program is free software : you can redistribute it and / or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. + This program is free software : you can redistribute it and / or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program.If not, see . + You should have received a copy of the GNU General Public License + along with this program.If not, see . */ #pragma once #include "MAXex/3DSMaxSDKCompat.h" -#include #include #include -#include +#include #include -//SIMPLE TYPE - +#include +// SIMPLE TYPE -#include -#include +#include "../project.h" #include +#include +#include - -TCHAR *GetString(int id); void PrintOffThreadMessages(); extern HINSTANCE hInstance; - diff --git a/src/resource.h b/src/resource.h index b20f5c8..d8ce7e4 100644 --- a/src/resource.h +++ b/src/resource.h @@ -2,7 +2,7 @@ // Microsoft Visual C++ generated include file. // Used by XenoImp.rc // -#define IDD_MXMD 101 +#define IDD_MXMD 101 #define IDD_ANIMSKEL 111 #define IDC_CH_DEBUGNAME 1003 #define IDC_CH_TEXTURES 1004 @@ -12,6 +12,7 @@ #define IDC_BT_CANCEL 1008 #define IDC_BT_ABOUT 1009 #define IDC_CB_MOTIONINDEX 1034 +#define IDC_CH_GLOBAL_FRAMES 1035 #define IDC_EDIT_SCALE 1490 #define IDC_SPIN_SCALE 1496 @@ -21,7 +22,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 113 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1035 +#define _APS_NEXT_CONTROL_VALUE 1036 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif