diff --git a/MaxNifPlugins_Readme.txt b/MaxNifPlugins_Readme.txt index 902dc78cfc998d967e3d5e31b4c4edac2bff90d8..971f29c0f622152c1ea4a7fe240bc2cc9fcfea42 100644 --- a/MaxNifPlugins_Readme.txt +++ b/MaxNifPlugins_Readme.txt @@ -34,11 +34,15 @@ - Added Vertex Color modifier support - Fixed issue with static animation import - Fixed issue with skin vertex weight count import + - Added support for more material/texture properties + - Added support for Civilization IV Shader, if installed + o holds much of the material data in nif compatible form o Exporter - Upgraded to Visual Studio 2005 - Dropped registry support in favor of INI file. - - Dropped Official Max6 support because I do not have SDK to compile it with (try the max 7 files). + - Dropped Official Max6 support because I do not have Max 6 to compile it + o Try editing the MaxNifTools.ini and setting the MaxSDKVersion to 0x17700d00 - Fixed issue with importing glossiness setting on textures. - Fixed issues with export of vertex color. Alpha map is now exported as part of the normal color map. - No longer exports meshes associated with bone or biped nodes. @@ -46,6 +50,10 @@ - Mass, Restitution(Ellasticity), and Friction now share values with Reactor(Havok) - Modified UPB export to actually export the values in the UserPropBuffer not just a fixed list. - Added Skin Modifier export + - Added support for more material/texture properties + - Added support for Civilization IV Shader, if installed + o holds much of the material data in nif compatible form + - Fixed issue with UV map needing to be flipped o NifProps Utility - Mass, Restitution(Ellasticity), and Friction now share values with Reactor(Havok) diff --git a/MaxNifTools.ini b/MaxNifTools.ini index c7b2529df4b160dd7e4ce3bba87ac4db452b4627..74969fd1f1d11fa9352dab75f19d5d87182c6f4a 100644 --- a/MaxNifTools.ini +++ b/MaxNifTools.ini @@ -6,7 +6,7 @@ ShortDescription=Netimmerse/Gamebryo ; KnownApplications - Used to indicate which sections in the ini file point ; to "Applications" which have their own settings in a section below. -KnownApplications=Oblivion;Morrowind;Civ4;DAoC +KnownApplications=Oblivion;Morrowind;Civilization 4;Dark Age of Camelot;User ; Reparse the Applications (and therefore Texture directory cache) on every import/export Reparse=0 @@ -24,14 +24,14 @@ GenerateStrips=1 FurnatureMarkers=1 ; Use Lights if present. Default:0 Lights=0 -; Include Hidden Nodes if present. Default:0 -IncludeHidden=0 +; Include Hidden Nodes if present. Default:1 +IncludeHidden=1 ; Export Collision meshes if present. Default:1 ExportCollision=1 ; Export Vertext Colors. Default:1 VertexColors=1 -; Remap Indices. Default:1 -RemapIndices=1 +; Remap Indices. Default:0 +RemapIndices=0 ; Texture Prefix if texture not found in AppSettings directory. Default:textures TexturePrefix=textures ; Add Export additional NiNodes for Meshes. Default: 0 @@ -40,14 +40,14 @@ ExportExtraNodes=0 ExportSkin=1 ; Export UserPropBuffer. Default: 0 UserPropBuffer=0 -; Flatten Node Hierarchy. Default: 0 -FlattenHierarchy=0 -; Remove Unreferenced Bones. Default: 0 -RemoveUnreferencedBones=0 +; Flatten Node Hierarchy. Default: 1 +FlattenHierarchy=1 +; Remove Unreferenced Bones. Default: 1 +RemoveUnreferencedBones=1 [MaxNifImport] ; Max SDK Plugin Version (0 - AutoSelect; 0x17700d00 - Max6, 0x1f401100 - Max8) Default: 0 -MaxSDKVersion=0x17700d00 +MaxSDKVersion=0 ; Current Application to get setting/directory information from. Should match KnownApps above or Auto. ; Auto will check the import file against the known root paths use that app if a directory match is found. CurrentApp=Auto @@ -64,7 +64,7 @@ EnableAutoSmooth=1 ; AutoSmooth angle. Default: 30 AutoSmoothAngle=30.0 ; Remove Double/Illegal faces on meshes on import. Default:1 -RemoveDoubleFaces=1 +RemoveDegenerateFaces=1 RemoveIllegalFaces=1 ; EnableSkinSupport attempt to skin the mesh if bones are available. Default:1 EnableSkinSupport=1 @@ -92,8 +92,6 @@ MaxBoneWidth=0.1 BoneWidthToLengthRatio=0.01 ; Force nub to point back to parent at expense of loss of rotation data. Default: 1 ForceRotation=0 -; Browse for skeleton on import. Default: 1 -BrowseForSkeleton=1 ; DefaultName for Skeletons (use if in same directory as imported nif) DefaultSkeletonName=skeleton.nif @@ -121,6 +119,8 @@ ApplyOverallTransformToSkinAndBones=1 bhkScaleFactor=7.0 ; [Applications] +; NiVersion - Version of Nif use by game +; NiUserVersion - User Version of Nif used by game ; RootPaths - Semicolon separated list of base directories to use when determining which app the imported file is from ; ; TextureRootPaths - Semicolon separated list of base directories to look for texturefiles @@ -132,6 +132,8 @@ bhkScaleFactor=7.0 ; GoToSkeletonBindPosition - Morrowind trishape data is not in the correct bind position for import. Default: 1 [Oblivion] +NiVersion=20.0.0.5 +NiUserVersion=11 ; Installation Folder InstallPath=[HKLM\SOFTWARE\Bethesda Softworks\Oblivion]=@"Installed Path" ExtractFolder=E:\Nifs\Oblivion @@ -148,6 +150,8 @@ TextureSearchPaths=${RootPath}\Textures;${TextureRootPath}\Textures\Characters;$ GoToSkeletonBindPosition=1 [Morrowind] +NiVersion=4.0.0.2 +NiUserVersion=0 InstallPath=[HKLM\SOFTWARE\Bethesda Softworks\Morrowind]=@"Installed Path" RootPath=${InstallPath}\Data Files ExtractFolder=E:\Nifs\Morrowind\Data Files @@ -157,7 +161,9 @@ TextureExtensions=.tga; TextureSearchPaths=${RootPath}\Textures GoToSkeletonBindPosition=1 -[Civ4] +[Civilization 4] +NiVersion=20.0.0.4 +NiUserVersion=0 InstallPath=[HKEY_LOCAL_MACHINE\SOFTWARE\Firaxis Games\Sid Meier's Civilization 4]=@"INSTALLDIR" RootPath= ExtractFolder=C:\Projects\Main\Civilization4\assets @@ -168,7 +174,9 @@ TextureSearchPaths= GoToSkeletonBindPosition=1 DummyNodeMatches=MD;Bip;Bip??;* NonAccum;Effect*;Sound*;Dummy* -[DAoC] +[Dark Age of Camelot] +NiVersion=10.1.0.0 +NiUserVersion=0 Isles_InstallPath=[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Dark Age of Camelot - Shrouded Isles_is1]=@"InstallLocation" RootPath= ExtractFolder= @@ -177,4 +185,8 @@ TextureRootPaths=$(ExtractFolder) TextureExtensions=.dds;.bmp;.tga TextureSearchPaths= GoToSkeletonBindPosition=1 -ApplyOverallTransformToSkinAndBones=0 \ No newline at end of file +ApplyOverallTransformToSkinAndBones=0 + +[User] +NiVersion=20.0.0.5 +NiUserVersion=0 diff --git a/NifCommon/AppSettings.cpp b/NifCommon/AppSettings.cpp index 59cbb30c72e80851afe5047c31700cc9a02eb381..efb8b9c9ab6cbdde700f327a4554aa36801eab97 100644 --- a/NifCommon/AppSettings.cpp +++ b/NifCommon/AppSettings.cpp @@ -2,6 +2,7 @@ #include <string.h> #include <tchar.h> #include "AppSettings.h" +#include "IniSection.h" AppSettingsMap TheAppSettings; @@ -18,6 +19,7 @@ void AppSettings::Initialize(Interface *gi) string Applications = GetIniValue<string>("System", "KnownApplications", "", iniName); stringlist apps = TokenizeString(Applications.c_str(), ";"); + apps.push_back(string("User")); // always ensure that user is present for (stringlist::iterator appstr=apps.begin(); appstr != apps.end(); ++appstr){ AppSettings* setting = FindAppSetting(*appstr); if (NULL == setting){ @@ -46,6 +48,9 @@ void AppSettings::ReadSettings(string iniFile) std::swap(Environment, settings); + NiVersion = GetSetting<string>("NiVersion", "20.0.0.5"); + NiUserVersion = GetSetting<int>("NiUserVersion", 0); + rootPath = GetSetting<string>("RootPath"); rootPaths = TokenizeString(GetSetting<string>("RootPaths").c_str(), ";"); searchPaths = TokenizeString(GetSetting<string>("TextureSearchPaths").c_str(), ";"); @@ -61,6 +66,19 @@ void AppSettings::ReadSettings(string iniFile) dummyNodeMatches = TokenizeString(GetSetting<string>("DummyNodeMatches").c_str(), ";"); } +void AppSettings::WriteSettings(Interface *gi) +{ + TCHAR iniName[MAX_PATH]; + LPCTSTR pluginDir = gi->GetDir(APP_PLUGCFG_DIR); + PathCombine(iniName, pluginDir, "MaxNifTools.ini"); + if (-1 != _taccess(iniName, 0)) + { + SetIniValue(Name.c_str(), "NiVersion", NiVersion.c_str(), iniName); + SetIniValue(Name.c_str(), "NiUserVersion", FormatString("%d", NiUserVersion).c_str(), iniName); + } +} + + string AppSettings::FindImage(const string& fname){ TCHAR buffer[MAX_PATH]; diff --git a/NifCommon/AppSettings.h b/NifCommon/AppSettings.h index 0d7cfecf7549749dc2deef643e59401e4a06cd77..3e009eec0add25fbc42bd39a6795a13506c15810 100644 --- a/NifCommon/AppSettings.h +++ b/NifCommon/AppSettings.h @@ -42,9 +42,12 @@ public: NameValueCollection imgTable; stringlist dummyNodeMatches; int applyOverallTransformToSkinAndBones; + std::string NiVersion; + int NiUserVersion; static void Initialize(Interface *gi); void ReadSettings(std::string iniFile); + void WriteSettings(Interface *gi); std::string FindImage(const std::string& fname); // Check whether the given file is a child of the root paths diff --git a/NifCommon/IniSection.h b/NifCommon/IniSection.h new file mode 100644 index 0000000000000000000000000000000000000000..e42f6a8ded61cb5cb33612f45f897cde6298b362 --- /dev/null +++ b/NifCommon/IniSection.h @@ -0,0 +1,124 @@ +#pragma once + +#include <string> +#include <list> +enum INIDEFTYPE +{ + IDT_STRING, + IDT_INT, + IDT_FLOAT, + IDT_BOOL, + IDT_FILENAME, + IDT_UNKNOWN, +}; + +struct INIDEF +{ + INIDEF() : ShortName(NULL), IniName(NULL), MemberAddr(0), Description(NULL), DefaultValue(NULL), ValueSize(0) { + } + + ~INIDEF() { + if (ValueSize && DefaultValue) { + delete DefaultValue; + DefaultValue = NULL; + ValueSize = 0; + } + } + + template<typename U> + INIDEF(LPCTSTR sName, LPCTSTR iName, const U& member, U default, LPCTSTR desc, INIDEFTYPE type) + : ShortName(sName), IniName(iName), MemberAddr(NULL), Description(NULL), MemberType(type) { + SetDefault(default); + } + + template<> + INIDEF(LPCTSTR sName, LPCTSTR iName, const std::string& member, std::string default, LPCTSTR desc, INIDEFTYPE type) + : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { + MemberType = type==IDT_UNKNOWN?IDT_STRING:type; + SetDefault(default); + } + + template<> + INIDEF(LPCTSTR sName, LPCTSTR iName, const int& member, int default, LPCTSTR desc, INIDEFTYPE type) + : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { + MemberType = type==IDT_UNKNOWN?IDT_INT:type; + SetDefault(default); + } + + template<> + INIDEF(LPCTSTR sName, LPCTSTR iName, const float& member, float default, LPCTSTR desc, INIDEFTYPE type) + : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { + MemberType = type==IDT_UNKNOWN?IDT_FLOAT:type; + SetDefault(default); + } + + template<> + INIDEF(LPCTSTR sName, LPCTSTR iName, const bool& member, bool default, LPCTSTR desc, INIDEFTYPE type) + : ShortName(sName), IniName(iName), MemberAddr((DWORD)&member), Description(NULL) { + MemberType = type==IDT_UNKNOWN?IDT_BOOL:type; + SetDefault(default); + } + + template<typename U> + void SetDefault(U default) { + ValueSize = sizeof(U); + DefaultValue = new U(default); + } + + template <typename U> + const U& GetDefault() const { + return *(U*)DefaultValue; + } + + LPCTSTR ShortName; + LPCTSTR IniName; + DWORD MemberAddr; + INIDEFTYPE MemberType; + LPCTSTR Description; + LPVOID DefaultValue; + DWORD ValueSize; +}; + +#define BEGIN_INI_MAP(name) \ + virtual void *GetMember(const INIDEF* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \ + virtual const INIDEF* GetInfDefmap() const { return InternalGetInfDefmap(); } \ + static INIDEF* InternalGetInfDefmap() { \ + const name* pThis = 0; \ + static INIDEF map[] = { \ + +#define BEGIN_INI_MAP_WITH_BASE(name, base) \ + virtual void *GetMember(const INIDEF* memptr) const { return (void*)(((char*)this) + memptr->MemberAddr); } \ + virtual const INIDEF* GetInfDefmap() const { return InternalGetInfDefmap(); } \ + static INIDEF* InternalGetInfDefmap() { \ + const name* pThis = 0; \ + static INIDEF map[] = { \ + +#define END_INI_MAP() \ + INIDEF() };\ + return map;\ +} + +#define ADDITEM(sName, iName, member, desc) \ + INIDEF(sName, iName, pThis->member, desc, IDT_UNKNOWN), \ + +#define ADDITEMEX(sName, iName, member, type, desc) \ + INIDEF(sName, iName, pThis->member, desc, type), \ + +struct IniFileSection +{ + virtual LPCTSTR GetName() const = 0; + virtual const INIDEF* GetInfDefmap() const = 0; + virtual void *GetMember(const INIDEF* memptr) const = 0; +}; + +typedef std::list<IniFileSection*> IniFileSectionList; + +inline int GetIniDefSectionSize(IniFileSection *section) { + int len = 0; + + for (const INIDEF *inidef = section->GetInfDefmap() + ; inidef != NULL && inidef->ShortName + ; ++inidef) + ++len; + return len; +} \ No newline at end of file diff --git a/NifCommon/NifCommon_VC80.vcproj b/NifCommon/NifCommon_VC80.vcproj index 0f75d8fe4a6085024ed57d10801e1541386f3b1d..d8d7fc716fcd9875706ccd7b194dbcfe9aee1078 100644 --- a/NifCommon/NifCommon_VC80.vcproj +++ b/NifCommon/NifCommon_VC80.vcproj @@ -504,6 +504,10 @@ RelativePath=".\AppSettings.h" > </File> + <File + RelativePath=".\IniSection.h" + > + </File> <File RelativePath=".\NifGui.h" > @@ -516,6 +520,10 @@ RelativePath=".\niutils.h" > </File> + <File + RelativePath=".\objectParams.h" + > + </File> <File RelativePath=".\pch.h" > diff --git a/NifCommon/niutils.cpp b/NifCommon/niutils.cpp index 3f2190afafdf38b239afd0220d83afe5d2fa0793..f6e0b75f433f7da0f505a7abfbcdcc19574befbc 100644 --- a/NifCommon/niutils.cpp +++ b/NifCommon/niutils.cpp @@ -70,12 +70,12 @@ std::string FormatString(const TCHAR* format,...) } // Tokenize a string using strtok and return it as a stringlist -stringlist TokenizeString(LPCTSTR str, LPCTSTR delims) +stringlist TokenizeString(LPCTSTR str, LPCTSTR delims, bool trim) { stringlist values; LPTSTR buf = STRDUPA(str); for (LPTSTR p = _tcstok(buf, delims); p && *p; p = _tcstok(NULL, delims)){ - values.push_back(string(p)); + values.push_back(string((trim) ? Trim(p) : p)); } return values; } @@ -583,6 +583,22 @@ TriObject* GetTriObject(Object *o) } // Get or Create the Skin Modifier +Modifier *GetOrCreateSkin(INode *node) +{ + Modifier *skinMod = GetSkin(node); + if (skinMod) + return skinMod; + + IDerivedObject *dobj = CreateDerivedObject(node->GetObjectRef()); + //create a skin modifier and add it + skinMod = (Modifier*) CreateInstance(OSM_CLASS_ID, SKIN_CLASSID); + dobj->SetAFlag(A_LOCK_TARGET); + dobj->AddModifier(skinMod); + dobj->ClearAFlag(A_LOCK_TARGET); + node->SetObjectRef(dobj); + return skinMod; +} + Modifier *GetSkin(INode *node) { Object* pObj = node->GetObjectRef(); @@ -604,14 +620,65 @@ Modifier *GetSkin(INode *node) } pObj = pDerObj->GetObjRef(); } + return NULL; +} - IDerivedObject *dobj = CreateDerivedObject(node->GetObjectRef()); - //create a skin modifier and add it - Modifier *skinMod = (Modifier*) CreateInstance(OSM_CLASS_ID, SKIN_CLASSID); - dobj->SetAFlag(A_LOCK_TARGET); - dobj->AddModifier(skinMod); - dobj->ClearAFlag(A_LOCK_TARGET); - node->SetObjectRef(dobj); - return skinMod; -} +TSTR GetFileVersion(const char *fileName) +{ + TSTR retval; + char fileVersion[MAX_PATH]; + if (fileName == NULL) + { + GetModuleFileName(hInstance, fileVersion, MAX_PATH); + fileName = fileVersion; + } + HMODULE ver = GetModuleHandle("version.dll"); + if (!ver) ver = LoadLibrary("version.dll"); + if (ver != NULL) + { + DWORD (APIENTRY *GetFileVersionInfoSize)(LPCTSTR, LPDWORD) = NULL; + BOOL (APIENTRY *GetFileVersionInfo)(LPCTSTR, DWORD, DWORD, LPVOID) = NULL; + BOOL (APIENTRY *VerQueryValue)(const LPVOID, LPTSTR, LPVOID *, PUINT) = NULL; + *(FARPROC*)&GetFileVersionInfoSize = GetProcAddress(ver, "GetFileVersionInfoSizeA"); + *(FARPROC*)&GetFileVersionInfo = GetProcAddress(ver, "GetFileVersionInfoA"); + *(FARPROC*)&VerQueryValue = GetProcAddress(ver, "VerQueryValueA"); + if (GetFileVersionInfoSize && GetFileVersionInfo && VerQueryValue) + { + DWORD vLen = 0; + DWORD vSize = GetFileVersionInfoSize(fileName,&vLen); + if (vSize) + { + LPVOID versionInfo = malloc(vSize+1); + if (GetFileVersionInfo(fileName,vLen,vSize,versionInfo)) + { + LPVOID version=NULL; + if (VerQueryValue(versionInfo,"\\VarFileInfo\\Translation",&version,(UINT *)&vLen) && vLen==4) + { + DWORD langD = *(DWORD*)version; + sprintf(fileVersion, "\\StringFileInfo\\%02X%02X%02X%02X\\ProductVersion", + (langD & 0xff00)>>8,langD & 0xff,(langD & 0xff000000)>>24, (langD & 0xff0000)>>16); + } + else + { + sprintf(fileVersion, "\\StringFileInfo\\%04X04B0\\ProductVersion", GetUserDefaultLangID()); + } + LPCTSTR value = NULL; + if (VerQueryValue(versionInfo,fileVersion,&version,(UINT *)&vLen)) + value = LPCTSTR(version); + else if (VerQueryValue(versionInfo,"\\StringFileInfo\\040904B0\\ProductVersion",&version,(UINT *)&vLen)) + value = LPCTSTR(version); + if (value != NULL) + { + stringlist val = TokenizeString(value, ",", true); + if (val.size() >= 4){ + retval = FormatText("%s.%s.%s.%s", val[0].c_str(), val[1].c_str(), val[2].c_str(), val[3].c_str()); + } + } + free(versionInfo); + } + } + } + } + return retval; +} \ No newline at end of file diff --git a/NifCommon/niutils.h b/NifCommon/niutils.h index 1a8cf8f0ef58eda64eee8555d53fd0b4ef37c198..11aaec24bd1ff57a61c31053bafeed5381b91740 100644 --- a/NifCommon/niutils.h +++ b/NifCommon/niutils.h @@ -121,7 +121,7 @@ struct NumericStringEquivalence // Common collections that I use typedef std::map<std::string, std::string, ltstr> NameValueCollection; typedef std::pair<std::string, std::string> KeyValuePair; -typedef std::list<std::string> stringlist; +typedef std::vector<std::string> stringlist; extern int wildcmp(const TCHAR *wild, const TCHAR *string); extern int wildcmpi(const TCHAR *wild, const TCHAR *string); @@ -209,7 +209,7 @@ inline void SetIniValue<TSTR>(LPCTSTR Section, LPCTSTR Setting, TSTR value, LPCT extern TSTR FormatText(const TCHAR* format,...); extern std::string FormatString(const TCHAR* format,...); -extern stringlist TokenizeString(LPCTSTR str, LPCTSTR delims); +extern stringlist TokenizeString(LPCTSTR str, LPCTSTR delims, bool trim=false); extern string GetIndirectValue(LPCSTR path); extern NameValueCollection ReadIniSection(LPCTSTR Section, LPCTSTR iniFileName ); extern string ExpandQualifiers(const string& src, const NameValueCollection& map); @@ -271,6 +271,9 @@ static inline Color TOCOLOR(const Niflib::Color3& c3) { return Color(c3.r, c3.g, c3.b); } +static inline Niflib::Color3 TOCOLOR3(const Color& c3) { + return Niflib::Color3(c3.r, c3.g, c3.b); +} static inline Point3 TOPOINT3(const Niflib::Vector3& v){ return Point3(v.x, v.y, v.z); @@ -334,7 +337,10 @@ inline Niflib::Ref<U> SelectFirstObjectOfType( list<Niflib::Ref<T> > const & obj TSTR PrintMatrix3(Matrix3& m); TSTR PrintMatrix44(Niflib::Matrix44& m); +extern Modifier *GetOrCreateSkin(INode *node); extern Modifier *GetSkin(INode *node); extern TriObject* GetTriObject(Object *o); +extern TSTR GetFileVersion(const char *fileName); + #endif // _NIUTILS_H_ \ No newline at end of file diff --git a/NifCommon/objectParams.h b/NifCommon/objectParams.h index 23a45f424dc7db9d93716af5ca3aeacb2c484102..9773e3e0b076371a4e3ad44955e921b8c77061c1 100644 --- a/NifCommon/objectParams.h +++ b/NifCommon/objectParams.h @@ -32,7 +32,7 @@ inline Value* make_maxscript_value(const Color& rgb); inline Value* make_maxscript_value(LPCTSTR str); inline Value* make_maxscript_value(ReferenceTarget* rtarg); -#if VERSION_3DSMAX <= ((MAX_RELEASE_R7<<16)+(15<<8)+0) +#if VERSION_3DSMAX <= ((7000<<16)+(15<<8)+0) // Version 7 inline void clear_error_source_data() {} #endif @@ -317,7 +317,8 @@ inline float ConvertMAXScriptToC<float>::cvt(Value* val) inline Color ConvertMAXScriptToC<Color>::cvt(Value* val) { - return val->to_point3(); + Point3 pt3 = val->to_point3(); + return Color(pt3.x/255.0f, pt3.y/255.0f, pt3.z/255.0f); } inline LPTSTR ConvertMAXScriptToC<LPTSTR>::cvt(Value* val) diff --git a/NifExport/Coll.cpp b/NifExport/Coll.cpp index 20a7ab684917a195939e1c69a6b42673f6649f0e..5c8f30f7e431ca774d9f85efc7971a4ae2cef901 100755 --- a/NifExport/Coll.cpp +++ b/NifExport/Coll.cpp @@ -252,6 +252,9 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) // marked as collision? bool coll = npIsCollision(node); + bool local = !mFlattenHierarchy; + NiNodeRef nodeParent = mFlattenHierarchy ? mNiRoot : parent; + NiNodeRef newParent; if (coll) { @@ -275,7 +278,7 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) body->SetRotation(q); body->SetTranslation(Vector3(trans.x/7, trans.y/7, trans.z/7)); */ - newParent = makeNode(parent, node); + newParent = nodeParent; // always have collision one level up? bhkSphereRepShapeRef shape = makeCollisionShape(node); bhkRigidBodyRef body = makeCollisionBody(node); @@ -283,18 +286,17 @@ Exporter::Result Exporter::exportCollision(NiNodeRef &parent, INode *node) bhkCollisionObjectRef co = DynamicCast<bhkCollisionObject>(CreateBlock("bhkCollisionObject")); co->SetBody(DynamicCast<NiObject>(body)); + co->SetParent(newParent); // link newParent->SetCollisionObject(DynamicCast<NiCollisionObject>(co)); - } else - if (isCollisionGroup(node)) - { - newParent = makeNode(parent, node); - } else - newParent = parent; - + } else if (isCollisionGroup(node) && !mFlattenHierarchy) { + newParent = makeNode(nodeParent, node); + } else { + newParent = nodeParent; + } for (int i=0; i<node->NumberOfChildren(); i++) { Result result = exportCollision(newParent, node->GetChildNode(i)); @@ -315,13 +317,13 @@ bhkRigidBodyRef Exporter::makeCollisionBody(INode *node) // Handle compatibility npGetProp(node, NP_HVK_MASS_OLD, mass, NP_DEFAULT_HVK_EMPTY); - if (mass != NP_DEFAULT_HVK_EMPTY) + if (mass == NP_DEFAULT_HVK_EMPTY) npGetProp(node, NP_HVK_MASS, mass, NP_DEFAULT_HVK_MASS); npGetProp(node, NP_HVK_FRICTION_OLD, frict, NP_DEFAULT_HVK_EMPTY); - if (frict != NP_DEFAULT_HVK_EMPTY) + if (frict == NP_DEFAULT_HVK_EMPTY) npGetProp(node, NP_HVK_FRICTION, frict, NP_DEFAULT_HVK_FRICTION); npGetProp(node, NP_HVK_RESTITUTION_OLD, resti, NP_DEFAULT_HVK_EMPTY); - if (resti != NP_DEFAULT_HVK_EMPTY) + if (resti == NP_DEFAULT_HVK_EMPTY) npGetProp(node, NP_HVK_RESTITUTION, resti, NP_DEFAULT_HVK_RESTITUTION); npGetProp(node, NP_HVK_LAYER, lyr, NP_DEFAULT_HVK_LAYER); @@ -336,7 +338,7 @@ bhkRigidBodyRef Exporter::makeCollisionBody(INode *node) npGetProp(node, NP_HVK_CENTER, center); // setup body - bhkRigidBodyRef body = DynamicCast<bhkRigidBody>(CreateBlock("bhkRigidBody")); + bhkRigidBodyRef body = DynamicCast<bhkRigidBody>(CreateBlock("bhkRigidBodyT")); body->SetLayer(lyr); body->SetLayerCopy(lyr); @@ -351,6 +353,8 @@ bhkRigidBodyRef Exporter::makeCollisionBody(INode *node) body->SetMaxAngularVelocity(maxangvel); body->SetPenetrationDepth(pendepth); body->SetCenter(center); + QuaternionXYZW q; q.x = q.y = q.z = 0; q.w = 1.0f; + body->SetRotation(q); return body; } @@ -490,7 +494,6 @@ bhkSphereRepShapeRef Exporter::makeTriStripsShape(INode *node) shape->SetUnknownInts1(unknownInts1); */ - ASSERT(!"TODO: Need to support this"); /* Still not handled vector<uint> unknownInts2; unknownInts2.resize(1); diff --git a/NifExport/Config.cpp b/NifExport/Config.cpp index 5c4937cadb20e65d8f923e8f922cad1db6c0e984..f9ab7303a6158bd3d9ec593149f5a5ae719c2d76 100755 --- a/NifExport/Config.cpp +++ b/NifExport/Config.cpp @@ -57,6 +57,13 @@ void Exporter::writeConfig(Interface *i) SetIniValue(NifExportSection, "TexturePrefix", mTexPrefix, iniName); SetIniValue(NifExportSection, "ExportCollision", mExportCollision, iniName); SetIniValue(NifExportSection, "RemapIndices", mRemapIndices, iniName); + + SetIniValue(NifExportSection, "ExportExtraNodes", mExportExtraNodes, iniName); + SetIniValue(NifExportSection, "ExportSkin", mExportSkin, iniName); + SetIniValue(NifExportSection, "UserPropBuffer", mUserPropBuffer, iniName); + SetIniValue(NifExportSection, "FlattenHierarchy", mFlattenHierarchy, iniName); + SetIniValue(NifExportSection, "RemoveUnreferencedBones", mRemoveUnreferencedBones, iniName); + SetIniValue(NifExportSection, "SortNodesToEnd", mSortNodesToEnd, iniName); } } diff --git a/NifExport/Exporter.cpp b/NifExport/Exporter.cpp index a38bfe331892fd4a3c5d67ff83de4f2c477aad17..57c2e09580ae43c7895d49697712751cdccb90be 100755 --- a/NifExport/Exporter.cpp +++ b/NifExport/Exporter.cpp @@ -20,6 +20,9 @@ bool Exporter::mUserPropBuffer=false; bool Exporter::mFlattenHierarchy=false; bool Exporter::mRemoveUnreferencedBones=false; bool Exporter::mSortNodesToEnd=false; +string Exporter::mGameName = "User"; +string Exporter::mNifVersion = "20.0.0.5"; +int Exporter::mNifUserVersion = 0; Exporter::Exporter(Interface *i, AppSettings *appSettings) : mI(i), mAppSettings(appSettings) @@ -28,11 +31,21 @@ Exporter::Exporter(Interface *i, AppSettings *appSettings) Exporter::Result Exporter::doExport(NiNodeRef &root, INode *node) { + //root->SetName("Scene Root"); + BSXFlagsRef bsx = CreateNiObject<BSXFlags>(); bsx->SetName("BSX"); bsx->SetFlags(0x00000002); root->AddExtraData(DynamicCast<NiExtraData>(bsx)); - exportUPB(root, node); + bool ok = exportUPB(root, node); + + if (!ok && Exporter::mExportCollision) + { + NiStringExtraDataRef strings = DynamicCast<NiStringExtraData>(CreateBlock("NiStringExtraData")); + strings->SetName("UPB"); + strings->SetData("Ellasticity = 0.300000\r\nFriction = 0.300000\r\nUnyielding = 0\r\nProxy_Geometry = <None>\r\nUse_Display_Proxy = 0\r\nDisplay_Children = 1\r\nDisable_Collisions = 0\r\nInactive = 0\r\nDisplay_Proxy = <None>\r\nMass = 0.000000\r\nSimulation_Geometry = 2\r\nCollision_Groups = 589825\r\n"); + root->AddExtraData(DynamicCast<NiExtraData>(strings)); + } mNiRoot = root; diff --git a/NifExport/Exporter.h b/NifExport/Exporter.h index a931c1be48718980b30b77c6e6906be033f09872..e73a5a4a163ca4774b1babc677131467ef4e2f54 100755 --- a/NifExport/Exporter.h +++ b/NifExport/Exporter.h @@ -5,6 +5,7 @@ using namespace Niflib; class BitmapTex; class AppSettings; +class StdMat2; class Exporter { @@ -49,6 +50,9 @@ public: static bool mFlattenHierarchy; static bool mRemoveUnreferencedBones; static bool mSortNodesToEnd; + static string mGameName; + static string mNifVersion; + static int mNifUserVersion; Exporter(Interface *i, AppSettings *appSettings); @@ -108,7 +112,8 @@ private: void nodeTransform(QuaternionXYZW &rot, Vector3 &trans, INode *node, TimeValue t, bool local=true); Point3 getVertexNormal(Mesh* mesh, int faceNo, RVertex* rv); bool equal(const Vector3 &a, const Point3 &b, float thresh); - BitmapTex *getTexture(Mtl *mtl); + BitmapTex *getTexture(Mtl *mtl); + BitmapTex *getTexture(Mtl *mtl, int i); void getTextureMatrix(Matrix3 &mat, Mtl *mtl); NiNodeRef makeNode(NiNodeRef &parent, INode *maxNode, bool local=true); NiNodeRef getNode(const string& name); @@ -138,8 +143,10 @@ private: /* texture & material */ // creates NiTexturingProperty + NiSourceTexture void makeTexture(NiAVObjectRef &parent, Mtl *mtl); + bool makeTextureDesc(BitmapTex *bmTex, Niflib::TexDesc &td); // creates a NiMaterialProperty void makeMaterial(NiAVObjectRef &parent, Mtl *mtl); + bool exportCiv4Shader(NiAVObjectRef parent, Mtl* mtl); /* havok & collision */ int addVertex(vector<Vector3> &verts, vector<Vector3> &vnorms, const Point3 &pt, const Point3 &norm); diff --git a/NifExport/Mesh.cpp b/NifExport/Mesh.cpp index 2ec3cb8d42e6eafd40293523d2efb49b427ccf48..8c29ba46a93b61d848085215432dfa9294880620 100755 --- a/NifExport/Mesh.cpp +++ b/NifExport/Mesh.cpp @@ -251,7 +251,6 @@ NiTriBasedGeomRef Exporter::makeMesh(NiNodeRef &parent, Mtl *mtl, FaceGroup &grp NiAVObjectRef av(DynamicCast<NiAVObject>(shape)); makeMaterial(av, mtl); - makeTexture(av, mtl); parent->AddChild(DynamicCast<NiAVObject>(shape)); @@ -265,8 +264,10 @@ int Exporter::addVertex(FaceGroup &grp, int face, int vi, Mesh *mesh, const Matr Point3 norm = getVertexNormal(mesh, face, mesh->getRVertPtr(vidx)); Point3 uv; - if (mesh->tVerts && mesh->tvFace) + if (mesh->tVerts && mesh->tvFace) { uv = mesh->tVerts[ mesh->tvFace[ face ].t[ vi ]] * texm; + uv.y += 1.0f; + } Color4 col(1.0f, 1.0f, 1.0f); if (mVertexColors && !vertColors.empty()){ @@ -282,7 +283,7 @@ int Exporter::addVertex(FaceGroup &grp, int face, int vi, Mesh *mesh, const Matr if (equal(grp.verts[i], pt, mWeldThresh) && equal(grp.vnorms[i], norm, 0)) { - if (mesh->tvFace && (grp.uvs[i].u!=uv.x || grp.uvs[i].v!=uv.y)) + if (mesh->tVerts && mesh->tvFace && (grp.uvs[i].u!=uv.x || grp.uvs[i].v!=uv.y)) continue; if (mVertexColors && !vertColors.empty() && diff --git a/NifExport/MtlTex.cpp b/NifExport/MtlTex.cpp index a18a2b2886d785a9a1fa328f7be4c8f4cef14808..75b4089cd2050e44187e0961f0ab882b4a14ba92 100755 --- a/NifExport/MtlTex.cpp +++ b/NifExport/MtlTex.cpp @@ -1,20 +1,76 @@ #include "pch.h" #include "stdmat.h" +#include "shaders.h" #include "AppSettings.h" +#include "obj/NiWireframeProperty.h" +#include "obj/NiAlphaProperty.h" +#include "obj/NiStencilProperty.h" +#include "obj/NiShadeProperty.h" +#include "obj/NiVertexColorProperty.h" +#include "obj/NiDitherProperty.h" +#include "obj/NiSpecularProperty.h" void Exporter::makeTexture(NiAVObjectRef &parent, Mtl *mtl) { - BitmapTex *bmTex = getTexture(mtl); - + BitmapTex *bmTex = getTexture(mtl); if (!bmTex) - return; + return; - NiTexturingPropertyRef texProp(DynamicCast<NiTexturingProperty>(CreateBlock("NiTexturingProperty"))); + NiTexturingPropertyRef texProp = CreateNiObject<NiTexturingProperty>(); texProp->SetApplyMode(APPLY_MODULATE); texProp->SetTextureCount(7); TexDesc td; - td.source = DynamicCast<NiSourceTexture>(CreateBlock("NiSourceTexture")); + if (makeTextureDesc(bmTex, td)) + texProp->SetTexture(BASE_MAP, td); + + NiPropertyRef prop = DynamicCast<NiProperty>(texProp); + parent->AddProperty(prop); +} + +bool Exporter::makeTextureDesc(BitmapTex *bmTex, TexDesc& td) +{ + td.source = CreateNiObject<NiSourceTexture>(); + + // Filtering + switch (bmTex->GetFilterType()) + { + case FILTER_PYR: td.filterMode = FILTER_TRILERP; break; + case FILTER_SAT: td.filterMode = FILTER_BILERP; break; + case FILTER_NADA: td.filterMode = FILTER_NEAREST; break; + } + + td.clampMode = TexClampMode(); + switch (bmTex->GetTextureTiling()) + { + case 3: td.clampMode = WRAP_S_WRAP_T; break; + case 1: td.clampMode = WRAP_S_CLAMP_T; break; + case 2: td.clampMode = CLAMP_S_WRAP_T; break; + case 0: td.clampMode = CLAMP_S_CLAMP_T; break; + } + + if (UVGen *uvGen = bmTex->GetTheUVGen()){ + if (RefTargetHandle ref = uvGen->GetReference(0)){ + TexCoord trans, tiling; + float wangle; + bool ok = true; + if(ok) ok &= getMAXScriptValue(ref, "U_Offset", 0, trans.u); + if(ok) ok &= getMAXScriptValue(ref, "V_Offset", 0, trans.v); + if(ok) ok &= getMAXScriptValue(ref, "U_Tiling", 0, tiling.u); + if(ok) ok &= getMAXScriptValue(ref, "V_Tiling", 0, tiling.v); + if(ok) ok &= getMAXScriptValue(ref, "W_Angle", 0, wangle); + if (ok) { + if (trans.u != 0.0f || trans.v != 0.0f || tiling.u != 1.0f || tiling.v != 1.0f || wangle != 0.0f) { + td.hasTextureTransform = true; + td.translation = trans; + td.tiling = tiling; + td.wRotation = TORAD(wangle); + td.transformType_ = 1; + td.centerOffset = TexCoord(0.5, 0.5); + } + } + } + } // Get file name and check if it matches the "app" settings in the ini file TSTR mapPath; @@ -31,23 +87,25 @@ void Exporter::makeTexture(NiAVObjectRef &parent, Mtl *mtl) { TSTR p, f; SplitPathFile(mapPath, &p, &f); - TSTR newPath; - if (mTexPrefix != "") - newPath = TSTR(mTexPrefix.c_str()) + _T("\\") + f; - else - newPath = f; - + TSTR newPath; + if (mTexPrefix != "") + newPath = TSTR(mTexPrefix.c_str()) + _T("\\") + f; + else + newPath = f; + NiObjectRef unk_link(NULL); - td.source->SetExternalTexture(newPath.data(), unk_link); + td.source->SetExternalTexture(newPath.data(), unk_link); } - texProp->SetTexture(BASE_MAP, td); - - NiPropertyRef prop = DynamicCast<NiProperty>(texProp); - parent->AddProperty(prop); + return true; } void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl) { + // Fill-in using the Civ4 Shader if available + bool done = exportCiv4Shader(parent, mtl); + if (done) + return; + string name; NiMaterialPropertyRef mtlProp(DynamicCast<NiMaterialProperty>(CreateBlock("NiMaterialProperty"))); if (mtl) @@ -74,6 +132,29 @@ void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl) { StdMat2 * smtl = (StdMat2*)mtl; mtlProp->SetTransparency(smtl->GetOpacity(0)); + + if (smtl->SupportsShaders()) { + if (Shader *s = smtl->GetShader()) { + if (smtl->GetWire()){ + NiWireframePropertyRef wireProp = CreateNiObject<NiWireframeProperty>(); + wireProp->SetFlags(1); + parent->AddProperty(wireProp); + } + if (smtl->GetTwoSided()){ + NiStencilPropertyRef stencil = CreateNiObject<NiStencilProperty>(); + stencil->SetStencilFunction(4); + stencil->SetStencilEnabled(false); + stencil->SetPassAction(3); + stencil->SetDrawMode(3); + parent->AddProperty(stencil); + } + if (smtl->IsFaceted()) { + NiShadePropertyRef shade = CreateNiObject<NiShadeProperty>(); + shade->SetFlags(0); + parent->AddProperty(shade); + } + } + } } } else { @@ -90,6 +171,8 @@ void Exporter::makeMaterial(NiAVObjectRef &parent, Mtl *mtl) NiPropertyRef prop = DynamicCast<NiProperty>(mtlProp); parent->AddProperty(prop); + + makeTexture(parent, mtl); } @@ -133,6 +216,21 @@ BitmapTex *Exporter::getTexture(Mtl *mtl) return bmTex; } +BitmapTex *Exporter::getTexture(Mtl *mtl, int i) +{ + if (mtl) { + int texMaps = mtl->NumSubTexmaps(); + if (i < texMaps) { + if (Texmap *texMap = mtl->GetSubTexmap(i)) { + if (texMap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0)) { + return (BitmapTex*)texMap; + } + } + } + } + return NULL; +} + void Exporter::getTextureMatrix(Matrix3 &mat, Mtl *mtl) { BitmapTex *tex = getTexture(mtl); @@ -141,3 +239,207 @@ void Exporter::getTextureMatrix(Matrix3 &mat, Mtl *mtl) else mat.IdentityMatrix(); } + + +bool Exporter::exportCiv4Shader(NiAVObjectRef parent, Mtl* mtl) +{ + if (!mtl) + return false; + + RefTargetHandle ref = mtl->GetReference(2/*shader*/); + if (!ref) + return false; + + TSTR shaderByName; + if(mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0) ) + { + StdMat2 * smtl = (StdMat2*)mtl; + if (smtl->SupportsShaders()) { + if (Shader *s = smtl->GetShader()) { + s->GetClassName(shaderByName); + } + } + } + if (shaderByName != TSTR("CivilizationIV Shader")) + return false; + + //if (Shader *s = mtl->GetShader()) { + // TSTR className; + // s->GetClassName(className); + // if (className != TSTR("CivilizationIV Shader")) + // return false; + + Color ambient = Color(0.0f,0.0f,0.0f), diffuse = Color(0.0f,0.0f,0.0f), specular = Color(0.0f,0.0f,0.0f), emittance = Color(0.0f,0.0f,0.0f); + float shininess = 0.0f, alpha = 0.0f, Magnitude = 0.0f, LumaScale = 0.0f, LumaOffset = 0.0f; + int TestRef = 0, srcBlend = 0, destBlend = 0, TestMode = 0; + bool AlphaTestEnable = false; + int ApplyMode = 0, SrcVertexMode = 0, LightingMode = 0; + bool VertexColorsEnable = false, SpecularEnable = false, NoSorter = false, Dither = false; + int alphaMode = 0, BaseTextureExport=0, DarkTextureExport=0, DetailTextureExport=0; + int Decal1TextureExport=0, Decal2TextureExport=0, GlossTextureExport=0, GlowTextureExport=0; + LPTSTR CustomShader = NULL; + int ShaderViewerTechnique=0, ShaderExportTechnique=0; + bool UseNormalMaps = false; + int NormalMapTechnique=0; + + bool ok = true; + + if(ok) ok &= getMAXScriptValue(ref, "ambient", 0, ambient ); + if(ok) ok &= getMAXScriptValue(ref, "diffuse", 0, diffuse ); + if(ok) ok &= getMAXScriptValue(ref, "specular", 0, specular ); + if(ok) ok &= getMAXScriptValue(ref, "emittance", 0, emittance ); + if(ok) ok &= getMAXScriptValue(ref, "shininess", 0, shininess ); + if(ok) ok &= getMAXScriptValue(ref, "alpha", 0, alpha ); + if(ok) ok &= getMAXScriptValue(ref, "Bump_Map_Magnitude", 0, Magnitude); + if(ok) ok &= getMAXScriptValue(ref, "Bump_Map_Luma_Scale", 0, LumaScale); + if(ok) ok &= getMAXScriptValue(ref, "Bump_Map_Luma_offset", 0, LumaOffset); + if(ok) ok &= getMAXScriptValue(ref, "TestRef", 0, TestRef ); + if(ok) ok &= getMAXScriptValue(ref, "AlphaTestEnable", 0, AlphaTestEnable ); + if(ok) ok &= getMAXScriptValue(ref, "Vertex_Color_Enable", 0, VertexColorsEnable); + if(ok) ok &= getMAXScriptValue(ref, "SpecularEnable", 0, SpecularEnable); + if(ok) ok &= getMAXScriptValue(ref, "NoSorter", 0, NoSorter); + if(ok) ok &= getMAXScriptValue(ref, "Dither", 0, Dither ); + if(ok) ok &= getMAXScriptValue(ref, "UseNormalMaps", 0, UseNormalMaps ); + if(ok) ok &= getMAXScriptValue(ref, "srcBlend", 0, srcBlend); + if(ok) ok &= getMAXScriptValue(ref, "destBlend", 0, destBlend); + if(ok) ok &= getMAXScriptValue(ref, "TestMode", 0, TestMode ); + if(ok) ok &= getMAXScriptValue(ref, "ApplyMode", 0, ApplyMode); + if(ok) ok &= getMAXScriptValue(ref, "SourceVertexMode", 0, SrcVertexMode); + if(ok) ok &= getMAXScriptValue(ref, "LightingMode", 0, LightingMode); + if(ok) ok &= getMAXScriptValue(ref, "alphaMode", 0, alphaMode); + if(ok) ok &= getMAXScriptValue(ref, "BaseTextureExport", 0, BaseTextureExport); + if(ok) ok &= getMAXScriptValue(ref, "DarkTextureExport", 0, DarkTextureExport); + if(ok) ok &= getMAXScriptValue(ref, "DetailTextureExport", 0, DetailTextureExport); + if(ok) ok &= getMAXScriptValue(ref, "Decal1TextureExport", 0, Decal1TextureExport); + if(ok) ok &= getMAXScriptValue(ref, "Decal2TextureExport", 0, Decal2TextureExport); + if(ok) ok &= getMAXScriptValue(ref, "GlossTextureExport", 0, GlossTextureExport); + if(ok) ok &= getMAXScriptValue(ref, "GlowTextureExport", 0, GlowTextureExport); + if(ok) ok &= getMAXScriptValue(ref, "CustomShader", 0, CustomShader ); + if(ok) ok &= getMAXScriptValue(ref, "ShaderViewerTechnique", 0, ShaderViewerTechnique); + if(ok) ok &= getMAXScriptValue(ref, "ShaderExportTechnique", 0, ShaderExportTechnique); + if(ok) ok &= getMAXScriptValue(ref, "NormalMapTechnique", 0, NormalMapTechnique ); + + if (ok) // civ4 shader + { + NiMaterialPropertyRef mtlProp = CreateNiObject<NiMaterialProperty>(); + parent->AddProperty(mtlProp); + + mtlProp->SetName((char*)mtl->GetName()); + mtlProp->SetAmbientColor(TOCOLOR3(ambient)); + mtlProp->SetDiffuseColor(TOCOLOR3(diffuse)); + mtlProp->SetSpecularColor(TOCOLOR3(specular)); + mtlProp->SetEmissiveColor(TOCOLOR3(emittance)); + mtlProp->SetGlossiness(shininess); + mtlProp->SetTransparency(alpha/100.0f); + if(mtl->ClassID() == Class_ID(DMTL_CLASS_ID, 0) ) + { + StdMat2 * smtl = (StdMat2*)mtl; + if (smtl->SupportsShaders()) { + if (Shader *s = smtl->GetShader()) { + if (smtl->GetWire()){ + NiWireframePropertyRef wireProp = CreateNiObject<NiWireframeProperty>(); + wireProp->SetFlags(1); + parent->AddProperty(wireProp); + } + if (smtl->GetTwoSided()){ + NiStencilPropertyRef stencil = CreateNiObject<NiStencilProperty>(); + stencil->SetStencilFunction(4); + stencil->SetStencilEnabled(false); + stencil->SetPassAction(3); + stencil->SetDrawMode(3); + parent->AddProperty(stencil); + } + if (smtl->IsFaceted()) { + NiShadePropertyRef shade = CreateNiObject<NiShadeProperty>(); + shade->SetFlags(0); + parent->AddProperty(shade); + } + } + } + } + if (VertexColorsEnable && (SrcVertexMode != 2 || LightingMode != 1)) { + NiVertexColorPropertyRef vertexColor = CreateNiObject<NiVertexColorProperty>(); + parent->AddProperty(vertexColor); + vertexColor->SetVertexMode(VertMode(SrcVertexMode)); + vertexColor->SetLightingMode(LightMode(LightingMode)); + vertexColor->SetFlags(LightingMode + (SrcVertexMode << 3)); + } + if (SpecularEnable) { + NiSpecularPropertyRef prop = CreateNiObject<NiSpecularProperty>(); + parent->AddProperty(prop); + prop->SetFlags(1); + + } + if (Dither) { + NiDitherPropertyRef prop = CreateNiObject<NiDitherProperty>(); + parent->AddProperty(prop); + prop->SetFlags(1); + } + if (alphaMode != 0 || AlphaTestEnable) { + // always add alpha ??? + NiAlphaPropertyRef alphaProp = CreateNiObject<NiAlphaProperty>(); + parent->AddProperty(alphaProp); + alphaProp->SetAlphaBlend(true); + if (alphaMode == 0) { // automatic + alphaProp->SetSourceBlendMode(NiAlphaProperty::BlendMode(srcBlend)); + alphaProp->SetDestBlendMode(NiAlphaProperty::BlendMode(destBlend)); + } else if (alphaMode == 1) { // None + alphaProp->SetAlphaBlend(false); + alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_SRC_ALPHA); + alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA); + } else if (alphaMode == 2) { // Standard + alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_SRC_ALPHA); + alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA); + } else if (alphaMode == 3) { // Additive + alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_ONE); + alphaProp->SetDestBlendMode(NiAlphaProperty::BM_ONE); + } else if (alphaMode == 4) { // Multiplicative + alphaProp->SetSourceBlendMode(NiAlphaProperty::BM_ZERO); + alphaProp->SetDestBlendMode(NiAlphaProperty::BM_SRC_COLOR); + } else { // Advanced + alphaProp->SetSourceBlendMode(NiAlphaProperty::BlendMode(srcBlend)); + alphaProp->SetDestBlendMode(NiAlphaProperty::BlendMode(destBlend)); + } + alphaProp->SetTestMode(NiAlphaProperty::TestMode(TestMode)); + alphaProp->SetAlphaSort(!NoSorter); + alphaProp->SetAlphaTestThreshold(TestRef); + alphaProp->SetAlphaTest(AlphaTestEnable); + } + + int ntex = mtl->NumSubTexmaps(); + if (ntex > 0) + { + ntex = min(ntex, 7); + TexType texmap[] = {BASE_MAP, DARK_MAP, DETAIL_MAP, DECAL_0_MAP, BUMP_MAP, GLOSS_MAP, GLOW_MAP, DECAL_1_MAP}; + NiTexturingPropertyRef texProp = CreateNiObject<NiTexturingProperty>(); + texProp->SetApplyMode(Niflib::ApplyMode(ApplyMode)); + texProp->SetTextureCount(7); + for (int i = 0; i < ntex; ++i) { + + BitmapTex *bmTex = getTexture(mtl, i); + if (!bmTex) + continue; + + TexDesc td; + if (makeTextureDesc(bmTex, td)) { + TexType textype = texmap[i]; + texProp->SetTexture(textype, td); + if (textype == BUMP_MAP) { + td.source->SetPixelLayout(PIX_LAY_BUMPMAP); + texProp->SetLumaOffset(LumaOffset); + texProp->SetLumaScale(LumaScale); + + Matrix22 m2; + m2[0][0] = m2[1][1] = Magnitude; + m2[0][1] = m2[1][0] = 0.0f; + texProp->SetBumpMapMatrix(m2); + } + } + } + + parent->AddProperty(texProp); + } + return true; + } + return false; +} diff --git a/NifExport/NifExport.cpp b/NifExport/NifExport.cpp index 4095a3ab849228e0a551f44405b8f0545c0f0d1a..26051600b07b974c6498c8782ea47f01f4ff7e15 100755 --- a/NifExport/NifExport.cpp +++ b/NifExport/NifExport.cpp @@ -66,6 +66,16 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA { case WM_INITDIALOG: { + // Append file version to dialog + TSTR fileVersion = GetFileVersion(NULL); + if (!fileVersion.isNull()) { + char buffer[256]; + GetWindowText(hWnd, buffer, _countof(buffer)); + _tcscat(buffer, TEXT(" ")); + _tcscat(buffer, fileVersion); + SetWindowText(hWnd, buffer); + } + imp = (NifExport *)lParam; CenterWindow(hWnd,GetParent(hWnd)); CheckDlgButton(hWnd, IDC_CHK_STRIPS, Exporter::mTriStrips); @@ -75,7 +85,23 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA CheckDlgButton(hWnd, IDC_CHK_VCOLORS, Exporter::mVertexColors); SetDlgItemText(hWnd, IDC_ED_TEXPREFIX, Exporter::mTexPrefix.c_str()); CheckDlgButton(hWnd, IDC_CHK_COLL, Exporter::mExportCollision); - CheckDlgButton(hWnd, IDC_CHK_REMAP, Exporter::mRemapIndices); + CheckDlgButton(hWnd, IDC_CHK_REMAP, Exporter::mRemapIndices); + + CheckDlgButton(hWnd, IDC_CHK_EXTRA, Exporter::mExportExtraNodes); + CheckDlgButton(hWnd, IDC_CHK_SKIN, Exporter::mExportSkin); + CheckDlgButton(hWnd, IDC_CHK_UPB, Exporter::mUserPropBuffer); + CheckDlgButton(hWnd, IDC_CHK_HIER, Exporter::mFlattenHierarchy); + CheckDlgButton(hWnd, IDC_CHK_REM_BONES, Exporter::mRemoveUnreferencedBones); + CheckDlgButton(hWnd, IDC_CHK_SORTNODES, Exporter::mSortNodesToEnd); + + string selection = Exporter::mGameName; + string version = Exporter::mNifVersion; + string userVer = FormatString("%d", Exporter::mNifUserVersion); + for (AppSettingsMap::iterator itr = TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr) + SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_ADDSTRING, 0, LPARAM(itr->Name.c_str())); + SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_SELECTSTRING, WPARAM(-1), LPARAM(selection.c_str())); + SendDlgItemMessage(hWnd, IDC_CB_VERSION, WM_SETTEXT, 0, LPARAM(version.c_str())); + SendDlgItemMessage(hWnd, IDC_CB_USER_VERSION, WM_SETTEXT, 0, LPARAM(userVer.c_str())); TSTR tmp; tmp.printf("%.4f", Exporter::mWeldThresh); @@ -92,11 +118,23 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA case WM_COMMAND: if (HIWORD(wParam) == BN_CLICKED) { - char tmp[MAX_PATH]; + char tmp[MAX_PATH], *end; bool close = false; switch (LOWORD(wParam)) { case IDOK: + // Validity Check + GetDlgItemText(hWnd, IDC_CB_VERSION, tmp, MAX_PATH); + if (tmp[0] != 0) + { + int nifVersion = GetVersion(tmp); + if (!IsVersionSupported(nifVersion)) + { + MessageBox(hWnd, FormatString("Version '%s' is not a supported version.", tmp).c_str(), "NifExport", MB_OK|MB_ICONSTOP); + return FALSE; + } + } + Exporter::mTriStrips = IsDlgButtonChecked(hWnd, IDC_CHK_STRIPS); Exporter::mExportHidden = IsDlgButtonChecked(hWnd, IDC_CHK_HIDDEN); Exporter::mExportFurn = IsDlgButtonChecked(hWnd, IDC_CHK_FURN); @@ -104,6 +142,13 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA Exporter::mVertexColors = IsDlgButtonChecked(hWnd, IDC_CHK_VCOLORS); Exporter::mExportCollision = IsDlgButtonChecked(hWnd, IDC_CHK_COLL); Exporter::mRemapIndices = IsDlgButtonChecked(hWnd, IDC_CHK_REMAP); + + Exporter::mExportExtraNodes = IsDlgButtonChecked(hWnd, IDC_CHK_EXTRA); + Exporter::mExportSkin = IsDlgButtonChecked(hWnd, IDC_CHK_SKIN); + Exporter::mUserPropBuffer = IsDlgButtonChecked(hWnd, IDC_CHK_UPB); + Exporter::mFlattenHierarchy = IsDlgButtonChecked(hWnd, IDC_CHK_HIER); + Exporter::mRemoveUnreferencedBones = IsDlgButtonChecked(hWnd, IDC_CHK_REM_BONES); + Exporter::mSortNodesToEnd = IsDlgButtonChecked(hWnd, IDC_CHK_SORTNODES); GetDlgItemText(hWnd, IDC_ED_TEXPREFIX, tmp, MAX_PATH); Exporter::mTexPrefix = tmp; @@ -111,6 +156,16 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA GetDlgItemText(hWnd, IDC_ED_WELDTHRESH, tmp, MAX_PATH); Exporter::mWeldThresh = atof(tmp); + GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH); + if (AppSettings *appSettings = FindAppSetting(tmp)) + { + Exporter::mGameName = appSettings->Name; + GetDlgItemText(hWnd, IDC_CB_VERSION, tmp, MAX_PATH); + Exporter::mNifVersion = tmp; + GetDlgItemText(hWnd, IDC_CB_USER_VERSION, tmp, MAX_PATH); + Exporter::mNifUserVersion = strtol(tmp, &end, 0); + } + EndDialog(hWnd, imp->mDlgResult=IDOK); close = true; break; @@ -124,8 +179,7 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA if (close) SendMessage(hWnd, WM_CLOSE, 0, 0); } - - if (HIWORD(wParam) == STN_CLICKED) + else if (HIWORD(wParam) == STN_CLICKED) { if (LOWORD(wParam) == IDC_LBL_LINK) { @@ -133,7 +187,21 @@ BOOL CALLBACK NifExportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARA NULL, NULL, SW_SHOWDEFAULT); } } - + else if (HIWORD(wParam) == CBN_SELCHANGE) + { + if (LOWORD(wParam) == IDC_CB_GAME) + { + char tmp[MAX_PATH]; + GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH); + if (AppSettings *appSettings = FindAppSetting(tmp)) + { + string version = appSettings->NiVersion; + string userVer = FormatString("%d", appSettings->NiUserVersion); + SendDlgItemMessage(hWnd, IDC_CB_VERSION, WM_SETTEXT, 0, LPARAM(version.c_str())); + SendDlgItemMessage(hWnd, IDC_CB_USER_VERSION, WM_SETTEXT, 0, LPARAM(userVer.c_str())); + } + } + } break; } return FALSE; @@ -243,12 +311,15 @@ int NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL appSettings = FindAppSetting(curapp); } } - if (appSettings == NULL && !TheAppSettings.empty()){ + if (appSettings == NULL && !TheAppSettings.empty()) appSettings = &TheAppSettings.front(); - } if(!suppressPrompts) { + Exporter::mGameName = appSettings->Name; + Exporter::mNifVersion = appSettings->NiVersion; + Exporter::mNifUserVersion = appSettings->NiUserVersion; + if (DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_PANEL), GetActiveWindow(), NifExportOptionsDlgProc, (LPARAM)this) != IDOK) return true; @@ -256,10 +327,28 @@ int NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL Exporter::writeConfig(i); // write config to root node Exporter::writeConfig(i->GetRootNode()); + + // Update the current app version + appSettings = FindAppSetting(Exporter::mGameName); + if (appSettings == NULL && !TheAppSettings.empty()) + appSettings = &TheAppSettings.front(); + appSettings->NiVersion = Exporter::mNifVersion; + appSettings->NiUserVersion = Exporter::mNifUserVersion; + appSettings->WriteSettings(i); } try { + int nifVersion = VER_20_0_0_5; + int nifUserVer = Exporter::mNifUserVersion; + + if (!Exporter::mNifVersion.empty()) + { + nifVersion = GetVersion(Exporter::mNifVersion); + if (!IsVersionSupported(nifVersion)) + throw exception(FormatString("Version '%s' is not a supported version.").c_str()); + } + Exporter::mSelectedOnly = (options&SCENE_EXPORT_SELECTED) != 0; Exporter exp(i, appSettings); @@ -269,7 +358,7 @@ int NifExport::DoExport(const TCHAR *name, ExpInterface *ei, Interface *i, BOOL if (result!=Exporter::Ok) throw exception("Unknown error."); - WriteNifTree(name, NiObjectRef(root), VER_20_0_0_5, 11); + WriteNifTree(name, NiObjectRef(root), nifVersion, nifUserVer); } catch (exception &e) diff --git a/NifExport/NifExport.rc b/NifExport/NifExport.rc index 038667854b98a6945469e8acfb823773be7c6033..efbb97acbaf89c7f9b54e300fcb1fe00dbc39d73 100755 --- a/NifExport/NifExport.rc +++ b/NifExport/NifExport.rc @@ -13,7 +13,7 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// Deutsch (Deutschland) resources +// German (Germany) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) #ifdef _WIN32 @@ -35,12 +35,12 @@ END #endif // APSTUDIO_INVOKED -#endif // Deutsch (Deutschland) resources +#endif // German (Germany) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// -// Englisch (USA) resources +// English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 @@ -73,48 +73,43 @@ END // Dialog // -IDD_PANEL DIALOGEX 0, 0, 200, 137 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | - WS_SYSMENU +IDD_PANEL DIALOGEX 0, 0, 207, 187 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_TOOLWINDOW CAPTION "Export Nif" FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - CONTROL "",IDC_EDIT,"CustEdit",NOT WS_VISIBLE | WS_TABSTOP,148,8, - 35,10 - CONTROL "",IDC_SPIN,"SpinnerControl",NOT WS_VISIBLE,186,7,7,10 - PUSHBUTTON "&Export",IDOK,5,115,34,14 - PUSHBUTTON "&Cancel",IDCANCEL,45,115,33,14 - CONTROL "Include &Hidden",IDC_CHK_HIDDEN,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,80,5,64,10 - CONTROL "Generate &Strips",IDC_CHK_STRIPS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,5,5,65,10 - CONTROL "Furniture &Markers",IDC_CHK_FURN,"Button", - BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,5,15,71,10 - EDITTEXT IDC_ED_TEXPREFIX,5,60,190,12,ES_AUTOHSCROLL - LTEXT "Texture &Prefix",IDC_STATIC,5,50,44,8 - CONTROL "&Lights",IDC_CHK_LIGHTS,"Button",BS_AUTOCHECKBOX | - WS_DISABLED | WS_TABSTOP,5,25,35,10 - EDITTEXT IDC_ED_WELDTHRESH,163,22,35,12,ES_AUTOHSCROLL | NOT - WS_VISIBLE | WS_DISABLED - LTEXT "Auto-&Weld",IDC_LBL_WELDTHRESH,160,30,34,8,NOT - WS_VISIBLE | WS_DISABLED - CONTROL "Export Co&llision",IDC_CHK_COLL,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,80,15,68,10 - CONTROL "&Vertex Colors",IDC_CHK_VCOLORS,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,80,25,68,10 - LTEXT "http://niftools.sourceforge.net",IDC_LBL_LINK,98,114,95, - 14,SS_NOTIFY | SS_CENTERIMAGE - CONTROL "&Remap Indices",IDC_CHK_REMAP,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,80,35,68,10 - COMBOBOX IDC_CB_GAME,5,90,105,70,CBS_DROPDOWN | CBS_SORT | - WS_DISABLED | WS_VSCROLL | WS_TABSTOP - LTEXT "Game",IDC_STATIC,5,79,66,8,WS_DISABLED - EDITTEXT IDC_CB_VERSION,115,90,45,12,ES_AUTOHSCROLL | WS_DISABLED - LTEXT "Version",IDC_STATIC,115,79,39,8,WS_DISABLED - EDITTEXT IDC_CB_USER_VERSION,165,90,30,12,ES_AUTOHSCROLL | - WS_DISABLED - LTEXT "User",IDC_STATIC,165,79,25,8,WS_DISABLED + GROUPBOX "Export:",IDC_STATIC,7,7,81,97 + CONTROL "&Hidden Nodes",IDC_CHK_HIDDEN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,17,67,10 + CONTROL "Co&llision",IDC_CHK_COLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,29,67,10 + CONTROL "&Vertex Colors",IDC_CHK_VCOLORS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,41,67,10 + CONTROL "Skin Modifier",IDC_CHK_SKIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,53,67,10 + CONTROL "&Animation",IDC_CHK_ANIMATION,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,14,65,67,10 + CONTROL "Furniture &Markers",IDC_CHK_FURN,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,14,77,67,10 + CONTROL "&Lights",IDC_CHK_LIGHTS,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_DISABLED | WS_TABSTOP,14,89,67,10 + GROUPBOX "Behaviors:",IDC_STATIC,94,6,101,97 + CONTROL "Generate &Strips",IDC_CHK_STRIPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,17,88,10 + CONTROL "&Remap Indices",IDC_CHK_REMAP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,29,88,10 + CONTROL "Extra Nodes on Mesh",IDC_CHK_EXTRA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,41,88,11 + CONTROL "Add User Prop Buffer",IDC_CHK_UPB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,53,88,11 + CONTROL "Flatten Hierarchy",IDC_CHK_HIER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,65,88,10 + CONTROL "Remove Extra Bones",IDC_CHK_REM_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,77,88,10 + CONTROL "Sort Nodes",IDC_CHK_SORTNODES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,89,88,10 + CONTROL "",IDC_SPIN,"SpinnerControl",NOT WS_VISIBLE,193,7,7,10 + CONTROL "",IDC_EDIT,"CustEdit",NOT WS_VISIBLE | WS_TABSTOP,194,18,6,10 + EDITTEXT IDC_ED_WELDTHRESH,189,30,11,12,ES_AUTOHSCROLL | NOT WS_VISIBLE | WS_DISABLED + LTEXT "Auto-&Weld",IDC_LBL_WELDTHRESH,192,42,8,8,NOT WS_VISIBLE | WS_DISABLED + LTEXT "Default Texture &Prefix:",IDC_STATIC,7,111,71,8 + EDITTEXT IDC_ED_TEXPREFIX,7,122,190,12,ES_AUTOHSCROLL + LTEXT "Game",IDC_STATIC,7,138,66,8 + COMBOBOX IDC_CB_GAME,7,149,105,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Version",IDC_STATIC,117,138,39,8 + EDITTEXT IDC_CB_VERSION,117,149,45,12,ES_AUTOHSCROLL + LTEXT "User",IDC_STATIC,167,138,25,8 + EDITTEXT IDC_CB_USER_VERSION,167,149,30,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "&Export",IDOK,5,166,34,14 + PUSHBUTTON "&Cancel",IDCANCEL,45,166,33,14 + LTEXT "http://niftools.sourceforge.net",IDC_LBL_LINK,105,166,95,14,SS_NOTIFY | SS_CENTERIMAGE END @@ -129,14 +124,53 @@ BEGIN IDD_PANEL, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 193 + RIGHTMARGIN, 200 TOPMARGIN, 7 - BOTTOMMARGIN, 130 + BOTTOMMARGIN, 180 END END #endif // APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,2,0,0 + PRODUCTVERSION 0,2,0,0 + FILEFLAGSMASK 0x37L +#ifdef _DEBUG + FILEFLAGS 0x21L +#else + FILEFLAGS 0x20L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "3ds Max Nif Exporter" + VALUE "FileVersion", "0, 2, 0, 0" + VALUE "InternalName", "NifExport.dle" + VALUE "LegalCopyright", "Copyright (c) 2006, NIF File Format Library and Tools\r\nAll rights reserved." + VALUE "OriginalFilename", "NifExport.dle" + VALUE "ProductName", "3ds Max Nif Exporter" + VALUE "ProductVersion", "0, 2, 0, 0" + VALUE "SpecialBuild", "Alpha" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + ///////////////////////////////////////////////////////////////////////////// // // String Table @@ -149,7 +183,7 @@ BEGIN IDS_SPIN "Spin" END -#endif // Englisch (USA) resources +#endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/NifExport/NifExport_VC80.vcproj b/NifExport/NifExport_VC80.vcproj index fc8e25e2ef0100924b32526d640dbcbc0fd0b6c3..dda568d17180c761d47f363dfe57d6d4527b6597 100644 --- a/NifExport/NifExport_VC80.vcproj +++ b/NifExport/NifExport_VC80.vcproj @@ -47,7 +47,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalOptions="/LD /FI"$(ProjectDir)pch.h"" + AdditionalOptions="/LD /FI"$(ProjectDir)pch.h" /Zm200" Optimization="2" InlineFunctionExpansion="2" EnableIntrinsicFunctions="true" @@ -153,7 +153,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalOptions="/LD /FI"$(ProjectDir)pch.h"" + AdditionalOptions="/LD /FI"$(ProjectDir)pch.h" /Zm200" Optimization="0" AdditionalIncludeDirectories="C:\3dsmax8\maxsdk\include;..\..\niflib;..\NifCommon" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS" @@ -250,7 +250,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalOptions="/LD /FI"$(ProjectDir)pch.h"" + AdditionalOptions="/LD /FI"$(ProjectDir)pch.h" /Zm200" Optimization="0" AdditionalIncludeDirectories="C:\3dsmax6\maxsdk\include;..\..\niflib;..\NifCommon" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS" @@ -349,7 +349,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalOptions="/LD /FI"$(ProjectDir)pch.h"" + AdditionalOptions="/LD /FI"$(ProjectDir)pch.h" /Zm200" Optimization="2" InlineFunctionExpansion="2" EnableIntrinsicFunctions="true" @@ -457,7 +457,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalOptions="/LD /FI"$(ProjectDir)pch.h"" + AdditionalOptions="/LD /FI"$(ProjectDir)pch.h" /Zm200" Optimization="2" InlineFunctionExpansion="2" EnableIntrinsicFunctions="true" @@ -563,7 +563,7 @@ /> <Tool Name="VCCLCompilerTool" - AdditionalOptions="/LD /FI"$(ProjectDir)pch.h"" + AdditionalOptions="/LD /FI"$(ProjectDir)pch.h" /Zm200" Optimization="0" AdditionalIncludeDirectories="C:\3dsmax7\maxsdk\include;..\..\niflib;..\NifCommon" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_DEPRECATE;USE_NIFLIB_TEMPLATE_HELPERS" diff --git a/NifExport/Util.cpp b/NifExport/Util.cpp index c714c707df901670b79a70dac5346865aa847a5a..b310bc015a17b53053b298b36814ec532b75af0f 100755 --- a/NifExport/Util.cpp +++ b/NifExport/Util.cpp @@ -234,12 +234,16 @@ struct SortNodeEquivalence if (!rhs) return true; string ltype = lhs->GetType().GetTypeName(); string rtype = rhs->GetType().GetTypeName(); - if (ltype == "NiNode") + if (ltype == rtype) return false; - if (rtype == "NiNode") + if (ltype == "bhkCollisionObject") return true; - if (ltype == rtype) + if (rtype == "bhkCollisionObject") return false; + if (ltype == "NiNode") + return false; + else if (rtype == "NiNode") + return true; return (ltype < rtype); } }; diff --git a/NifExport/pch.h b/NifExport/pch.h index f916d528ae7da3d1bd7ed4442a1375f2fd4d4012..34cf26caf18153a7d51953332c74dc6c67357e3f 100755 --- a/NifExport/pch.h +++ b/NifExport/pch.h @@ -13,7 +13,8 @@ #include "istdplug.h" #include "iparamb2.h" #include "iparamm2.h" - +#include "objectParams.h" +#undef ALPHA_NONE // niflib/Ref.h' header guard caused havok! // near & far diff --git a/NifExport/resource.h b/NifExport/resource.h index 520d8a8052002445c114aa5546795d1ea3692752..26b12888647b45a91583ef8ae799de1149d1f1fe 100755 --- a/NifExport/resource.h +++ b/NifExport/resource.h @@ -25,6 +25,14 @@ #define IDC_CB_VERSION 1015 #define IDC_CB_VERSION2 1016 #define IDC_CB_USER_VERSION 1016 +#define IDC_CHK_SKIN 1017 +#define IDC_CHK_ANIMATION 1018 +#define IDC_CHK_EXTRA 1019 +#define IDC_CHK_UPB 1020 +#define IDC_CHK_HIER 1021 +#define IDC_CHK_REM_BONES 1022 +#define IDC_CHECK7 1023 +#define IDC_CHK_SORTNODES 1023 #define IDC_COLOR 1456 #define IDC_EDIT 1490 #define IDC_SPIN 1496 @@ -35,7 +43,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1016 +#define _APS_NEXT_CONTROL_VALUE 1024 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/NifImport/ImportMeshAndSkin.cpp b/NifImport/ImportMeshAndSkin.cpp index 4cfdc3f3d44b7c48092a1a4ede2cab63b641f06b..846be2687dc88896d2d2161a540ec8225c4d3883 100644 --- a/NifImport/ImportMeshAndSkin.cpp +++ b/NifImport/ImportMeshAndSkin.cpp @@ -365,7 +365,7 @@ bool NifImporter::ImportSkin(ImpNode *node, NiTriBasedGeomRef triGeom) vector<NiNodeRef> nifBones = nifSkin->GetBones(); //create a skin modifier and add it - Modifier *skinMod = GetSkin(tnode); + Modifier *skinMod = GetOrCreateSkin(tnode); TriObject *triObject = GetTriObject(tnode->GetObjectRef()); Mesh& m = triObject->GetMesh(); diff --git a/NifImport/ImportMtlAndTex.cpp b/NifImport/ImportMtlAndTex.cpp index 838ba000029d2ca73d96ce6bbee2c7d3eea97b22..d99faf6936efe4d0f56ba01d830f333bc45f030f 100644 --- a/NifImport/ImportMtlAndTex.cpp +++ b/NifImport/ImportMtlAndTex.cpp @@ -16,6 +16,10 @@ HISTORY: #include "obj/NiWireframeProperty.h" #include "obj/NiAlphaProperty.h" #include "obj/NiStencilProperty.h" +#include "obj/NiShadeProperty.h" +#include "obj/NiVertexColorProperty.h" +#include "obj/NiDitherProperty.h" +#include "obj/NiSpecularProperty.h" #include "objectParams.h" using namespace Niflib; @@ -26,10 +30,50 @@ Texmap* NifImporter::CreateTexture(TexDesc& desc) string filename = texSrc->GetExternalFileName(); if (bmpMgr->CanImport(filename.c_str())){ BitmapTex *bmpTex = NewDefaultBitmapTex(); - bmpTex->SetName(texSrc->GetName().c_str()); + string name = texSrc->GetName(); + if (name.empty()) { + TCHAR buffer[MAX_PATH]; + _tcscpy(buffer, PathFindFileName(filename.c_str())); + PathRemoveExtension(buffer); + name = buffer; + } + bmpTex->SetName(name.c_str()); bmpTex->SetMapName(const_cast<TCHAR*>(FindImage(filename).c_str())); bmpTex->SetAlphaAsMono(TRUE); - bmpTex->SetAlphaSource(ALPHA_NONE); + bmpTex->SetAlphaSource(ALPHA_DEFAULT); + + switch (desc.filterMode) + { + case FILTER_TRILERP: bmpTex->SetFilterType(FILTER_PYR); break; + case FILTER_BILERP: bmpTex->SetFilterType(FILTER_SAT); break; + case FILTER_NEAREST: bmpTex->SetFilterType(FILTER_NADA); break; + } + + if (UVGen *uvGen = bmpTex->GetTheUVGen()){ + + switch (desc.clampMode) + { + case WRAP_S_WRAP_T : uvGen->SetTextureTiling(3); break; + case WRAP_S_CLAMP_T: uvGen->SetTextureTiling(1); break; + case CLAMP_S_WRAP_T: uvGen->SetTextureTiling(2); break; + case CLAMP_S_CLAMP_T:uvGen->SetTextureTiling(0); break; + } + + if (desc.hasTextureTransform) { + if (RefTargetHandle ref = uvGen->GetReference(0)){ + TexCoord trans = desc.translation; + TexCoord tiling = desc.tiling; + float wangle = TODEG(desc.wRotation); + + setMAXScriptValue(ref, "U_Offset", 0, trans.u); + setMAXScriptValue(ref, "V_Offset", 0, trans.v); + setMAXScriptValue(ref, "U_Tiling", 0, tiling.u); + setMAXScriptValue(ref, "V_Tiling", 0, tiling.v); + setMAXScriptValue(ref, "W_Angle", 0, wangle); + } + } + } + return bmpTex; } } @@ -45,6 +89,7 @@ bool NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObjec NiWireframePropertyRef wireRef = SelectFirstObjectOfType<NiWireframeProperty>(props); NiAlphaPropertyRef alphaRef = SelectFirstObjectOfType<NiAlphaProperty>(props); NiStencilPropertyRef stencilRef = SelectFirstObjectOfType<NiStencilProperty>(props); + NiShadePropertyRef shadeRef = SelectFirstObjectOfType<NiShadeProperty>(props); bool hasTexture = (texRef && matRef); if (matRef != NULL){ @@ -52,6 +97,13 @@ bool NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObjec m->SetName(matRef->GetName().c_str()); if (showTextures) m->SetMtlFlag(MTL_DISPLAY_ENABLE_FLAGS, TRUE); + + // try the civ4 shader first then default back to normal shaders + if (ImportCiv4Shader(node, avObject, m)) { + gi->GetMaterialLibrary().Add(m); + node->GetINode()->SetMtl(m); + return true; + } m->SetAmbient(TOCOLOR(matRef->GetAmbientColor()),0); m->SetDiffuse(TOCOLOR(matRef->GetDiffuseColor()),0); m->SetSpecular(TOCOLOR(matRef->GetSpecularColor()),0); @@ -64,19 +116,24 @@ bool NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObjec m->SetShininess(matRef->GetGlossiness()/100.0,0); m->SetOpacity(matRef->GetTransparency(),0); - bool hasShaderAttributes = (wireRef != NULL) || (stencilRef != NULL); + bool hasShaderAttributes = (wireRef != NULL) || (stencilRef != NULL) || (shadeRef != NULL); if (m->SupportsShaders() && hasShaderAttributes) { if (Shader *s = m->GetShader()) { if (wireRef != NULL && (wireRef->GetFlags() & 1)) { BOOL value = TRUE; - setMAXScriptValue(s->GetReference(0), "wire", 0, value); + m->SetWire(value); } if (stencilRef != NULL) { - + if (stencilRef->GetDrawMode() == 3 /*DRAW_BOTH*/) { + BOOL value = TRUE; + m->SetTwoSided(value); + } + } + if (shadeRef != NULL && shadeRef->GetFlags() & 1) { + m->SetFaceted(TRUE); } } } - if (NULL != texRef) { @@ -115,12 +172,150 @@ bool NifImporter::ImportMaterialAndTextures(ImpNode *node, NiAVObjectRef avObjec return hasTexture; } +bool NifImporter::ImportCiv4Shader(ImpNode *node, NiAVObjectRef avObject, StdMat2 *mtl) +{ + if (!useCiv4Shader || !mtl || !mtl->SupportsShaders()) + return false; + + Class_ID civ4Shader(0x670a77d0,0x23ab5c7f); + if (!mtl->SwitchShader(civ4Shader)) + return false; + + TSTR shaderByName; + if (Shader *s = mtl->GetShader()) + s->GetClassName(shaderByName); + if (shaderByName != TSTR("CivilizationIV Shader")) + return false; + + RefTargetHandle ref = mtl->GetReference(2/*shader*/); + if (!ref) + return false; + + vector<NiPropertyRef> props = avObject->GetProperties(); + + if (NiMaterialPropertyRef matRef = SelectFirstObjectOfType<NiMaterialProperty>(props)){ + Color ambient = TOCOLOR(matRef->GetAmbientColor()); + Color diffuse = TOCOLOR(matRef->GetDiffuseColor()); + Color specular = TOCOLOR(matRef->GetSpecularColor()); + Color emittance = TOCOLOR(matRef->GetEmissiveColor()); + float shininess = matRef->GetGlossiness(); + float alpha = matRef->GetTransparency() * 100.0f; + + mtl->SetShinStr(0.0,0); + mtl->SetShininess(shininess/100.0,0); + mtl->SetOpacity(alpha*100.0f,0); + + setMAXScriptValue(ref, "ambient", 0, ambient ); + setMAXScriptValue(ref, "diffuse", 0, diffuse ); + setMAXScriptValue(ref, "specular", 0, specular ); + setMAXScriptValue(ref, "emittance", 0, emittance ); + setMAXScriptValue(ref, "shininess", 0, shininess ); + setMAXScriptValue(ref, "alpha", 0, alpha ); + } + if (NiShadePropertyRef shadeRef = SelectFirstObjectOfType<NiShadeProperty>(props)) { + if (shadeRef->GetFlags() & 1){ + mtl->SetFaceted(TRUE); + } + } + if (NiWireframePropertyRef wireRef = SelectFirstObjectOfType<NiWireframeProperty>(props)) { + if (wireRef->GetFlags() & 1){ + mtl->SetWire(TRUE); + } + } + if (NiStencilPropertyRef stencilRef = SelectFirstObjectOfType<NiStencilProperty>(props)) { + mtl->SetTwoSided(TRUE); + } + bool Dither = false; + bool SpecularEnable = false; + if (NiDitherPropertyRef ditherRef = SelectFirstObjectOfType<NiDitherProperty>(props)) { + Dither = (ditherRef->GetFlags() & 1) ? true : false; + } + if (NiSpecularPropertyRef specRef = SelectFirstObjectOfType<NiSpecularProperty>(props)) { + SpecularEnable = (specRef->GetFlags() & 1) ? true : false; + } + setMAXScriptValue(ref, "Dither", 0, Dither ); + setMAXScriptValue(ref, "SpecularEnable", 0, SpecularEnable); + + if (NiVertexColorPropertyRef vertexColor = SelectFirstObjectOfType<NiVertexColorProperty>(props)) { + int SrcVertexMode = vertexColor->GetVertexMode(); + int LightingMode = vertexColor->GetLightingMode(); + bool VertexColorsEnable = true; + setMAXScriptValue(ref, "Vertex_Color_Enable", 0, VertexColorsEnable); + setMAXScriptValue(ref, "SourceVertexMode", 0, SrcVertexMode); + setMAXScriptValue(ref, "LightingMode", 0, LightingMode); + } else { + bool VertexColorsEnable = false; + setMAXScriptValue(ref, "Vertex_Color_Enable", 0, VertexColorsEnable); + } + if (NiAlphaPropertyRef alphaRef = SelectFirstObjectOfType<NiAlphaProperty>(props)) { + int TestRef = alphaRef->GetAlphaTestThreshold(); + int srcBlend = alphaRef->GetSourceBlendMode(); + int destBlend = alphaRef->GetDestBlendMode(); + int TestMode = alphaRef->GetTestMode(); + bool AlphaTestEnable = alphaRef->GetAlphaTest(); + bool NoSorter = !alphaRef->GetAlphaSort(); + bool alphaBlend = alphaRef->GetAlphaBlend(); + int alphaMode = 1; + + if (!alphaBlend) { + alphaMode = 1; // none + } else if (srcBlend == NiAlphaProperty::BM_SRC_ALPHA && destBlend == NiAlphaProperty::BM_ONE_MINUS_SRC_ALPHA) { + alphaMode = 0; // standard or automatic? + } else if (srcBlend == NiAlphaProperty::BM_ONE && destBlend == NiAlphaProperty::BM_ONE) { + alphaMode = 3; + } else if (srcBlend == NiAlphaProperty::BM_ZERO && destBlend == NiAlphaProperty::BM_SRC_COLOR) { + alphaMode = 4; + } else { + alphaMode = 5; + } + setMAXScriptValue(ref, "AlphaTestEnable", 0, AlphaTestEnable ); + setMAXScriptValue(ref, "alphaMode", 0, alphaMode); + setMAXScriptValue(ref, "srcBlend", 0, srcBlend); + setMAXScriptValue(ref, "destBlend", 0, destBlend); + setMAXScriptValue(ref, "NoSorter", 0, NoSorter); + setMAXScriptValue(ref, "TestRef", 0, TestRef ); + setMAXScriptValue(ref, "TestMode", 0, TestMode ); + } + if (NiTexturingPropertyRef texRef = SelectFirstObjectOfType<NiTexturingProperty>(props)) { + Matrix22 m2 = texRef->GetBumpMapMatrix(); + float Magnitude = (m2[0][0] + m2[1][1]) / 2.0f; + float LumaScale = texRef->GetLumaScale(); + float LumaOffset = texRef->GetLumaOffset(); + int ApplyMode = texRef->GetApplyMode(); + + setMAXScriptValue(ref, "Bump_Map_Magnitude", 0, Magnitude); + setMAXScriptValue(ref, "Bump_Map_Luma_Scale", 0, LumaScale); + setMAXScriptValue(ref, "Bump_Map_Luma_offset", 0, LumaOffset); + setMAXScriptValue(ref, "ApplyMode", 0, ApplyMode); + + int ntex = mtl->NumSubTexmaps(); + if (ntex > 0) + { + ntex = min(ntex, 7); + TexType texmap[] = {BASE_MAP, DARK_MAP, DETAIL_MAP, DECAL_0_MAP, BUMP_MAP, GLOSS_MAP, GLOW_MAP, DECAL_1_MAP}; + NiTexturingPropertyRef texProp = CreateNiObject<NiTexturingProperty>(); + texProp->SetApplyMode(Niflib::ApplyMode(ApplyMode)); + texProp->SetTextureCount(7); + for (int i = 0; i < ntex; ++i) { + TexType textype = texmap[i]; + if (texRef->HasTexture(textype)){ + if (Texmap* tex = CreateTexture(texRef->GetTexture(textype))) { + mtl->SetSubTexmap(i, tex); + } + } + } + } + } + return true; +} + + string NifImporter::FindImage(const string& name) { TCHAR buffer[MAX_PATH]; // Simply check for fully qualified path - if (PathIsRoot(name.c_str())) { + if (!PathIsRelative(name.c_str())) { if (-1 != _taccess(name.c_str(), 0)) return string(buffer); } @@ -138,4 +333,6 @@ string NifImporter::FindImage(const string& name) return appSettings->FindImage(name); } return name; -} \ No newline at end of file +} + + diff --git a/NifImport/ImportSkeleton.cpp b/NifImport/ImportSkeleton.cpp index 885d9307f21f757fe5c7491ac6dfe76bc6b1a99a..dfc2eb05d1b15c09de9ba895eba9f855fe68f60b 100644 --- a/NifImport/ImportSkeleton.cpp +++ b/NifImport/ImportSkeleton.cpp @@ -611,10 +611,7 @@ void NifImporter::ImportBones(NiNodeRef node, bool recurse) else if (bone = CreateBone(name, p, pp, zAxis)) { PosRotScaleNode(bone, p, q, scale, prs); - if (isDummy) - bone->Hide(TRUE); - else - bone->Hide(node->GetHidden() ? TRUE : FALSE); + bone->Hide(node->GetHidden() ? TRUE : FALSE); } if (bone) { diff --git a/NifImport/MaxNifImport.cpp b/NifImport/MaxNifImport.cpp index 40f861f38063688af2cf9bd8ba990616856fe2b2..9af93ff400107ef8195ed814b3fea1e1beb4d565 100644 --- a/NifImport/MaxNifImport.cpp +++ b/NifImport/MaxNifImport.cpp @@ -64,44 +64,6 @@ class MaxNifImportClassDesc : public ClassDesc2 { static MaxNifImportClassDesc MaxNifImportDesc; ClassDesc2* GetMaxNifImportDesc() { return &MaxNifImportDesc; } -BOOL CALLBACK MaxNifImportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { - static NifImporter *imp = NULL; - - switch(message) { - case WM_INITDIALOG: - { - imp = (NifImporter *)lParam; - CenterWindow(hWnd,GetParent(hWnd)); - - char buffer[33] = {0}; - sprintf(buffer, "%f", imp->bipedHeight); - SetWindowText(GetDlgItem(hWnd, IDC_EDITHEIGHT), buffer); - } - return TRUE; - - case WM_CLOSE: - { - char buffer[33] = {0}, *end = NULL; - GetWindowText(GetDlgItem(hWnd, IDC_EDITHEIGHT), buffer, 33); - imp->bipedHeight = strtod(buffer, &end); - EndDialog(hWnd, 0); - } - return TRUE; - - case WM_COMMAND : - { - switch (wParam) - { - case IDCLOSE : - SendMessage(hWnd, WM_CLOSE, 0, 0); - return TRUE; - } - } - break; - } - return FALSE; -} - //--- MaxNifImport ------------------------------------------------------- MaxNifImport::MaxNifImport() diff --git a/NifImport/MaxNifImport.rc b/NifImport/MaxNifImport.rc index 06f8df207660ee5a1dc89b7a577eabb935420ed5..639490ea76e49e9d2968c9cae8afa0afcb4b3166 100644 --- a/NifImport/MaxNifImport.rc +++ b/NifImport/MaxNifImport.rc @@ -26,14 +26,34 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // Dialog // -IDD_PANEL DIALOGEX 0, 0, 142, 59 +IDD_PANEL DIALOGEX 0, 0, 206, 158 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_TOOLWINDOW +CAPTION "Import Nif" FONT 8, "MS Sans Serif", 0, 0, 0x1 BEGIN - EDITTEXT IDC_EDITHEIGHT,68,15,62,14,ES_AUTOHSCROLL - LTEXT "&Height:",IDC_STATIC,16,18,49,8 - PUSHBUTTON "&Close",IDCLOSE,44,38,50,14 + GROUPBOX "Import:",IDC_STATIC,7,6,81,81 + CONTROL "&Skeleton",IDC_CHK_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,16,67,10 + CONTROL "Skin Modifier",IDC_CHK_SKIN,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,27,67,10 + CONTROL "&Vertex Colors",IDC_CHK_VCOLORS,"Button",BS_AUTO3STATE | WS_TABSTOP,14,38,67,10 + CONTROL "Co&llision",IDC_CHK_COLL,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,14,62,67,10 + CONTROL "&Animation",IDC_CHK_ANIMATION,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,50,67,10 + CONTROL "Furniture &Markers",IDC_CHK_FURN,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,14,73,67,10 + GROUPBOX "Behaviors:",IDC_STATIC,94,6,101,81 + CONTROL "Flip UV",IDC_CHK_FLIP_UV,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,16,88,10 + CONTROL "&Render Textures in View",IDC_CHK_SHOW_TEX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,27,88,10 + CONTROL "&Auto Smooth Mesh",IDC_CHK_AUTOSMOOTH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,38,88,11 + CONTROL "Remove Illegal Faces",IDC_CHK_ILLEGAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,50,88,11 + CONTROL "Remove Unused Bones",IDC_CHK_REM_BONES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,102,62,88,10 + CONTROL "&Use Biped",IDC_CHK_BIPED,"Button",BS_AUTOCHECKBOX | WS_DISABLED | WS_TABSTOP,102,73,87,10 + LTEXT "Skeleton:",IDC_STC_SKELETON,7,107,31,8 + EDITTEXT IDC_ED_SKELETON,7,119,171,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_BTN_BROWSE,180,119,19,13 + LTEXT "Game:",IDC_STATIC,7,93,31,8 + COMBOBOX IDC_CB_GAME,47,91,131,70,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "&Import",IDOK,5,137,34,14 + PUSHBUTTON "&Cancel",IDCANCEL,45,137,33,14 + LTEXT "http://niftools.sourceforge.net",IDC_LBL_LINK,93,137,95,14,SS_NOTIFY | SS_CENTERIMAGE END @@ -48,9 +68,9 @@ BEGIN IDD_PANEL, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 135 + RIGHTMARGIN, 199 TOPMARGIN, 7 - BOTTOMMARGIN, 52 + BOTTOMMARGIN, 151 END END #endif // APSTUDIO_INVOKED @@ -88,8 +108,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,1,6,8 - PRODUCTVERSION 0,1,6,0 + FILEVERSION 0,2,0,0 + PRODUCTVERSION 0,2,0,0 FILEFLAGSMASK 0x37L #ifdef _DEBUG FILEFLAGS 0x21L @@ -105,12 +125,12 @@ BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "3ds Max Nif Importer" - VALUE "FileVersion", "0, 1, 6, 8" + VALUE "FileVersion", "0, 2, 0, 0" VALUE "InternalName", "MaxNifImport.dli" VALUE "LegalCopyright", "Copyright (c) 2006, NIF File Format Library and Tools\r\nAll rights reserved." VALUE "OriginalFilename", "MaxNifImport.dli" VALUE "ProductName", "3ds Max Nif Importer" - VALUE "ProductVersion", "0, 1, 6, 0" + VALUE "ProductVersion", "0, 2, 0, 0" VALUE "SpecialBuild", "Alpha" END END diff --git a/NifImport/MaxNifImport_VC80.vcproj b/NifImport/MaxNifImport_VC80.vcproj index d05d46e9cfaefeadbf4298674f94c3230d2a2f02..245bcbb797a644a6ca549347aeed5ab49ebc701a 100644 --- a/NifImport/MaxNifImport_VC80.vcproj +++ b/NifImport/MaxNifImport_VC80.vcproj @@ -695,10 +695,6 @@ RelativePath=".\KFImporter.h" > </File> - <File - RelativePath=".\objectParams.h" - > - </File> <File RelativePath=".\resource.h" > @@ -788,6 +784,10 @@ RelativePath=".\MaxNifImport.h" > </File> + <File + RelativePath=".\NifDialog.cpp" + > + </File> <File RelativePath=".\NIFImport.cpp" > diff --git a/NifImport/NIFImport.cpp b/NifImport/NIFImport.cpp index b8f9dc9f34800d879348115b1076b5c9f19c17b2..c728fed2ccba49f28f21c5dc739b2101a96a0a2a 100644 --- a/NifImport/NIFImport.cpp +++ b/NifImport/NIFImport.cpp @@ -72,7 +72,7 @@ void NifImporter::Initialize() hasSkeleton = HasSkeleton(); isBiped = IsBiped(); - skeleton = (appSettings != NULL) ? appSettings->Skeleton : ""; + skeleton = GetSkeleton(appSettings); importSkeleton = (appSettings != NULL) ? appSettings->useSkeleton : false; importSkeleton &= hasSkeleton; @@ -89,6 +89,22 @@ void NifImporter::Initialize() } } +string NifImporter::GetSkeleton(AppSettings *appSettings) +{ + string skeleton = (appSettings != NULL) ? appSettings->Skeleton : ""; + // Guess that the skeleton is the same one in the current directory + if (importSkeleton && !defaultSkeletonName.empty()) { + TCHAR buffer[MAX_PATH]; + GetFullPathName(name.c_str(), _countof(buffer), buffer, NULL); + PathRemoveFileSpec(buffer); + PathAddBackslash(buffer); + PathAppend(buffer, defaultSkeletonName.c_str()); + if (-1 != _taccess(buffer, 0)) + skeleton = buffer; + } + return skeleton; +} + void NifImporter::LoadIniSettings() { TCHAR iniName[MAX_PATH]; @@ -127,6 +143,7 @@ void NifImporter::LoadIniSettings() enableSkinSupport = GetIniValue(NifImportSection, "EnableSkinSupport", true); enableCollision = GetIniValue(NifImportSection, "EnableCollision", true); vertexColorMode = GetIniValue<int>(NifImportSection, "VertexColorMode", 1); + useCiv4Shader = GetIniValue(NifImportSection, "UseCiv4Shader", true); // Biped importBones = GetIniValue(BipedImportSection, "ImportBones", true); @@ -154,7 +171,10 @@ void NifImporter::LoadIniSettings() // Collision bhkScaleFactor = GetIniValue<float>(CollisionSection, "bhkScaleFactor", 7.0f); - + ApplyAppSettings(); +} +void NifImporter::ApplyAppSettings() +{ goToSkeletonBindPosition = false; // Override specific settings if (appSettings) { @@ -170,14 +190,22 @@ void NifImporter::LoadIniSettings() void NifImporter::SaveIniSettings() { - //SetIniValue(NifImportSection, "UseBiped", useBiped); - //SetIniValue<string>(NifImportSection, "Skeleton", skeleton); - //SetIniValue<string>(NifImportSection, "SkeletonCheck", skeletonCheck); - - //SetIniValue<float>(BipedImportSection, "BipedHeight", bipedHeight); - //SetIniValue<float>(BipedImportSection, "BipedAngle", bipedAngle); - //SetIniValue<float>(BipedImportSection, "BipedAnkleAttach", bipedAnkleAttach); - //SetIniValue(BipedImportSection, "BipedTrianglePelvis", bipedTrianglePelvis); + SetIniValue(NifImportSection, "UseBiped", useBiped); + SetIniValue(NifImportSection, "EnableSkinSupport", enableSkinSupport); + SetIniValue(NifImportSection, "VertexColorMode", vertexColorMode); + SetIniValue(NifImportSection, "EnableCollision", enableCollision); + //SetIniValue(NifImportSection, "EnableFurniture", enableAnimations); + + SetIniValue(NifImportSection, "FlipUVTextures", flipUVTextures); + SetIniValue(NifImportSection, "ShowTextures", showTextures); + SetIniValue(NifImportSection, "EnableAutoSmooth", enableAutoSmooth); + SetIniValue(NifImportSection, "RemoveIllegalFaces", removeIllegalFaces); + SetIniValue(NifImportSection, "RemoveDegenerateFaces", removeDegenerateFaces); + + SetIniValue(BipedImportSection, "ImportBones", importBones); + SetIniValue(BipedImportSection, "RemoveUnusedImportedBones", removeUnusedImportedBones); + + SetIniValue(AnimImportSection, "EnableAnimations", enableAnimations); } INode *NifImporter::GetNode(Niflib::NiNodeRef node) @@ -190,39 +218,48 @@ INode *NifImporter::GetNode(Niflib::NiNodeRef node) bool NifImporter::DoImport() { bool ok = true; + if (!suppressPrompts) + { + if (!ShowDialog()) + return true; + + ApplyAppSettings(); + SaveIniSettings(); + } + vector<string> importedBones; if (!isBiped && importSkeleton && importBones) { - if (browseForSkeleton) - { - TCHAR filter[64], *pfilter=filter; - pfilter = _tcscpy(filter, shortDescription.c_str()); - pfilter = _tcscat(pfilter, " (*.NIF)"); - pfilter += strlen(pfilter); - *pfilter++ = '\0'; - _tcscpy(pfilter, "*.NIF"); - pfilter += strlen(pfilter); - *pfilter++ = '\0'; - *pfilter++ = '\0'; - - TCHAR filename[MAX_PATH]; - GetFullPathName(skeleton.c_str(), _countof(filename), filename, NULL); - - OPENFILENAME ofn; - memset(&ofn, 0, sizeof(ofn)); - ofn.lStructSize = sizeof(ofn); - ofn.hwndOwner = gi->GetMAXHWnd(); - ofn.lpstrFilter = filter; - ofn.lpstrFile = filename; - ofn.nMaxFile = _countof(filename); - ofn.lpstrTitle = TEXT("Browse for Skeleton NIF..."); - ofn.lpstrDefExt = TEXT("NIF"); - ofn.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR|OFN_PATHMUSTEXIST; - importSkeleton = GetOpenFileName(&ofn) ? true : false; - if (importSkeleton) { - skeleton = filename; - } - } + //if (browseForSkeleton) + //{ + // TCHAR filter[64], *pfilter=filter; + // pfilter = _tcscpy(filter, shortDescription.c_str()); + // pfilter = _tcscat(pfilter, " (*.NIF)"); + // pfilter += strlen(pfilter); + // *pfilter++ = '\0'; + // _tcscpy(pfilter, "*.NIF"); + // pfilter += strlen(pfilter); + // *pfilter++ = '\0'; + // *pfilter++ = '\0'; + + // TCHAR filename[MAX_PATH]; + // GetFullPathName(skeleton.c_str(), _countof(filename), filename, NULL); + + // OPENFILENAME ofn; + // memset(&ofn, 0, sizeof(ofn)); + // ofn.lStructSize = sizeof(ofn); + // ofn.hwndOwner = gi->GetMAXHWnd(); + // ofn.lpstrFilter = filter; + // ofn.lpstrFile = filename; + // ofn.nMaxFile = _countof(filename); + // ofn.lpstrTitle = TEXT("Browse for Skeleton NIF..."); + // ofn.lpstrDefExt = TEXT("NIF"); + // ofn.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR|OFN_PATHMUSTEXIST; + // importSkeleton = GetOpenFileName(&ofn) ? true : false; + // if (importSkeleton) { + // skeleton = filename; + // } + //} if (importSkeleton && !skeleton.empty()) { NifImporter skelImport(skeleton.c_str(), i, gi, suppressPrompts); if (skelImport.isValid()) @@ -233,7 +270,7 @@ bool NifImporter::DoImport() // Disable undesirable skeleton items skelImport.enableCollision = false; skelImport.enableAnimations = false; - + skelImport.suppressPrompts = true; skelImport.DoImport(); if (!skelImport.useBiped && removeUnusedImportedBones) importedBones = GetNamesOfNodes(skelImport.nodes); diff --git a/NifImport/NIFImporter.h b/NifImport/NIFImporter.h index c15cbf1d72103962de741a3174e6e1ba589f41d5..4f61b1d82f2bc0349ad6b62726e813cd483b4488 100644 --- a/NifImport/NIFImporter.h +++ b/NifImport/NIFImporter.h @@ -15,8 +15,10 @@ HISTORY: #define __NIFIMPORTER_H__ #include "BaseImporter.h" +#include "IniSection.h" + // NIF Importer -class NifImporter : public BaseImporter +class NifImporter : public BaseImporter//, public IniFileSection { public: // Ini settings @@ -30,6 +32,7 @@ public: bool goToSkeletonBindPosition; bool enableCollision; int vertexColorMode; + bool useCiv4Shader; // Biped/Bones related settings bool importBones; @@ -77,6 +80,8 @@ public: void LoadIniSettings(); void SaveIniSettings(); + void ApplyAppSettings(); + bool HasSkeleton(); bool IsBiped(); void ImportBones(vector<Niflib::NiNodeRef>& bones); @@ -92,6 +97,7 @@ public: bool ImportMesh(Niflib::NiTriShapeRef triShape); bool ImportMesh(Niflib::NiTriStripsRef triStrips); bool ImportMaterialAndTextures(ImpNode *node, Niflib::NiAVObjectRef avObject); + bool ImportCiv4Shader(ImpNode *node, Niflib::NiAVObjectRef avObject, StdMat2 *m); bool ImportTransform(ImpNode *node, Niflib::NiAVObjectRef avObject); bool ImportMesh(ImpNode *node, TriObject *o, Niflib::NiTriBasedGeomRef triGeom, Niflib::NiTriBasedGeomDataRef triGeomData, vector<Niflib::Triangle>& tris); bool ImportVertexColor(ImpNode *node, TriObject *o, Niflib::NiTriBasedGeomRef triGeom, Niflib::NiTriBasedGeomDataRef triGeomData, vector<Niflib::Triangle>& tris); @@ -105,7 +111,9 @@ public: bool ImportCollision(Niflib::NiNodeRef node); INode *GetNode(Niflib::NiNodeRef node); + string GetSkeleton(AppSettings *appSettings); + bool ShowDialog(); virtual bool DoImport(); // Animation Helpers diff --git a/NifImport/NifDialog.cpp b/NifImport/NifDialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8294625a2e5578e8ab2ce43dd57d907bd55e5d19 --- /dev/null +++ b/NifImport/NifDialog.cpp @@ -0,0 +1,187 @@ +/********************************************************************** +*< +FILE: ImporterCore.cpp + +DESCRIPTION: Core Import helper routines + +CREATED BY: tazpn (Theo) + +HISTORY: + +*> Copyright (c) 2006, All Rights Reserved. +**********************************************************************/ +#include "stdafx.h" +#include "MaxNifImport.h" +#include "resource.h" +#include "shellapi.h" + +using namespace Niflib; + +BOOL CALLBACK MaxNifImportOptionsDlgProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { + static NifImporter *imp = NULL; + static DWORD dlgRes = IDCANCEL; + + switch(message) { + case WM_INITDIALOG: + { + dlgRes = IDCANCEL; + + // Append file version to dialog + TSTR version = GetFileVersion(NULL); + if (!version.isNull()) { + char buffer[256]; + GetWindowText(hWnd, buffer, _countof(buffer)); + _tcscat(buffer, TEXT(" ")); + _tcscat(buffer, version); + SetWindowText(hWnd, buffer); + } + + imp = (NifImporter *)lParam; + CenterWindow(hWnd,GetParent(hWnd)); + + CheckDlgButton(hWnd, IDC_CHK_BONES, imp->importBones); + CheckDlgButton(hWnd, IDC_CHK_SKIN, imp->enableSkinSupport); + CheckDlgButton(hWnd, IDC_CHK_VCOLORS, imp->vertexColorMode); + CheckDlgButton(hWnd, IDC_CHK_COLL, imp->enableCollision); + CheckDlgButton(hWnd, IDC_CHK_ANIMATION, imp->enableAnimations); + //CheckDlgButton(hWnd, IDC_CHK_FURN, imp->); + + CheckDlgButton(hWnd, IDC_CHK_FLIP_UV, imp->flipUVTextures); + CheckDlgButton(hWnd, IDC_CHK_SHOW_TEX, imp->showTextures); + CheckDlgButton(hWnd, IDC_CHK_AUTOSMOOTH, imp->enableAutoSmooth); + CheckDlgButton(hWnd, IDC_CHK_ILLEGAL, imp->removeIllegalFaces); + CheckDlgButton(hWnd, IDC_CHK_REM_BONES, imp->removeUnusedImportedBones); + CheckDlgButton(hWnd, IDC_CHK_BIPED, imp->useBiped); + + string selection = (imp->appSettings) ? imp->appSettings->Name : "User"; + for (AppSettingsMap::iterator itr = TheAppSettings.begin(), end = TheAppSettings.end(); itr != end; ++itr) + SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_ADDSTRING, 0, LPARAM(itr->Name.c_str())); + SendDlgItemMessage(hWnd, IDC_CB_GAME, CB_SELECTSTRING, WPARAM(-1), LPARAM(selection.c_str())); + + SHAutoComplete(GetDlgItem(hWnd, IDC_ED_SKELETON), SHACF_FILESYSTEM); + if (imp->HasSkeleton() && imp->appSettings && imp->importSkeleton) { + SetDlgItemText(hWnd, IDC_ED_SKELETON, imp->skeleton.c_str()); + } else { + EnableWindow(GetDlgItem(hWnd, IDC_STC_SKELETON), FALSE); + EnableWindow(GetDlgItem(hWnd, IDC_ED_SKELETON), FALSE); + EnableWindow(GetDlgItem(hWnd, IDC_BTN_BROWSE), FALSE); + EnableWindow(GetDlgItem(hWnd, IDC_CHK_BIPED), FALSE); + EnableWindow(GetDlgItem(hWnd, IDC_CHK_REM_BONES), FALSE); + } + } + return TRUE; + + case WM_CLOSE: + { + EndDialog(hWnd, dlgRes); + } + return TRUE; + + case WM_COMMAND : + { + if (HIWORD(wParam) == BN_CLICKED) + { + char tmp[MAX_PATH]; + switch (LOWORD(wParam)) + { + case IDOK: + + imp->importBones = IsDlgButtonChecked(hWnd, IDC_CHK_BONES) ? true : false; + imp->enableSkinSupport = IsDlgButtonChecked(hWnd, IDC_CHK_SKIN) ? true : false; + imp->vertexColorMode = (int)IsDlgButtonChecked(hWnd, IDC_CHK_VCOLORS); + imp->enableCollision = IsDlgButtonChecked(hWnd, IDC_CHK_COLL) ? true : false; + imp->enableAnimations = IsDlgButtonChecked(hWnd, IDC_CHK_ANIMATION) ? true : false; + //IsDlgButtonChecked(hWnd, IDC_CHK_FURN, imp->); + + imp->flipUVTextures = IsDlgButtonChecked(hWnd, IDC_CHK_FLIP_UV) ? true : false; + imp->showTextures = IsDlgButtonChecked(hWnd, IDC_CHK_SHOW_TEX) ? true : false; + imp->enableAutoSmooth = IsDlgButtonChecked(hWnd, IDC_CHK_AUTOSMOOTH) ? true : false; + imp->removeDegenerateFaces = + imp->removeIllegalFaces = IsDlgButtonChecked(hWnd, IDC_CHK_ILLEGAL) ? true : false; + imp->removeUnusedImportedBones = IsDlgButtonChecked(hWnd, IDC_CHK_REM_BONES) ? true : false; + imp->useBiped = IsDlgButtonChecked(hWnd, IDC_CHK_BIPED) ? true : false; + + GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH); + if (AppSettings *appSettings = FindAppSetting(tmp)) { + imp->appSettings = appSettings; + } + + GetDlgItemText(hWnd, IDC_ED_SKELETON, tmp, MAX_PATH); + imp->skeleton = tmp; + + EndDialog(hWnd, dlgRes=IDOK); + return TRUE; + + case IDCANCEL: + EndDialog(hWnd, dlgRes=IDCANCEL); + return TRUE; + + case IDC_BTN_BROWSE: + { + TCHAR filter[64], *pfilter=filter; + pfilter = _tcscpy(filter, shortDescription.c_str()); + pfilter = _tcscat(pfilter, " (*.NIF)"); + pfilter += strlen(pfilter); + *pfilter++ = '\0'; + _tcscpy(pfilter, "*.NIF"); + pfilter += strlen(pfilter); + *pfilter++ = '\0'; + *pfilter++ = '\0'; + + GetDlgItemText(hWnd, IDC_ED_SKELETON, tmp, MAX_PATH); + GetLongPathName(tmp, tmp, _countof(tmp)); + + OPENFILENAME ofn; + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = imp->gi->GetMAXHWnd(); + ofn.lpstrFilter = filter; + ofn.lpstrFile = tmp; + ofn.nMaxFile = _countof(tmp); + ofn.lpstrTitle = TEXT("Browse for Skeleton NIF..."); + ofn.lpstrDefExt = TEXT("NIF"); + ofn.Flags = OFN_HIDEREADONLY|OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR|OFN_PATHMUSTEXIST; + if (GetOpenFileName(&ofn)) { + SetDlgItemText(hWnd, IDC_ED_SKELETON, tmp); + } + } + break; + } + } + else if (HIWORD(wParam) == STN_CLICKED) + { + if (LOWORD(wParam) == IDC_LBL_LINK) + { + ShellExecute(hWnd, "open", "http://niftools.sourceforge.net", + NULL, NULL, SW_SHOWDEFAULT); + } + } + else if (HIWORD(wParam) == CBN_SELCHANGE) + { + if (LOWORD(wParam) == IDC_CB_GAME) + { + char tmp[MAX_PATH]; + GetDlgItemText(hWnd, IDC_CB_GAME, tmp, MAX_PATH); + if (AppSettings *appSettings = FindAppSetting(tmp)) + { + string skeleton = imp->GetSkeleton(appSettings); + BOOL enable = imp->HasSkeleton() ? TRUE : FALSE; + if (enable) { + SetDlgItemText(hWnd, IDC_ED_SKELETON, skeleton.c_str()); + } + EnableWindow(GetDlgItem(hWnd, IDC_STC_SKELETON), enable); + EnableWindow(GetDlgItem(hWnd, IDC_ED_SKELETON), enable); + EnableWindow(GetDlgItem(hWnd, IDC_BTN_BROWSE), enable); + } + } + } + } + break; + } + return FALSE; +} + +bool NifImporter::ShowDialog() +{ + return (IDOK == DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_PANEL), GetActiveWindow(), MaxNifImportOptionsDlgProc, (LPARAM)this)); +} \ No newline at end of file diff --git a/NifImport/objectParams.h b/NifImport/objectParams.h deleted file mode 100644 index 23a45f424dc7db9d93716af5ca3aeacb2c484102..0000000000000000000000000000000000000000 --- a/NifImport/objectParams.h +++ /dev/null @@ -1,339 +0,0 @@ -/*===========================================================================*\ - | - | FILE: objectParams.h - | Skeleton project and code for a Utility - | 3D Studio MAX R3.0 - | - | AUTH: Cleve Ard - | Render Group - | Copyright(c) Discreet 2000 - | - | HIST: Started 9-8-00 - | -\*===========================================================================*/ - -#ifndef _OBJECTPARAMS_H_ -#define _OBJECTPARAMS_H_ - -#include "maxscrpt/maxscrpt.h" -#include "maxscrpt/Numbers.h" -#include "maxscrpt/Name.h" -#include "maxscrpt/ColorVal.h" -#include "maxscrpt/MAXObj.h" -#include "assert1.h" - -template <class T> -class ConvertMAXScriptToC; -inline Value* make_maxscript_value(bool v); -inline Value* make_maxscript_value(int v); -inline Value* make_maxscript_value(float v); -inline Value* make_maxscript_value(COLORREF rgb); -inline Value* make_maxscript_value(const Color& rgb); -inline Value* make_maxscript_value(LPCTSTR str); -inline Value* make_maxscript_value(ReferenceTarget* rtarg); - -#if VERSION_3DSMAX <= ((MAX_RELEASE_R7<<16)+(15<<8)+0) -inline void clear_error_source_data() {} -#endif - -// Not all of the paramters for materials and shaders -// are published in the interfaces. ObjectParams class -// is used to access the properties of objects the same -// way the scriptor does, so you can get to properties. - -// Set the array parameter named name to the value at time t. -template<class T> -bool setMAXScriptValue(ReferenceTarget* obj, LPTSTR name, TimeValue t, T value, int tabIndex) -{ - bool rval = false; // Return false if fails - assert(obj != NULL); - init_thread_locals(); - push_alloc_frame(); - two_value_locals(prop, result); // Keep two local variables - save_current_frames(); - trace_back_active = FALSE; - - try { - // Get the name of the parameter and then retrieve - // the array holding the value we want to set. - vl.prop = Name::intern(name); - vl.result = MAXWrapper::get_property(obj, vl.prop, NULL); - - // Make sure it is the right type. - if (vl.result != NULL && vl.result->tag == class_tag(MAXPB2ArrayParam)) { - // OK. Now we make sure the tabIndex is within the array bounds. - MAXPB2ArrayParam* array = static_cast<MAXPB2ArrayParam*>(vl.result); - if (array->pblock != NULL && array->pdef != NULL - && tabIndex >= 0 && tabIndex < array->pblock->Count(array->pdef->ID)) { - // Set the value in the array. - array->pblock->SetValue(array->pdef->ID, 0, value, tabIndex); - rval = true; // Succeeded - } - } - } catch ( ... ) { - // Failed. - clear_error_source_data(); - restore_current_frames(); - MAXScript_signals = 0; - if (progress_bar_up) - MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE; - } - pop_value_locals(); - pop_alloc_frame(); - return rval; -} - -// Set the parameter. Cannot be an array entry -template<class T> -bool setMAXScriptValue(ReferenceTarget* obj, LPTSTR name, TimeValue t, T& value) -{ - bool rval = false; // return false if fails - assert(obj != NULL); - init_thread_locals(); - push_alloc_frame(); - two_value_locals(prop, val); // Keep two local variables - save_current_frames(); - trace_back_active = FALSE; - - try { - // Get the name and value to set - vl.prop = Name::intern(name); - vl.val = make_maxscript_value(value); - - // Set the value. - Value* val = MAXWrapper::set_property(obj, vl.prop, vl.val); - if (val != NULL) - rval = true; // Succeeded - } catch ( ... ) { - // Failed. - clear_error_source_data(); - restore_current_frames(); - MAXScript_signals = 0; - if (progress_bar_up) - MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE; - } - pop_value_locals(); - pop_alloc_frame(); - return rval; -} - -// Get the parameter from an array -template<class T> -bool getMAXScriptValue(ReferenceTarget* obj, LPTSTR name, TimeValue t, T& value, int tabIndex) -{ - bool rval = false; // Return false if fails - assert(obj != NULL); - init_thread_locals(); - push_alloc_frame(); - two_value_locals(prop, result); // Keep two local variables - save_current_frames(); - trace_back_active = FALSE; - - try { - // Get the name and the array holding the roperty. - vl.prop = Name::intern(name); - vl.result = MAXWrapper::get_property(obj, vl.prop, NULL); - - // Make sure it is they right type. - if (vl.result != NULL && is_tab_param(vl.result)) { - // OK. Now we make sure the tabIndex is within the array bounds. - MAXPB2ArrayParam* array = static_cast<MAXPB2ArrayParam*>(vl.result); - if (array->pblock != NULL && array->pdef != NULL - && tabIndex >= 0 && tabIndex < array->pblock->Count(array->pdef->ID)) { - // Good. Get the value - array->pblock->GetValue(array->pdef->ID, 0, value, Interval(0,0), tabIndex); - rval = true; // Succeeded - } - } - } catch ( ... ) { - // Failed. - clear_error_source_data(); - restore_current_frames(); - MAXScript_signals = 0; - if (progress_bar_up) - MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE; - } - pop_value_locals(); - pop_alloc_frame(); - return rval; -} - -// Get the parameter -template<class T> -bool getMAXScriptValue(ReferenceTarget* obj, LPTSTR name, TimeValue t, T& value) -{ - bool rval = false; // Return false if fails - assert(obj != NULL); - init_thread_locals(); - push_alloc_frame(); - two_value_locals(prop, result); // Keep two local varaibles - save_current_frames(); - trace_back_active = FALSE; - - try { - // Get the name and the parameter value - vl.prop = Name::intern(name); - vl.result = MAXWrapper::get_property(obj, vl.prop, NULL); - - // Make sure it is valid. - if (vl.result != NULL && vl.result != &undefined && vl.result != &unsupplied) { - // Convert to C++ type. - value = ConvertMAXScriptToC<T>::cvt(vl.result); - rval = true; // Succeeded - } - } catch ( ... ) { - clear_error_source_data(); - restore_current_frames(); - MAXScript_signals = 0; - if (progress_bar_up) - MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE; - } - pop_value_locals(); - pop_alloc_frame(); - return rval; -} - -// Get the parameter controller -inline Control* getMAXScriptController(ReferenceTarget* obj, LPTSTR name, ParamDimension*& dim) -{ - Control* rval = NULL; - assert(obj != NULL); - init_thread_locals(); - push_alloc_frame(); - one_value_local(prop); // Keep one local varaibles - save_current_frames(); - trace_back_active = FALSE; - - try { - // Get the name and the parameter value - vl.prop = Name::intern(name); - rval = MAXWrapper::get_max_prop_controller(obj, vl.prop, &dim); - } catch ( ... ) { - clear_error_source_data(); - restore_current_frames(); - MAXScript_signals = 0; - if (progress_bar_up) - MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE; - } - pop_value_locals(); - pop_alloc_frame(); - return rval; -} - -// Set the parameter controller -inline bool setMAXScriptController(ReferenceTarget* obj, LPTSTR name, Control* control, ParamDimension* dim) -{ - bool rval = false; - assert(obj != NULL); - init_thread_locals(); - push_alloc_frame(); - two_value_locals(prop, maxControl); // Keep two local varaibles - save_current_frames(); - trace_back_active = FALSE; - - try { - // Get the name and the parameter value - vl.prop = Name::intern(name); - vl.maxControl = MAXControl::intern(control, dim); - rval = MAXWrapper::set_max_prop_controller(obj, vl.prop, - static_cast<MAXControl*>(vl.maxControl)) != 0; - } catch ( ... ) { - clear_error_source_data(); - restore_current_frames(); - MAXScript_signals = 0; - if (progress_bar_up) - MAXScript_interface->ProgressEnd(), progress_bar_up = FALSE; - } - pop_value_locals(); - pop_alloc_frame(); - return rval; -} - -// These helpers are used to convert C++ values to -// their MAXScript value. Maxscript uses different -// methods to handle the conversion, and these helpers -// allow the conversion to be templated. You may need -// to add more converter, if you need to access other -// parameter types. -inline Value* make_maxscript_value(bool v) -{ - return_protected(v ? &true_value : &false_value); -} - -inline Value* make_maxscript_value(int v) -{ - return_protected(Integer::intern(v)); -} - -inline Value* make_maxscript_value(float v) -{ - return_protected(Float::intern(v)); -} - -inline Value* make_maxscript_value(COLORREF rgb) -{ - return new ColorValue(rgb); -} - -inline Value* make_maxscript_value(const Color& rgb) -{ - return new ColorValue(rgb); -} - -inline Value* make_maxscript_value(LPCTSTR str) -{ - return Name::intern(const_cast<LPTSTR>(str)); -} - -inline Value* make_maxscript_value(ReferenceTarget* rtarg) -{ - return MAXClass::make_wrapper_for(rtarg); -} - -// These helpers convert MAXScript values to C++ values. -// MAXScript uses different methods for this conversion, -// and these helpers template the conversion. You will -// need to add more converters if you need more types. -template <class T> -class ConvertMAXScriptToC { -public: - static T cvt(Value* val); -}; - -inline bool ConvertMAXScriptToC<bool>::cvt(Value* val) -{ - return val->to_bool() != 0; -} - -inline int ConvertMAXScriptToC<int>::cvt(Value* val) -{ - return val->to_int(); -} - -inline float ConvertMAXScriptToC<float>::cvt(Value* val) -{ - return val->to_float(); -} - -inline Color ConvertMAXScriptToC<Color>::cvt(Value* val) -{ - return val->to_point3(); -} - -inline LPTSTR ConvertMAXScriptToC<LPTSTR>::cvt(Value* val) -{ - return val->to_string(); -} - -inline Texmap* ConvertMAXScriptToC<Texmap*>::cvt(Value* val) -{ - return val->to_texmap(); -} - -inline ReferenceTarget* ConvertMAXScriptToC<ReferenceTarget*>::cvt(Value* val) -{ - return val->to_reftarg(); -} - - -#endif diff --git a/NifImport/resource.h b/NifImport/resource.h index 01805df3283da03790417e21430b878414cedeee..6c53f318b4a80ce8b73781b4ea2812d7eeee552d 100644 --- a/NifImport/resource.h +++ b/NifImport/resource.h @@ -12,9 +12,25 @@ #define IDC_DOSTUFF 1000 #define IDC_EDITHEIGHT 1001 #define IDC_BUTTON1 1002 -#define IDC_COLOR 1456 -#define IDC_EDIT 1490 -#define IDC_SPIN 1496 +#define IDC_BTN_BROWSE 1002 +#define IDC_CHK_BONES 1003 +#define IDC_CHK_FLIP_UV 1004 +#define IDC_CHK_FURN 1005 +#define IDC_ED_SKELETON 1006 +#define IDC_CHK_BIPED 1007 +#define IDC_CHK_COLL 1010 +#define IDC_LBL_LINK 1011 +#define IDC_CHK_VCOLORS 1012 +#define IDC_CHK_SHOW_TEX 1013 +#define IDC_CB_GAME 1014 +#define IDC_CB_USER_VERSION 1016 +#define IDC_CHK_SKIN 1017 +#define IDC_CHK_ANIMATION 1018 +#define IDC_CHK_AUTOSMOOTH 1019 +#define IDC_CHK_ILLEGAL 1020 +#define IDC_STC_SKELETON 1021 +#define IDC_CHK_REM_BONES 1022 + // Next default values for new objects // diff --git a/NifPlugins_VC80.sln b/NifPlugins_VC80.sln index b3f90853ccc8912e9620aae0909175f068ad49ea..b1ec78f894fd30a15c84de112a25e85b2b426018 100644 --- a/NifPlugins_VC80.sln +++ b/NifPlugins_VC80.sln @@ -30,6 +30,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject MaxNifPlugins_Readme.txt = MaxNifPlugins_Readme.txt MaxNifTools.ini = MaxNifTools.ini + ..\docsys\nif.xml = ..\docsys\nif.xml NifPlugins_Development_Readme.txt = NifPlugins_Development_Readme.txt EndProjectSection EndProject