Split off 3ds Max exporter to a separate repository

It now lives at https://github.com/panda3d/max-egg-plugin

See #1584
This commit is contained in:
rdb 2024-08-13 10:59:12 +02:00
parent 712300c9f1
commit fff9ea594c
23 changed files with 3 additions and 5734 deletions

View File

@ -86,7 +86,6 @@ LangString DESC_SecPython ${LANG_ENGLISH} "Contains a ${REGVIEW}-bit copy of Pyt
LangString DESC_SecEnsurePip ${LANG_ENGLISH} "Installs the pip package manager into the included Python installation."
LangString DESC_SecHeadersLibs ${LANG_ENGLISH} "Headers and libraries needed for C++ development with Panda3D."
LangString DESC_SecSamples ${LANG_ENGLISH} "The sample programs demonstrate how to make Python applications with Panda3D."
LangString DESC_SecMaxPlugins ${LANG_ENGLISH} "Plug-ins for Autodesk 3ds Max (${REGVIEW}-bit) that can be used to export models to Panda3D."
LangString DESC_SecMayaPlugins ${LANG_ENGLISH} "Plug-ins and scripts for Autodesk Maya (${REGVIEW}-bit) that can be used to export models to Panda3D."
var READABLE
@ -114,7 +113,6 @@ var READABLE
!insertmacro !defineifexist HAVE_BULLET "${BUILT}\bin\libpandabullet.dll"
!insertmacro !defineifexist HAVE_ODE "${BUILT}\bin\libpandaode.dll"
!insertmacro !defineifexist HAVE_SAMPLES "${SOURCE}\samples"
!insertmacro !defineifexist HAVE_MAX_PLUGINS "${BUILT}\plugins\*.dlo"
!insertmacro !defineifexist HAVE_MAYA_PLUGINS "${BUILT}\plugins\*.mll"
!macro RemovePythonPath PYVER
@ -697,21 +695,6 @@ Section "Sample programs" SecSamples
SectionEnd
!endif
!ifdef HAVE_MAX_PLUGINS
Section "3ds Max plug-ins" SecMaxPlugins
SectionIn 1 2
SetDetailsPrint both
DetailPrint "Installing Autodesk 3ds Max plug-ins..."
SetDetailsPrint listonly
SetOutPath $INSTDIR\plugins
File /nonfatal /r "${BUILT}\plugins\*.dle"
File /nonfatal /r "${BUILT}\plugins\*.dlo"
File /nonfatal /r "${BUILT}\plugins\*.ms"
SectionEnd
!endif
!ifdef HAVE_MAYA_PLUGINS
Section "Maya plug-ins" SecMayaPlugins
SectionIn 1 2
@ -960,9 +943,6 @@ SectionEnd
!ifdef HAVE_SAMPLES
!insertmacro MUI_DESCRIPTION_TEXT ${SecSamples} $(DESC_SecSamples)
!endif
!ifdef HAVE_MAX_PLUGINS
!insertmacro MUI_DESCRIPTION_TEXT ${SecMaxPlugins} $(DESC_SecMaxPlugins)
!endif
!ifdef HAVE_MAYA_PLUGINS
!insertmacro MUI_DESCRIPTION_TEXT ${SecMayaPlugins} $(DESC_SecMayaPlugins)
!endif

View File

@ -86,7 +86,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support
"ODE", "BULLET", "PANDAPHYSICS", # Physics
"SPEEDTREE", # SpeedTree
"ZLIB", "PNG", "JPEG", "TIFF", "OPENEXR", "SQUISH", # 2D Formats support
] + MAYAVERSIONS + MAXVERSIONS + [ "FCOLLADA", "ASSIMP", "EGG", # 3D Formats support
] + MAYAVERSIONS + [ "FCOLLADA", "ASSIMP", "EGG", # 3D Formats support
"FREETYPE", "HARFBUZZ", # Text rendering
"VRPN", "OPENSSL", # Transport
"FFTW", # Algorithm helpers
@ -176,6 +176,8 @@ def parseopts(args):
removedopts = [
"use-touchinput", "no-touchinput", "no-awesomium", "no-directscripts",
"no-carbon", "no-physx", "no-rocket", "host", "osxtarget=",
"no-max6", "no-max7", "no-max8", "no-max9", "no-max2009",
"no-max2010", "no-max2011", "no-max2012", "no-max2013", "no-max2014",
]
# All recognized options.
@ -521,7 +523,6 @@ MakeBuildTree()
SdkLocateDirectX(STRDXSDKVERSION)
SdkLocateMaya()
SdkLocateMax()
SdkLocateMacOSX(OSX_ARCHS)
SdkLocatePython(False)
SdkLocateWindows(WINDOWS_SDK)
@ -530,7 +531,6 @@ SdkLocateAndroid()
SdkAutoDisableDirectX()
SdkAutoDisableMaya()
SdkAutoDisableMax()
SdkAutoDisableSpeedTree()
if not PkgSkip("PYTHON") and SDK["PYTHONVERSION"] == "python2.7":
@ -585,15 +585,6 @@ if (COMPILER == "MSVC"):
IncDirectory(pkg, SDK[pkg] + "/include")
DefSymbol(pkg, "MAYAVERSION", pkg)
DefSymbol(pkg, "MLIBRARY_DONTUSE_MFC_MANIFEST", "")
elif (pkg[:3]=="MAX"):
IncDirectory(pkg, SDK[pkg] + "/include")
IncDirectory(pkg, SDK[pkg] + "/include/CS")
IncDirectory(pkg, SDK[pkg+"CS"] + "/include")
IncDirectory(pkg, SDK[pkg+"CS"] + "/include/CS")
DefSymbol(pkg, "MAX", pkg)
if (int(pkg[3:]) >= 2013):
DefSymbol(pkg, "UNICODE", "")
DefSymbol(pkg, "_UNICODE", "")
elif (pkg[:2]=="DX"):
IncDirectory(pkg, SDK[pkg] + "/include")
elif GetThirdpartyDir() is not None:
@ -776,15 +767,6 @@ if (COMPILER == "MSVC"):
LibName(pkg, '"' + SDK[pkg] + '/lib/OpenMaya.lib"')
LibName(pkg, '"' + SDK[pkg] + '/lib/OpenMayaAnim.lib"')
LibName(pkg, '"' + SDK[pkg] + '/lib/OpenMayaUI.lib"')
for pkg in MAXVERSIONS:
if not PkgSkip(pkg):
LibName(pkg, SDK[pkg] + '/lib/core.lib')
LibName(pkg, SDK[pkg] + '/lib/edmodel.lib')
LibName(pkg, SDK[pkg] + '/lib/gfx.lib')
LibName(pkg, SDK[pkg] + '/lib/geom.lib')
LibName(pkg, SDK[pkg] + '/lib/mesh.lib')
LibName(pkg, SDK[pkg] + '/lib/maxutil.lib')
LibName(pkg, SDK[pkg] + '/lib/paramblk2.lib')
if not PkgSkip("SPEEDTREE"):
if GetTargetArch() == 'x64':
@ -3293,8 +3275,6 @@ if not PkgSkip("PANDATOOL"):
if not PkgSkip("PYTHON") and os.path.isdir(GetThirdpartyBase() + "/Pmw"):
CopyTree(GetOutputDir() + "/Pmw", GetThirdpartyBase() + "/Pmw", exclude=["Pmw_1_3", "Pmw_1_3_3"])
ConditionalWriteFile(GetOutputDir()+'/include/ctl3d.h', '/* dummy file to make MAX happy */')
# Since Eigen is included by all sorts of core headers, as a convenience
# to C++ users on Win and Mac, we include it in the Panda include directory.
if not PkgSkip("EIGEN") and GetTarget() in ("windows", "darwin") and GetThirdpartyDir():
@ -3459,8 +3439,6 @@ if not PkgSkip("PANDATOOL"):
CopyAllHeaders('pandatool/src/lwoprogs')
CopyAllHeaders('pandatool/src/maya')
CopyAllHeaders('pandatool/src/mayaegg')
CopyAllHeaders('pandatool/src/maxegg')
CopyAllHeaders('pandatool/src/maxprogs')
CopyAllHeaders('pandatool/src/objegg')
CopyAllHeaders('pandatool/src/objprogs')
CopyAllHeaders('pandatool/src/vrml')
@ -5790,47 +5768,6 @@ for VER in MAYAVERSIONS:
TargetAdd('libmayaegg'+VNUM+'.lib', input='mayaegg'+VNUM+'_loader.obj')
TargetAdd('libmayaegg'+VNUM+'.lib', input='mayaegg'+VNUM+'_composite1.obj')
#
# DIRECTORY: pandatool/src/maxegg/
#
for VER in MAXVERSIONS:
VNUM = VER[3:]
if PkgSkip(VER) or PkgSkip("PANDATOOL") or PkgSkip("EGG"):
continue
OPTS=['DIR:pandatool/src/maxegg', VER, "WINCOMCTL", "WINCOMDLG", "WINUSER", "MSFORSCOPE", "RTTI"]
TargetAdd('maxEgg'+VNUM+'.res', opts=OPTS, input='maxEgg.rc')
TargetAdd('maxegg'+VNUM+'_loader.obj', opts=OPTS, input='maxEggLoader.cxx')
TargetAdd('maxegg'+VNUM+'_composite1.obj', opts=OPTS, input='p3maxegg_composite1.cxx')
TargetAdd('maxegg'+VNUM+'.dlo', input='maxegg'+VNUM+'_composite1.obj')
TargetAdd('maxegg'+VNUM+'.dlo', input='maxEgg'+VNUM+'.res')
TargetAdd('maxegg'+VNUM+'.dlo', input='maxEgg.def', ipath=OPTS)
TargetAdd('maxegg'+VNUM+'.dlo', input=COMMON_EGG2X_LIBS)
TargetAdd('maxegg'+VNUM+'.dlo', opts=OPTS)
#
# DIRECTORY: pandatool/src/maxprogs/
#
for VER in MAXVERSIONS:
VNUM = VER[3:]
if PkgSkip(VER) or PkgSkip("PANDATOOL") or PkgSkip("EGG"):
continue
OPTS=['DIR:pandatool/src/maxprogs', VER, "WINCOMCTL", "WINCOMDLG", "WINUSER", "MSFORSCOPE", "RTTI"]
TargetAdd('maxImportRes.res', opts=OPTS, input='maxImportRes.rc')
TargetAdd('maxprogs'+VNUM+'_maxeggimport.obj', opts=OPTS, input='maxEggImport.cxx')
TargetAdd('maxeggimport'+VNUM+'.dle', input='maxegg'+VNUM+'_loader.obj')
TargetAdd('maxeggimport'+VNUM+'.dle', input='maxprogs'+VNUM+'_maxeggimport.obj')
TargetAdd('maxeggimport'+VNUM+'.dle', input='libpandaegg.dll')
TargetAdd('maxeggimport'+VNUM+'.dle', input='libpanda.dll')
TargetAdd('maxeggimport'+VNUM+'.dle', input='libpandaexpress.dll')
TargetAdd('maxeggimport'+VNUM+'.dle', input='maxImportRes.res')
TargetAdd('maxeggimport'+VNUM+'.dle', input='maxEggImport.def', ipath=OPTS)
TargetAdd('maxeggimport'+VNUM+'.dle', input=COMMON_DTOOL_LIBS)
TargetAdd('maxeggimport'+VNUM+'.dle', opts=OPTS)
#
# DIRECTORY: pandatool/src/vrml/
#

View File

@ -120,28 +120,12 @@ MAYAVERSIONINFO = [("MAYA6", "6.0"),
("MAYA2022","2022"),
]
MAXVERSIONINFO = [("MAX6", "SOFTWARE\\Autodesk\\3DSMAX\\6.0", "installdir", "maxsdk\\cssdk\\include"),
("MAX7", "SOFTWARE\\Autodesk\\3DSMAX\\7.0", "Installdir", "maxsdk\\include\\CS"),
("MAX8", "SOFTWARE\\Autodesk\\3DSMAX\\8.0", "Installdir", "maxsdk\\include\\CS"),
("MAX9", "SOFTWARE\\Autodesk\\3DSMAX\\9.0", "Installdir", "maxsdk\\include\\CS"),
("MAX2009", "SOFTWARE\\Autodesk\\3DSMAX\\11.0\\MAX-1:409", "Installdir", "maxsdk\\include\\CS"),
("MAX2010", "SOFTWARE\\Autodesk\\3DSMAX\\12.0\\MAX-1:409", "Installdir", "maxsdk\\include\\CS"),
("MAX2011", "SOFTWARE\\Autodesk\\3DSMAX\\13.0\\MAX-1:409", "Installdir", "maxsdk\\include\\CS"),
("MAX2012", "SOFTWARE\\Autodesk\\3DSMAX\\14.0\\MAX-1:409", "Installdir", "maxsdk\\include\\CS"),
("MAX2013", "SOFTWARE\\Autodesk\\3DSMAX\\15.0\\MAX-1:409", "Installdir", "maxsdk\\include\\CS"),
("MAX2014", "SOFTWARE\\Autodesk\\3DSMAX\\16.0\\MAX-1:409", "Installdir", "maxsdk\\include\\CS"),
]
MAYAVERSIONS = []
MAXVERSIONS = []
DXVERSIONS = ["DX9"]
for (ver,key) in MAYAVERSIONINFO:
MAYAVERSIONS.append(ver)
for (ver,key1,key2,subdir) in MAXVERSIONINFO:
MAXVERSIONS.append(ver)
########################################################################
##
## Potentially Conflicting Files
@ -2158,20 +2142,6 @@ def SdkLocateMaya():
if (os.path.isdir(ddir1)): SDK[ver] = ddir1
elif (os.path.isdir(ddir2)): SDK[ver] = ddir2
def SdkLocateMax():
if (GetHost() != "windows"): return
for version,key1,key2,subdir in MAXVERSIONINFO:
if (PkgSkip(version)==0):
if (version not in SDK):
GetSdkDir("maxsdk"+version.lower()[3:], version)
GetSdkDir("maxsdk"+version.lower()[3:], version+"CS")
if (not version in SDK):
top = GetRegistryKey(key1,key2)
if (top != 0):
SDK[version] = top + "maxsdk"
if (os.path.isdir(top + "\\" + subdir)!=0):
SDK[version+"CS"] = top + subdir
def SdkLocatePython(prefer_thirdparty_python=False):
if PkgSkip("PYTHON"):
# We're not compiling with Python support. We still need to set this
@ -2727,17 +2697,6 @@ def SdkAutoDisableMaya():
WARNINGS.append("I have automatically added this command-line option: --no-"+ver.lower())
PkgDisable(ver)
def SdkAutoDisableMax():
for version,key1,key2,subdir in MAXVERSIONINFO:
if (PkgSkip(version)==0) and ((version not in SDK) or (version+"CS" not in SDK)):
if (GetHost() == "windows"):
if (version in SDK):
WARNINGS.append("Your copy of "+version+" does not include the character studio SDK")
else:
WARNINGS.append("The registry does not appear to contain a pointer to "+version)
WARNINGS.append("I have automatically added this command-line option: --no-"+version.lower())
PkgDisable(version)
def SdkAutoDisableSpeedTree():
if ("SPEEDTREE" not in SDK) and (PkgSkip("SPEEDTREE")==0):
PkgDisable("SPEEDTREE")

View File

@ -1,860 +0,0 @@
/**
* @file maxEgg.cxx
* @author Steven "Sauce" Osman
* @date 2003-01
* @author Ken Strickland
* @date 2003-02-25
*
* This file implements the classes that are used in the Panda 3D file
* exporter for 3D Studio Max.
*/
#include "maxEgg.h"
const double meshVerts[252][3] = {
{0.729464, -0.919852, 0.714986},
{0.466137, -0.594656, 0.160201},
{-0.265897, -1.14704, 0.714986},
{0.466137, -0.594656, 0.160201},
{-0.177333, -0.741523, 0.160201},
{-0.265897, -1.14704, 0.714986},
{-0.265897, -1.14704, 0.714986},
{-0.177333, -0.741523, 0.160201},
{-1.06411, -0.510479, 0.714986},
{-0.177333, -0.741523, 0.160201},
{-0.693356, -0.330009, 0.160201},
{-1.06411, -0.510479, 0.714986},
{-1.06411, 0.510479, 0.714986},
{-1.06411, -0.510479, 0.714986},
{-0.693356, 0.330009, 0.160201},
{-0.693356, -0.330009, 0.160201},
{-0.693356, 0.330009, 0.160201},
{-1.06411, -0.510479, 0.714986},
{-0.265897, 1.14704, 0.714986},
{-1.06411, 0.510479, 0.714986},
{-0.177333, 0.741523, 0.160201},
{-0.693356, 0.330009, 0.160201},
{-0.177333, 0.741523, 0.160201},
{-1.06411, 0.510479, 0.714986},
{0.729464, 0.919852, 0.714986},
{-0.265897, 1.14704, 0.714986},
{0.466137, 0.594656, 0.160201},
{-0.177333, 0.741523, 0.160201},
{0.466137, 0.594656, 0.160201},
{-0.265897, 1.14704, 0.714986},
{1.17244, 0.0, 0.714986},
{0.729464, 0.919852, 0.714986},
{0.752508, 0.0, 0.160201},
{0.466137, 0.594656, 0.160201},
{0.752508, 0.0, 0.160201},
{0.729464, 0.919852, 0.714986},
{0.729464, -0.919852, 0.714986},
{1.17244, 0.0, 0.714986},
{0.466137, -0.594656, 0.160201},
{0.752508, 0.0, 0.160201},
{0.466137, -0.594656, 0.160201},
{1.17244, 0.0, 0.714986},
{-0.286334, -1.26822, 1.44995},
{0.814187, -1.01703, 1.44995},
{-0.265897, -1.14704, 0.714986},
{0.729464, -0.919852, 0.714986},
{-0.265897, -1.14704, 0.714986},
{0.814187, -1.01703, 1.44995},
{-1.16888, -0.564412, 1.44995},
{-0.286334, -1.26822, 1.44995},
{-1.06411, -0.510479, 0.714986},
{-0.265897, -1.14704, 0.714986},
{-1.06411, -0.510479, 0.714986},
{-0.286334, -1.26822, 1.44995},
{-1.16888, 0.564411, 1.44995},
{-1.16888, -0.564412, 1.44995},
{-1.06411, 0.510479, 0.714986},
{-1.06411, -0.510479, 0.714986},
{-1.06411, 0.510479, 0.714986},
{-1.16888, -0.564412, 1.44995},
{-1.16888, 0.564411, 1.44995},
{-1.06411, 0.510479, 0.714986},
{-0.286334, 1.26822, 1.44995},
{-1.06411, 0.510479, 0.714986},
{-0.265897, 1.14704, 0.714986},
{-0.286334, 1.26822, 1.44995},
{-0.286334, 1.26822, 1.44995},
{-0.265897, 1.14704, 0.714986},
{0.814187, 1.01703, 1.44995},
{-0.265897, 1.14704, 0.714986},
{0.729464, 0.919852, 0.714986},
{0.814187, 1.01703, 1.44995},
{1.30396, 0.0, 1.44995},
{0.814187, 1.01703, 1.44995},
{1.17244, 0.0, 0.714986},
{0.729464, 0.919852, 0.714986},
{1.17244, 0.0, 0.714986},
{0.814187, 1.01703, 1.44995},
{1.30396, 0.0, 1.44995},
{1.17244, 0.0, 0.714986},
{0.814187, -1.01703, 1.44995},
{1.17244, 0.0, 0.714986},
{0.729464, -0.919852, 0.714986},
{0.814187, -1.01703, 1.44995},
{-0.286334, -1.26822, 1.44995},
{-0.227573, -1.05763, 2.16723},
{0.814187, -1.01703, 1.44995},
{0.814187, -1.01703, 1.44995},
{-0.227573, -1.05763, 2.16723},
{0.690208, -0.848157, 2.16723},
{-1.16888, -0.564412, 1.44995},
{-0.963577, -0.470692, 2.16723},
{-0.286334, -1.26822, 1.44995},
{-0.286334, -1.26822, 1.44995},
{-0.963577, -0.470692, 2.16723},
{-0.227573, -1.05763, 2.16723},
{-1.16888, -0.564412, 1.44995},
{-1.16888, 0.564411, 1.44995},
{-0.963577, -0.470692, 2.16723},
{-1.16888, 0.564411, 1.44995},
{-0.963577, 0.470692, 2.16723},
{-0.963577, -0.470692, 2.16723},
{-1.16888, 0.564411, 1.44995},
{-0.286334, 1.26822, 1.44995},
{-0.963577, 0.470692, 2.16723},
{-0.286334, 1.26822, 1.44995},
{-0.227574, 1.05763, 2.16723},
{-0.963577, 0.470692, 2.16723},
{-0.286334, 1.26822, 1.44995},
{0.814187, 1.01703, 1.44995},
{-0.227574, 1.05763, 2.16723},
{0.814187, 1.01703, 1.44995},
{0.690208, 0.848157, 2.16723},
{-0.227574, 1.05763, 2.16723},
{0.814187, 1.01703, 1.44995},
{1.30396, 0.0, 1.44995},
{0.690208, 0.848157, 2.16723},
{1.30396, 0.0, 1.44995},
{1.09866, 0.0, 2.16723},
{0.690208, 0.848157, 2.16723},
{0.814187, -1.01703, 1.44995},
{0.690208, -0.848157, 2.16723},
{1.30396, 0.0, 1.44995},
{1.30396, 0.0, 1.44995},
{0.690208, -0.848157, 2.16723},
{1.09866, 0.0, 2.16723},
{-0.227573, -1.05763, 2.16723},
{-0.154893, -0.759032, 2.72566},
{0.690208, -0.848157, 2.16723},
{0.690208, -0.848157, 2.16723},
{-0.154893, -0.759032, 2.72566},
{0.50377, -0.608696, 2.72566},
{-0.963577, -0.470692, 2.16723},
{-0.683099, -0.337801, 2.72566},
{-0.227573, -1.05763, 2.16723},
{-0.227573, -1.05763, 2.16723},
{-0.683099, -0.337801, 2.72566},
{-0.154893, -0.759032, 2.72566},
{-0.963577, -0.470692, 2.16723},
{-0.963577, 0.470692, 2.16723},
{-0.683099, -0.337801, 2.72566},
{-0.963577, 0.470692, 2.16723},
{-0.683099, 0.337801, 2.72566},
{-0.683099, -0.337801, 2.72566},
{-0.963577, 0.470692, 2.16723},
{-0.227574, 1.05763, 2.16723},
{-0.683099, 0.337801, 2.72566},
{-0.227574, 1.05763, 2.16723},
{-0.154893, 0.759032, 2.72566},
{-0.683099, 0.337801, 2.72566},
{-0.227574, 1.05763, 2.16723},
{0.690208, 0.848157, 2.16723},
{-0.154893, 0.759032, 2.72566},
{0.690208, 0.848157, 2.16723},
{0.50377, 0.608696, 2.72566},
{-0.154893, 0.759032, 2.72566},
{0.690208, 0.848157, 2.16723},
{1.09866, 0.0, 2.16723},
{0.50377, 0.608696, 2.72566},
{1.09866, 0.0, 2.16723},
{0.796903, 0.0, 2.72566},
{0.50377, 0.608696, 2.72566},
{1.09866, 0.0, 2.16723},
{0.690208, -0.848157, 2.16723},
{0.796903, 0.0, 2.72566},
{0.690208, -0.848157, 2.16723},
{0.50377, -0.608696, 2.72566},
{0.796903, 0.0, 2.72566},
{0.50377, -0.608696, 2.72566},
{-0.154893, -0.759032, 2.72566},
{0.259722, -0.299638, 3.11175},
{-0.154893, -0.759032, 2.72566},
{-0.0645132, -0.373643, 3.11175},
{0.259722, -0.299638, 3.11175},
{-0.154893, -0.759032, 2.72566},
{-0.683099, -0.337801, 2.72566},
{-0.0645132, -0.373643, 3.11175},
{-0.683099, -0.337801, 2.72566},
{-0.324529, -0.166287, 3.11175},
{-0.0645132, -0.373643, 3.11175},
{-0.683099, -0.337801, 2.72566},
{-0.683099, 0.337801, 2.72566},
{-0.324529, -0.166287, 3.11175},
{-0.683099, 0.337801, 2.72566},
{-0.324529, 0.166287, 3.11175},
{-0.324529, -0.166287, 3.11175},
{-0.683099, 0.337801, 2.72566},
{-0.154893, 0.759032, 2.72566},
{-0.324529, 0.166287, 3.11175},
{-0.154893, 0.759032, 2.72566},
{-0.0645132, 0.373642, 3.11175},
{-0.324529, 0.166287, 3.11175},
{-0.154893, 0.759032, 2.72566},
{0.50377, 0.608696, 2.72566},
{-0.0645132, 0.373642, 3.11175},
{0.50377, 0.608696, 2.72566},
{0.259722, 0.299638, 3.11175},
{-0.0645132, 0.373642, 3.11175},
{0.50377, 0.608696, 2.72566},
{0.796903, 0.0, 2.72566},
{0.259722, 0.299638, 3.11175},
{0.796903, 0.0, 2.72566},
{0.40402, 0.0, 3.11175},
{0.259722, 0.299638, 3.11175},
{0.796903, 0.0, 2.72566},
{0.50377, -0.608696, 2.72566},
{0.40402, 0.0, 3.11175},
{0.50377, -0.608696, 2.72566},
{0.259722, -0.299638, 3.11175},
{0.40402, 0.0, 3.11175},
{-0.177333, -0.741523, 0.160201},
{0.466137, -0.594656, 0.160201},
{-0.00334214, 0.0, 0.00443203},
{-0.693356, -0.330009, 0.160201},
{-0.177333, -0.741523, 0.160201},
{-0.00334214, 0.0, 0.00443203},
{-0.693356, 0.330009, 0.160201},
{-0.693356, -0.330009, 0.160201},
{-0.00334214, 0.0, 0.00443203},
{-0.177333, 0.741523, 0.160201},
{-0.693356, 0.330009, 0.160201},
{-0.00334214, 0.0, 0.00443203},
{0.466137, 0.594656, 0.160201},
{-0.177333, 0.741523, 0.160201},
{-0.00334214, 0.0, 0.00443203},
{0.752508, 0.0, 0.160201},
{0.466137, 0.594656, 0.160201},
{-0.00334214, 0.0, 0.00443203},
{0.466137, -0.594656, 0.160201},
{0.752508, 0.0, 0.160201},
{-0.00334214, 0.0, 0.00443203},
{0.259722, -0.299638, 3.11175},
{-0.0645132, -0.373643, 3.11175},
{0.0207683, 0.0, 3.20912},
{-0.0645132, -0.373643, 3.11175},
{-0.324529, -0.166287, 3.11175},
{0.0207683, 0.0, 3.20912},
{-0.324529, -0.166287, 3.11175},
{-0.324529, 0.166287, 3.11175},
{0.0207683, 0.0, 3.20912},
{-0.324529, 0.166287, 3.11175},
{-0.0645132, 0.373642, 3.11175},
{0.0207683, 0.0, 3.20912},
{-0.0645132, 0.373642, 3.11175},
{0.259722, 0.299638, 3.11175},
{0.0207683, 0.0, 3.20912},
{0.259722, 0.299638, 3.11175},
{0.40402, 0.0, 3.11175},
{0.0207683, 0.0, 3.20912},
{0.40402, 0.0, 3.11175},
{0.259722, -0.299638, 3.11175},
{0.0207683, 0.0, 3.20912}
};
// Disable the forcing int to true or false performance warning
#pragma warning(disable: 4800)
/* MaxEggPluginClassDesc - A class that describes 3DS Plugin support.
This basically says "Yes, I am a helper object!"
*/
class MaxEggPluginClassDesc : public ClassDesc
{
public:
int IsPublic() { return TRUE; }
void *Create(BOOL loading = FALSE) { return new MaxEggPlugin(); }
const TCHAR *ClassName() { return GetString(IDS_CLASS_NAME); }
SClass_ID SuperClassID() { return HELPER_CLASS_ID; }
Class_ID ClassID() { return MaxEggPlugin_CLASS_ID; }
const TCHAR *Category() { return GetString(IDS_CATEGORY); }
// returns fixed parsable name (scripter-visible name)
const TCHAR *InternalName() { return _T("MaxEggPlugin"); }
};
// Our private global instance of the above class
static MaxEggPluginClassDesc MaxEggPluginDesc;
// Called by LibClassDesc to find out what the plugin is
ClassDesc* GetMaxEggPluginDesc() { return &MaxEggPluginDesc; }
// Initialize class-static variables
Mesh MaxEggPlugin::mesh;
short MaxEggPlugin::meshBuilt=0;
HWND MaxEggPlugin::hMaxEggParams = nullptr;
IObjParam *MaxEggPlugin::iObjParams;
/* MaxEggPluginOptionsDlgProc() - This is the callback function for the
dialog box that appears at the beginning of the conversion process.
*/
INT_PTR CALLBACK MaxEggPluginOptionsDlgProc( HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
MaxOptionsDialog *tempEgg;
int sel, res;
// We pass in our plugin through the lParam variable. Let's convert it
// back.
MaxEggPlugin *imp = (MaxEggPlugin*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
if ( !imp && message != WM_INITDIALOG ) return FALSE;
switch(message)
{
// When we start, center the window.
case WM_INITDIALOG:
// this line is very necessary to pass the plugin as the lParam
SetWindowLongPtr(hWnd,GWLP_USERDATA,lParam);
SetDlgFont( hWnd, imp->iObjParams->GetAppHFont() );
MaxEggPlugin::hMaxEggParams = hWnd;
return TRUE; break;
case WM_MOUSEACTIVATE:
imp->iObjParams->RealizeParamPanel();
return TRUE; break;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MOUSEMOVE:
imp->iObjParams->RollupMouseMessage(hWnd,message,wParam,lParam);
return TRUE; break;
// A control was modified
case WM_COMMAND:
// The modified control is found in the lower word of the wParam long.
switch( LOWORD(wParam) ) {
case IDC_OVERWRITE_CHECK:
imp->autoOverwrite =
(IsDlgButtonChecked(hWnd, IDC_OVERWRITE_CHECK) == BST_CHECKED);
return TRUE; break;
case IDC_PVIEW_CHECK:
imp->pview =
(IsDlgButtonChecked(hWnd, IDC_PVIEW_CHECK) == BST_CHECKED);
return TRUE; break;
case IDC_LOGGING:
imp->logOutput =
(IsDlgButtonChecked(hWnd, IDC_LOGGING) == BST_CHECKED);
return TRUE; break;
case IDC_ADD_EGG:
tempEgg = new MaxOptionsDialog();
tempEgg->SetMaxInterface(imp->iObjParams);
tempEgg->SetAnimRange();
res = DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_EGG_DETAILS),
hWnd, MaxOptionsDialogProc, (LPARAM)tempEgg);
if (res == TRUE) {
imp->SaveCheckState();
imp->AddEgg(tempEgg);
imp->UpdateUI();
}
else delete tempEgg;
return TRUE; break;
case IDC_EDIT_EGG:
sel = ListView_GetSelectionMark(GetDlgItem(hWnd, IDC_LIST_EGGS));
if (sel != -1) {
MaxOptionsDialog *tempEgg = imp->GetEgg(sel);
if (tempEgg) {
tempEgg->SetAnimRange();
tempEgg->CullBadNodes();
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_EGG_DETAILS),
hWnd, MaxOptionsDialogProc, (LPARAM)tempEgg);
}
imp->SaveCheckState();
imp->UpdateUI();
}
return TRUE; break;
case IDC_REMOVE_EGG:
sel = ListView_GetSelectionMark(GetDlgItem(hWnd, IDC_LIST_EGGS));
if (sel != -1) {
imp->SaveCheckState();
imp->RemoveEgg(sel);
imp->UpdateUI();
}
return TRUE; break;
case IDC_EXPORT:
imp->DoExport();
return TRUE; break;
}
}
return FALSE;
}
MaxEggPlugin::MaxEggPlugin() :
autoOverwrite(false), pview(true), logOutput(false), numEggs(0), maxEggs(5)
{
eggList = new MaxOptionsDialog*[maxEggs];
BuildMesh();
}
MaxEggPlugin::~MaxEggPlugin() {
for (int i = 0; i < numEggs; i++) delete eggList[i];
delete [] eggList;
}
void MaxEggPlugin::AddEgg(MaxOptionsDialog *newEgg) {
if (numEggs >= maxEggs) {
MaxOptionsDialog **newList;
maxEggs *= 2;
newList = new MaxOptionsDialog*[maxEggs];
for (int i = 0; i < numEggs; i++) newList[i] = eggList[i];
delete [] eggList;
eggList = newList;
}
eggList[numEggs++] = newEgg;
}
void MaxEggPlugin::RemoveEgg(int i) {
if (i >= 0 && i < numEggs) {
delete eggList[i];
for (int j = i+1; j < numEggs;) eggList[i++] = eggList[j++];
--numEggs;
}
}
void MaxEggPlugin::BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev )
{
iObjParams = ip;
for (int i=0; i<numEggs; i++) {
eggList[i]->SetMaxInterface(ip);
}
if ( !hMaxEggParams ) {
hMaxEggParams = ip->AddRollupPage(hInstance,
MAKEINTRESOURCE(IDD_PANEL),
MaxEggPluginOptionsDlgProc,
GetString(IDS_PARAMS),
(LPARAM)this );
ip->RegisterDlgWnd(hMaxEggParams);
} else {
SetWindowLongPtr( hMaxEggParams, GWLP_USERDATA, (LPARAM)this );
}
UpdateUI();
}
void MaxEggPlugin::EndEditParams( IObjParam *ip, ULONG flags,Animatable *prev)
{
SaveCheckState();
if ( flags&END_EDIT_REMOVEUI ) {
ip->UnRegisterDlgWnd(hMaxEggParams);
ip->DeleteRollupPage(hMaxEggParams);
hMaxEggParams = nullptr;
} else {
SetWindowLongPtr( hMaxEggParams, GWLP_USERDATA, 0L );
}
}
void MaxEggPlugin::SaveCheckState() {
if (!hMaxEggParams) return;
HWND lv = GetDlgItem(hMaxEggParams, IDC_LIST_EGGS);
for (int i = 0; i < numEggs; i++)
eggList[i]->_checked = ListView_GetCheckState(lv, i);
}
void MaxEggPlugin::UpdateUI() {
HWND lv = GetDlgItem(hMaxEggParams, IDC_LIST_EGGS);
LV_COLUMN pCol;
if (ListView_GetColumnWidth(lv, 1) <= 0 || ListView_GetColumnWidth(lv, 1) > 10000) {
// Columns have not been setup, so initialize the control
ListView_SetExtendedListViewStyleEx(lv, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT,
LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
pCol.fmt = LVCFMT_LEFT;
pCol.cx = 96;
pCol.pszText = _T("Filename");
pCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
pCol.iSubItem = 0;
ListView_InsertColumn(lv, 0, &pCol);
pCol.cx = 44;
pCol.pszText = _T("Type");
ListView_InsertColumn(lv, 1, &pCol);
}
// Add the eggs to the list
ListView_DeleteAllItems(lv);
LV_ITEM Item;
Item.mask = LVIF_TEXT;
for (int i = 0; i < numEggs; i++) {
Item.iItem = i;
Item.iSubItem = 0;
Item.pszText = eggList[i]->_short_name;
ListView_InsertItem(lv, &Item);
Item.iSubItem = 1;
switch(eggList[i]->_anim_type) {
case MaxEggOptions::AT_chan: Item.pszText = _T("Animation"); break;
case MaxEggOptions::AT_both: Item.pszText = _T("Both"); break;
case MaxEggOptions::AT_pose: Item.pszText = _T("Static"); break;
case MaxEggOptions::AT_model: Item.pszText = _T("Model"); break;
default: Item.pszText = _T("Model"); break;
}
ListView_SetItem(lv, &Item);
ListView_SetCheckState(lv, i, eggList[i]->_checked);
}
// Set the "Overwrite Existing Files" and "Pview" checkboxes
CheckDlgButton(hMaxEggParams, IDC_OVERWRITE_CHECK,
autoOverwrite ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hMaxEggParams, IDC_PVIEW_CHECK,
pview ? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hMaxEggParams, IDC_LOGGING,
logOutput ? BST_CHECKED : BST_UNCHECKED);
}
void MaxEggPlugin::DoExport() {
int good = 0, bad = 0;
std::basic_stringstream<TCHAR> status;
SaveCheckState();
for (int i = 0; i < numEggs; i++) {
if (eggList[i]->_checked) {
// If "auto overwrite" was not checked and the file exists, ask if
// the user wishes to overwrite the file
bool do_write = true;
if (!autoOverwrite && GetFileAttributes(eggList[i]->_file_name) != INVALID_FILE_ATTRIBUTES) {
TCHAR msg[1024];
_stprintf(msg, _T("Overwrite file \"%s.egg\"?"), eggList[i]->_short_name);
do_write = (MessageBox(hMaxEggParams, msg, _T("Panda3D Exporter"), MB_YESNO | MB_ICONQUESTION) == IDYES);
}
if (do_write) {
MaxToEggConverter converter;
if (converter.convert((MaxEggOptions*)eggList[i])) {
good += 1;
status << _T("Successfully created ") << eggList[i]->_short_name << _T(".egg\n");
} else {
bad += 1;
status << _T("Could not export ") << eggList[i]->_short_name << _T(".egg\n");
}
} else {
bad += 1;
status << _T("Skipped file ") << eggList[i]->_short_name << _T(".egg\n");
}
}
}
UINT mask = MB_OK;
if (good == 0 && bad == 0) {
mask |= MB_ICONEXCLAMATION;
MessageBox(hMaxEggParams, _T("Nothing to export!"), _T("Panda3D Export results"), mask);
} else {
if (bad > 0) mask |= MB_ICONEXCLAMATION;
else mask |= MB_ICONINFORMATION;
MessageBox(hMaxEggParams, status.str().c_str(), _T("Panda3D Export results"), mask);
}
int pviewed = 0;
if (pview && good > 0) {
for (i = 0; i < numEggs; i++) {
if (eggList[i]->_checked && eggList[i]->_successful) {
if (eggList[i]->_anim_type != MaxEggOptions::AT_chan) {
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
TCHAR cmdLine[2048];
// If we have just one model and animation file, pview
// them both
if (numEggs == 2 && eggList[i]->_anim_type == MaxEggOptions::AT_model &&
eggList[1-i]->_checked && eggList[1-i]->_successful &&
eggList[1-i]->_anim_type == MaxEggOptions::AT_chan) {
_stprintf(cmdLine, _T("pview \"%s\" \"%s\""), eggList[i]->_file_name, eggList[1-i]->_file_name);
} else {
_stprintf(cmdLine, _T("pview \"%s\""), eggList[i]->_file_name);
}
CreateProcess(nullptr, cmdLine, nullptr, nullptr, FALSE, CREATE_NEW_CONSOLE,
nullptr, nullptr, &si, &pi);
pviewed += 1;
}
}
}
}
}
void MaxEggPlugin::BuildMesh()
{
int i;
if(meshBuilt) return;
mesh.setNumVerts(252);
mesh.setNumFaces(84);
mesh.setSmoothFlags(0);
mesh.setNumTVerts (0);
mesh.setNumTVFaces (0);
for (i=0; i<252; i++)
mesh.setVert(i, meshVerts[i][0]*10, meshVerts[i][1]*10, meshVerts[i][2]*10);
for (i=0; i<84; i++) {
mesh.faces[i].setEdgeVisFlags(1, 1, 0);
mesh.faces[i].setSmGroup(0);
mesh.faces[i].setVerts(i*3, i*3+1, i*3+2);
}
mesh.InvalidateGeomCache();
mesh.BuildStripsAndEdges();
meshBuilt = TRUE;
}
// The creation callback - sets the initial position of the helper in the
// scene.
class MaxEggPluginCreateMouseCallBack: public CreateMouseCallBack
{
public:
int proc( ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat );
};
int MaxEggPluginCreateMouseCallBack::proc(ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat )
{
if (msg==MOUSE_POINT||msg==MOUSE_MOVE) {
switch(point) {
case 0:
mat.SetTrans(vpt->SnapPoint(m,m,nullptr,SNAP_IN_PLANE));
break;
case 1:
mat.SetTrans(vpt->SnapPoint(m,m,nullptr,SNAP_IN_PLANE));
if (msg==MOUSE_POINT) return CREATE_STOP;
break;
}
} else if (msg == MOUSE_ABORT) {
return CREATE_ABORT;
}
return CREATE_CONTINUE;
}
static MaxEggPluginCreateMouseCallBack MaxEggCreateMouseCB;
CreateMouseCallBack* MaxEggPlugin::GetCreateMouseCallBack()
{ return &MaxEggCreateMouseCB; }
// Boilerplate functions for dealing with the display of the plugin
void MaxEggPlugin::GetMat(TimeValue t, INode* inode, ViewExp* vpt, Matrix3& tm)
{
tm = inode->GetObjectTM(t);
tm.NoScale();
PN_stdfloat scaleFactor = vpt->NonScalingObjectSize()*vpt->GetVPWorldWidth(tm.GetTrans())/(PN_stdfloat)360.0;
tm.Scale(Point3(scaleFactor,scaleFactor,scaleFactor));
}
void MaxEggPlugin::GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm, BOOL useSel )
{
box = mesh.getBoundingBox(tm);
}
void MaxEggPlugin::GetLocalBoundBox(TimeValue t, INode* inode, ViewExp* vpt, Box3& box )
{
Matrix3 m = inode->GetObjectTM(t);
Point3 pt;
Point3 q[4];
PN_stdfloat scaleFactor = vpt->GetVPWorldWidth(m.GetTrans())/360.0f;
box = mesh.getBoundingBox();
box.Scale(scaleFactor);
}
void MaxEggPlugin::GetWorldBoundBox(TimeValue t, INode* inode, ViewExp* vpt, Box3& box )
{
int i, nv; Matrix3 tm; Point3 pt;
GetMat(t,inode,vpt,tm);
nv = mesh.getNumVerts();
box.Init();
for (i=0; i<nv; i++)
box += tm*mesh.getVert(i);
}
int MaxEggPlugin::HitTest(TimeValue t, INode *inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt)
{
HitRegion hitRegion;
DWORD savedLimits;
Matrix3 m;
GraphicsWindow *gw = vpt->getGW();
Material *mtl = gw->getMaterial();
MakeHitRegion(hitRegion,type,crossing,4,p);
gw->setRndLimits(((savedLimits = gw->getRndLimits()) | GW_PICK) & ~GW_ILLUM);
GetMat(t,inode,vpt,m);
gw->setTransform(m);
gw->clearHitCode();
if (mesh.select( gw, mtl, &hitRegion, flags & HIT_ABORTONHIT ))
return TRUE;
return FALSE;
}
int MaxEggPlugin::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags)
{
Matrix3 m;
GraphicsWindow *gw = vpt->getGW();
Material *mtl = gw->getMaterial();
GetMat(t,inode,vpt,m);
gw->setTransform(m);
DWORD rlim = gw->getRndLimits();
gw->setRndLimits(GW_WIREFRAME|GW_BACKCULL);
if (inode->Selected())
gw->setColor( LINE_COLOR, GetSelColor());
else if(!inode->IsFrozen())
gw->setColor( LINE_COLOR, GetUIColor(COLOR_TAPE_OBJ));
mesh.render( gw, mtl, nullptr, COMP_ALL);
return 0;
}
RefResult MaxEggPlugin::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message )
{
UpdateUI();
return REF_SUCCEED;
}
ObjectState MaxEggPlugin::Eval(TimeValue time)
{
return ObjectState(this);
}
Interval MaxEggPlugin::ObjectValidity(TimeValue t)
{
Interval ivalid;
ivalid.SetInfinite();
return ivalid;
}
RefTargetHandle MaxEggPlugin::Clone(RemapDir& remap)
{
MaxEggPlugin* newob = new MaxEggPlugin();
return(newob);
}
// Loading and saving the plugin
IOResult MaxEggPlugin::Save(ISave *isave) {
SaveCheckState();
for (int i = 0; i < numEggs; i++)
eggList[i]->Save(isave);
ChunkSave(isave, CHUNK_OVERWRITE_FLAG, autoOverwrite);
ChunkSave(isave, CHUNK_PVIEW_FLAG, pview);
ChunkSave(isave, CHUNK_LOG_OUTPUT, logOutput);
return IO_OK;
}
IOResult MaxEggPlugin::Load(ILoad *iload) {
IOResult res = iload->OpenChunk();
MaxOptionsDialog *temp;
while (res == IO_OK) {
switch(iload->CurChunkID()) {
case CHUNK_OVERWRITE_FLAG: autoOverwrite = ChunkLoadBool(iload); break;
case CHUNK_PVIEW_FLAG: pview = ChunkLoadBool(iload); break;
case CHUNK_LOG_OUTPUT: logOutput = ChunkLoadBool(iload); break;
case CHUNK_EGG_EXP_OPTIONS:
temp = new MaxOptionsDialog();
temp->SetMaxInterface(iObjParams);
temp->Load(iload);
AddEgg(temp);
break;
}
iload->CloseChunk();
res = iload->OpenChunk();
}
return IO_OK;
}
/**********************************************************************
*
* DLL Initialization
*
**********************************************************************/
extern ClassDesc* GetMaxEggPluginDesc();
HINSTANCE hInstance;
int controlsInit = FALSE;
// This function is called by Windows when the DLL is loaded. This function
// may also be called many times during time critical operations like
// rendering. Therefore developers need to be careful what they do inside
// this function. In the code below, note how after the DLL is loaded the
// first time only a few statements are executed.
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved)
{
hInstance = hinstDLL; // Hang on to this DLL's instance handle.
if (!controlsInit) {
controlsInit = TRUE;
#if MAX_VERSION_MAJOR < 14
// It appears that InitCustomControls is deprecated in 2012.
// I'm not sure if we can just remove it like this, but I've
// heard that it seems to work, so let's do it like this.
InitCustomControls(hInstance); // Initialize MAX's custom controls
#endif
InitCommonControls(); // Initialize Win95 controls
}
return (TRUE);
}
// This function returns a string that describes the DLL and where the user
// could purchase the DLL if they don't have it.
__declspec( dllexport ) const TCHAR* LibDescription()
{
return GetString(IDS_LIBDESCRIPTION);
}
// This function returns the number of plug-in classes this DLL operates on.
// TODO: Must change this number when adding a new class
__declspec( dllexport ) int LibNumberClasses()
{
return 1;
}
// This function returns the descriptions of the plug-in classes this DLL
// operates on.
__declspec( dllexport ) ClassDesc* LibClassDesc(int i)
{
switch(i) {
case 0: return GetMaxEggPluginDesc();
default: return nullptr;
}
}
// This function returns a pre-defined constant indicating the version of the
// system under which it was compiled. It is used to allow the system to
// catch obsolete DLLs.
__declspec( dllexport ) ULONG LibVersion()
{
return VERSION_3DSMAX;
}
TCHAR *GetString(int id)
{
static TCHAR buf[256];
if (hInstance)
return LoadString(hInstance, id, buf, sizeof(buf)) ? buf : nullptr;
return nullptr;
}

View File

@ -1,8 +0,0 @@
LIBRARY MaxEgg
EXPORTS
LibDescription @1
LibNumberClasses @2
LibClassDesc @3
LibVersion @4
SECTIONS
.data READ WRITE

View File

@ -1,172 +0,0 @@
/*
MaxEgg.h
Created by Steven "Sauce" Osman, Jan03
Modified and maintained by Ken Strickland, (02/01/03)-(05/15/03)
Modified and maintained by Corey Revilla, (05/22/03)-present
Carnegie Mellon University, Entetainment Technology Center
This file contains a 3dsMax exporter derived from discreet's own SceneExport
plug-in class; this exporter is basically a wrapper around the MaxToEgg
Panda-converter class, and just sets up the interface and environment
in which the MaxToEgg class can be "run" as if it were a standalone app.
*/
#ifndef __MaxEgg__H
#define __MaxEgg__H
#include "pandatoolbase.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <crtdbg.h>
#include <errno.h>
using std::min;
using std::max;
#include "eggGroup.h"
#include "eggTable.h"
#include "eggXfmSAnim.h"
#include "eggData.h"
#include "referenceCount.h"
#include "pointerTo.h"
#include "namable.h"
#include <iostream>
#include <fstream>
#include <vector>
#define WIN32_LEAN_AND_MEAN
#include <windef.h>
#include <windows.h>
#include <Max.h>
#include <iparamb2.h>
#include <iparamm2.h>
#include <istdplug.h>
#include <iskin.h>
#include <stdmat.h>
#include <phyexp.h>
#include <surf_api.h>
#include <bipexp.h>
#include <modstack.h>
#include "eggCoordinateSystem.h"
#include "eggGroup.h"
#include "eggPolygon.h"
#include "eggTextureCollection.h"
#include "eggTexture.h"
#include "eggVertex.h"
#include "eggVertexPool.h"
#include "eggNurbsCurve.h"
#include "pandatoolbase.h"
#include "eggXfmSAnim.h"
#include "pathStore.h"
#include "maxNodeDesc.h"
#include "maxNodeTree.h"
#include "maxOptionsDialog.h"
#include "maxResource.h"
#include "maxToEggConverter.h"
#define MaxEggPlugin_CLASS_ID Class_ID(0x7ac0d6b7, 0x55731ef6)
#pragma conform(forScope, off)
/* Externed Globals
*/
extern HINSTANCE hInstance;
/* Global Functions
*/
extern TCHAR *GetString(int id);
/* This class defines the 3D Studio Max exporter itself. It is basically a
shell that is invoked by 3D Studio Max's export API. It then sets up
MaxToEgg instance and attempts to "fool it" into thinking that it is
actually being invoked as a standalone program. The thought behind this
is that some day MaxToEgg may well be a standalone program, provided that
a suitable interface to Max files can be connected from a standalone
program instead of a plugin.
*/
#if MAX_VERSION_MAJOR < 9
#define DefaultRemapDir NoRemap
#endif
class MaxEggPlugin : public HelperObject
{
MaxOptionsDialog **eggList;
int numEggs;
int maxEggs;
public:
bool autoOverwrite;
bool pview;
bool logOutput;
// Class vars
static Mesh mesh; // This plugin generates no geometry, this mesh is not passed on to 3D Studio.
static short meshBuilt;
static HWND hMaxEggParams;
static IObjParam *iObjParams;
// ConstructorDestructor
MaxEggPlugin();
virtual ~MaxEggPlugin();
// Other class Methods
void DoExport();
void UpdateUI();
void SaveCheckState();
void BuildMesh();
void AddEgg(MaxOptionsDialog *newEgg);
void RemoveEgg(int i);
MaxOptionsDialog *GetEgg(int i) { return (i >= 0 && i < numEggs) ? eggList[i] : nullptr; }
// Required implimented virtual methods: inherited virtual methods for
// Reference-management
RefResult NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget, PartID& partID, RefMessage message );
void GetMat(TimeValue t, INode* inod, ViewExp *vpt, Matrix3& mat);
// From BaseObject
int HitTest(TimeValue t, INode* inode, int type, int crossing, int flags, IPoint2 *p, ViewExp *vpt);
int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags);
CreateMouseCallBack* GetCreateMouseCallBack();
void BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev);
void EndEditParams( IObjParam *ip, ULONG flags,Animatable *next);
#if MAX_VERSION_MAJOR < 15
TCHAR *GetObjectName() { return GetString(IDS_LIBDESCRIPTION); }
#else
const TCHAR *GetObjectName() { return GetString(IDS_LIBDESCRIPTION); }
#endif
// From Object
ObjectState Eval(TimeValue time);
void InitNodeName(TSTR& s) { s = GetString(IDS_CLASS_NAME); }
Interval ObjectValidity(TimeValue time);
void Invalidate();
int DoOwnSelectHilite() { return 1; }
// From GeomObject
int IntersectRay(TimeValue t, Ray& r, PN_stdfloat& at) { return 0; }
void GetWorldBoundBox(TimeValue t, INode *mat, ViewExp *vpt, Box3& box );
void GetLocalBoundBox(TimeValue t, INode *mat, ViewExp *vpt, Box3& box );
void GetDeformBBox(TimeValue t, Box3& box, Matrix3 *tm, BOOL useSel );
// Animatable methods
void DeleteThis() { delete this; }
Class_ID ClassID() { return MaxEggPlugin_CLASS_ID; }
void GetClassName(TSTR& s) { s = TSTR(GetString(IDS_CLASS_NAME)); }
TSTR SubAnimName(int i) { return TSTR(GetString(IDS_CLASS_NAME)); }
// From ref
RefTargetHandle Clone(RemapDir& remap = DefaultRemapDir());
// IO
IOResult Save(ISave *isave);
IOResult Load(ILoad *iload);
};
#endif // __MaxEgg__H

View File

@ -1,200 +0,0 @@
// Microsoft Visual C++ generated resource script.
//
#include "maxResource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "WinResrc.h"
#define IDC_STATIC -1
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Neutral resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
#ifdef _WIN32
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_EGG_DETAILS DIALOGEX 0, 0, 256, 203
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Export Settings"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Animation Type:",IDC_STATIC,6,5,54,8,NOT WS_GROUP
CONTROL "Model",IDC_MODEL,"Button",BS_AUTORADIOBUTTON | BS_LEFT | WS_GROUP,65,4,38,12
CONTROL "Animation",IDC_ANIMATION,"Button",BS_AUTORADIOBUTTON | BS_LEFT,108,4,50,12
CONTROL "Both",IDC_BOTH,"Button",BS_AUTORADIOBUTTON | BS_LEFT,164,4,35,12
CONTROL "Static",IDC_POSE,"Button",BS_AUTORADIOBUTTON | BS_LEFT,206,4,38,12
LTEXT "Filename",IDC_STATIC,12,30,66,8,NOT WS_GROUP
CONTROL "Custom1",IDC_FILENAME,"CustEdit",WS_TABSTOP,12,42,180,12
CONTROL "Browse...",IDC_BROWSE,"CustButton",WS_TABSTOP,198,42,48,12
CONTROL "Export Entire Scene",IDC_EXPORT_ALL,"Button",BS_AUTORADIOBUTTON | BS_LEFT | WS_GROUP,12,59,79,10
CONTROL "Export Meshes:",IDC_EXPORT_SELECTED,"Button",BS_AUTORADIOBUTTON | BS_LEFT,12,71,66,10
LISTBOX IDC_LIST_EXPORT,12,84,114,36,LBS_SORT | LBS_NOINTEGRALHEIGHT | LBS_NOSEL | WS_VSCROLL | WS_TABSTOP
CONTROL "Add...",IDC_ADD_EXPORT,"CustButton",WS_TABSTOP,12,126,54,12
CONTROL "Remove...",IDC_REMOVE_EXPORT,"CustButton",WS_TABSTOP,72,126,54,12
CONTROL "Export All Frames",IDC_EXP_ALL_FRAMES,"Button",BS_AUTORADIOBUTTON | BS_LEFT | WS_GROUP,144,59,72,10
CONTROL "Use Range:",IDC_EXP_SEL_FRAMES,"Button",BS_AUTORADIOBUTTON | BS_LEFT | BS_VCENTER,144,71,53,10
LTEXT "Start Frame",IDC_SF_LABEL,144,90,42,8,WS_DISABLED | NOT WS_GROUP
CONTROL "Custom4",IDC_SF,"CustEdit",WS_DISABLED | WS_TABSTOP,186,87,48,12
LTEXT "End Frame",IDC_EF_LABEL,143,104,42,8,WS_DISABLED | NOT WS_GROUP
CONTROL "Custom5",IDC_EF,"CustEdit",WS_DISABLED | WS_TABSTOP,186,102,48,12
CONTROL "Double-sided Polygons",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,144,126,102,12
CONTROL "OK",IDC_OK,"CustButton",WS_TABSTOP,162,179,42,12
CONTROL "Cancel",IDC_CANCEL,"CustButton",WS_TABSTOP,208,179,42,12
LTEXT "The collision tags are now defined within each object's User Defined properties window. For more information and help please consult the panda3d manual at www.panda3d.org",IDC_STATIC,12,146,225,26
END
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
1 VERSIONINFO
FILEVERSION 3,0,0,0
PRODUCTVERSION 3,0,0,0
FILEFLAGSMASK 0x0L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "FileVersion", "4.0.0.0"
VALUE "InternalName", "MaxEgg"
VALUE "OriginalFilename", "MaxEgg.dle"
VALUE "ProductName", "3ds max"
VALUE "ProductVersion", "4.0.0.0"
VALUE "FileDescription", "Panda3D .egg exporter"
VALUE "Comments", "TECH: "
VALUE "LegalTrademarks", "3D Studio MAX, Biped, Character Studio, Heidi, Kinetix and Physique are registered trademarks and 3ds max, combustion, Discreet, DWG Unplugged, DXF, FLI and FLC are trademarks of Autodesk, Inc."
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // Neutral resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_PANEL DIALOGEX 0, 0, 108, 192
STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Sans Serif", 0, 0, 0x1
BEGIN
CTEXT "Panda 3D EGG Exporter",IDC_PANEL_TITLE,6,6,96,11,WS_BORDER | NOT WS_GROUP
LTEXT "Eggs",IDC_EGGS_LABEL,6,19,62,8,NOT WS_GROUP
CONTROL "Custom1",IDC_LIST_EGGS,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | WS_TABSTOP,6,28,96,69,WS_EX_CLIENTEDGE
CONTROL "Add...",IDC_ADD_EGG,"CustButton",WS_TABSTOP,6,102,24,12
CONTROL "Edit...",IDC_EDIT_EGG,"CustButton",WS_TABSTOP,36,102,30,12
CONTROL "Remove",IDC_REMOVE_EGG,"CustButton",WS_TABSTOP,72,102,30,12
CONTROL "Overwrite Existing Files",IDC_OVERWRITE_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,126,103,8,WS_EX_TRANSPARENT
CONTROL "Export Now",IDC_EXPORT,"CustButton",WS_TABSTOP,5,164,96,18
CONTROL "Pview Output",IDC_PVIEW_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,4,138,103,8,WS_EX_TRANSPARENT
CONTROL "Log Output",IDC_LOGGING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,6,148,90,11
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.\0"
END
3 TEXTINCLUDE
BEGIN
"\r\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_PANEL, DIALOG
BEGIN
RIGHTMARGIN, 107
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_LIBDESCRIPTION "Panda3D .egg exporter"
IDS_CATEGORY "Exporters"
IDS_CLASS_NAME "Panda3D"
IDS_PARAMS "Parameters"
IDS_SPIN "Spin"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -1,726 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file maxEggLoader.cxx
* @author jyelon
* @date 2005-07-15
*
* This file contains the code for class MaxEggLoader. This class
* does the actual work of copying an EggData tree into the max scene.
*/
#include "pandatoolbase.h"
#include "notifyCategoryProxy.h"
#include "eggData.h"
#include "eggVertexPool.h"
#include "eggVertex.h"
#include "eggPolygon.h"
#include "eggPrimitive.h"
#include "eggGroupNode.h"
#include "eggPolysetMaker.h"
#include "eggBin.h"
using std::min;
using std::max;
#include <stdio.h>
#include <Max.h>
#include <istdplug.h>
#include <stdmat.h>
#include <decomp.h>
#include <shape.h>
#include <simpobj.h>
#include <iparamb2.h>
#include <iskin.h>
#include <modstack.h>
#include "maxEggLoader.h"
using std::vector;
class MaxEggMesh;
class MaxEggJoint;
class MaxEggTex;
NotifyCategoryDeclNoExport(maxloader);
NotifyCategoryDef(maxloader, "");
class MaxEggLoader
{
public:
bool ConvertEggData(EggData *data, bool merge, bool model, bool anim);
bool ConvertEggFile(const char *name, bool merge, bool model, bool anim);
public:
void TraverseEggNode(EggNode *node, EggGroup *context);
MaxEggMesh *GetMesh(EggVertexPool *pool);
MaxEggJoint *FindJoint(EggGroup *joint);
MaxEggJoint *MakeJoint(EggGroup *joint, EggGroup *context);
MaxEggTex *GetTex(const Filename &fn);
void CreateSkinModifier(MaxEggMesh *M);
typedef phash_map<EggVertexPool *, MaxEggMesh *> MeshTable;
typedef second_of_pair_iterator<MeshTable::const_iterator> MeshIterator;
typedef phash_map<EggGroup *, MaxEggJoint *> JointTable;
typedef second_of_pair_iterator<JointTable::const_iterator> JointIterator;
typedef phash_map<std::string, MaxEggTex *> TexTable;
typedef second_of_pair_iterator<TexTable::const_iterator> TexIterator;
MeshTable _mesh_tab;
JointTable _joint_tab;
TexTable _tex_tab;
int _next_tex;
};
Point3 MakeMaxPoint(LVector3d vec)
{
return Point3(vec[0], vec[1], vec[2]);
}
// MaxEggTex
class MaxEggTex
{
public:
Filename _path;
int _id;
StdMat *_mat;
BitmapTex *_bmt;
};
MaxEggTex *MaxEggLoader::GetTex(const Filename &fn)
{
if (_tex_tab.count(fn))
return _tex_tab[fn];
BitmapTex *bmt = NewDefaultBitmapTex();
#ifdef _UNICODE
bmt->SetMapName((TCHAR*) fn.to_os_specific_w().c_str());
#else
bmt->SetMapName((char*) fn.to_os_specific().c_str());
#endif
StdMat *mat = NewDefaultStdMat();
mat->SetSubTexmap(ID_DI, bmt);
mat->SetTexmapAmt(ID_DI, 1.0, 0);
mat->EnableMap(ID_DI, TRUE);
mat->SetActiveTexmap(bmt);
GetCOREInterface()->ActivateTexture(bmt, mat);
MaxEggTex *res = new MaxEggTex;
res->_path = fn;
res->_id = _next_tex ++;
res->_bmt = bmt;
res->_mat = mat;
_tex_tab[fn] = res;
return res;
}
// MaxEggJoint
class MaxEggJoint
{
public:
LMatrix4d _trans;
LVector3d _endpos;
LVector3d _perp;
double _thickness;
bool _inskin;
SimpleObject2 *_bone;
INode *_node;
EggGroup *_egg_joint;
MaxEggJoint *_parent;
vector <MaxEggJoint *> _children;
public:
void GetRotation(LVector3d &xv, LVector3d &yv, LVector3d &zv);
LVector3d GetPos(void) { return _trans.get_row3(3); }
MaxEggJoint *ChooseBestChild(LVector3d dir);
void ChooseEndPos(double thickness);
void CreateMaxBone(void);
};
void MaxEggJoint::GetRotation(LVector3d &xv, LVector3d &yv, LVector3d &zv)
{
xv = _trans.get_row3(0);
yv = _trans.get_row3(1);
zv = _trans.get_row3(2);
xv.normalize();
yv.normalize();
zv = xv.cross(yv);
zv.normalize();
yv = zv.cross(xv);
}
MaxEggJoint *MaxEggLoader::FindJoint(EggGroup *joint)
{
if (joint==0) return 0;
return _joint_tab[joint];
}
MaxEggJoint *MaxEggLoader::MakeJoint(EggGroup *joint, EggGroup *context)
{
MaxEggJoint *parent = FindJoint(context);
MaxEggJoint *result = new MaxEggJoint;
LMatrix4d t = joint->get_transform3d();
if (parent) {
result->_trans = t * parent->_trans;
} else {
result->_trans = t;
}
result->_endpos = LVector3d(0,0,0);
result->_perp = LVector3d(0,0,0);
result->_thickness = 0.0;
result->_inskin = false;
result->_bone = 0;
result->_node = 0;
result->_egg_joint = joint;
result->_parent = parent;
if (parent) parent->_children.push_back(result);
_joint_tab[joint] = result;
return result;
}
MaxEggJoint *MaxEggJoint::ChooseBestChild(LVector3d dir)
{
if (dir.length() < 0.001) return 0;
dir.normalize();
double firstbest = -1000;
MaxEggJoint *firstchild = 0;
LVector3d firstpos = GetPos();
double secondbest = 0;
for (int i=0; i<_children.size(); i++) {
MaxEggJoint *child = _children[i];
LVector3d tryfwd = child->GetPos() - GetPos();
if ((child->GetPos() != firstpos) && (tryfwd.length() > 0.001)) {
LVector3d trydir = tryfwd;
trydir.normalize();
double quality = trydir.dot(dir);
if (quality > firstbest) {
secondbest = firstbest;
firstbest = quality;
firstpos = child->GetPos();
firstchild = child;
} else if (quality > secondbest) {
secondbest = quality;
}
}
}
if (firstbest > secondbest + 0.1)
return firstchild;
return 0;
}
void MaxEggJoint::ChooseEndPos(double thickness)
{
LVector3d parentpos(0,0,0);
LVector3d parentendpos(0,0,1);
if (_parent) {
parentpos = _parent->GetPos();
parentendpos = _parent->_endpos;
}
LVector3d fwd = GetPos() - parentpos;
if (fwd.length() < 0.001) {
fwd = parentendpos - parentpos;
}
fwd.normalize();
MaxEggJoint *child = ChooseBestChild(fwd);
if (child == 0) {
_endpos = fwd * thickness * 0.8 + GetPos();
_thickness = thickness * 0.8;
} else {
_endpos = child->GetPos();
_thickness = (_endpos - GetPos()).length();
if (_thickness > thickness) _thickness = thickness;
}
LVector3d orient = _endpos - GetPos();
orient.normalize();
LVector3d altaxis = orient.cross(LVector3d(0,-1,0));
if (altaxis.length() < 0.001) altaxis = orient.cross(LVector3d(0,0,1));
_perp = altaxis.cross(orient);
_perp.normalize();
}
void MaxEggJoint::CreateMaxBone(void)
{
LVector3d rxv,ryv,rzv;
GetRotation(rxv, ryv, rzv);
Point3 xv(MakeMaxPoint(rxv));
Point3 yv(MakeMaxPoint(ryv));
Point3 zv(MakeMaxPoint(rzv));
Point3 pos(MakeMaxPoint(GetPos()));
Point3 endpos(MakeMaxPoint(_endpos));
Point3 tzv(MakeMaxPoint(_perp));
Point3 fwd = endpos - pos;
double len = fwd.Length();
Point3 txv = fwd * ((PN_stdfloat)(1.0/len));
Point3 tyv = tzv ^ txv;
Point3 row1 = Point3(txv % xv, txv % yv, txv % zv);
Point3 row2 = Point3(tyv % xv, tyv % yv, tyv % zv);
Point3 row3 = Point3(tzv % xv, tzv % yv, tzv % zv);
Matrix3 oomat(row1,row2,row3,Point3(0,0,0));
Quat ooquat(oomat);
_bone = (SimpleObject2*)CreateInstance(GEOMOBJECT_CLASS_ID, BONE_OBJ_CLASSID);
_node = GetCOREInterface()->CreateObjectNode(_bone);
_node->SetNodeTM(0, Matrix3(xv, yv, zv, pos));
IParamBlock2 *blk = _bone->pblock2;
for (int i=0; i<blk->NumParams(); i++) {
TSTR n = blk->GetLocalName(i);
if (_tcscmp(n, _T("Length")) == 0) blk->SetValue(i, 0, (PN_stdfloat) len);
else if (_tcscmp(n, _T("Width")) == 0) blk->SetValue(i, 0, (PN_stdfloat) _thickness);
else if (_tcscmp(n, _T("Height")) == 0) blk->SetValue(i, 0, (PN_stdfloat) _thickness);
}
Point3 boneColor = GetUIColor(COLOR_BONES);
_node->SetWireColor(RGB(int(boneColor.x*255.0f), int(boneColor.y*255.0f), int(boneColor.z*255.0f) ));
_node->SetBoneNodeOnOff(TRUE, 0);
_node->SetRenderable(FALSE);
#ifdef _UNICODE
TCHAR wname[1024];
wname[1023] = 0;
mbstowcs(wname, _egg_joint->get_name().c_str(), 1023);
_node->SetName(wname);
#else
_node->SetName((char*) _egg_joint->get_name().c_str());
#endif
_node->SetObjOffsetRot(ooquat);
if (_parent) {
_node->Detach(0, 1);
_parent->_node->AttachChild(_node, 1);
}
}
// MaxEggMesh
typedef std::pair<double, EggGroup *> MaxEggWeight;
struct MaxEggVertex
{
LVertexd _pos;
LNormald _normal;
vector<MaxEggWeight> _weights;
int _index;
};
struct MEV_Compare: public stl_hash_compare<MaxEggVertex>
{
size_t operator()(const MaxEggVertex &key) const
{
return key._pos.add_hash(key._normal.get_hash());
}
bool operator()(const MaxEggVertex &k1, const MaxEggVertex &k2) const
{
int n = k1._pos.compare_to(k2._pos);
if (n < 0) return true;
if (n > 0) return false;
n = k1._normal.compare_to(k2._normal);
if (n < 0) return true;
if (n > 0) return false;
n = k1._weights.size() - k2._weights.size();
if (n < 0) return true;
if (n > 0) return false;
for (int i=0; i<k1._weights.size(); i++) {
double d = k1._weights[i].first - k2._weights[i].first;
if (d < 0) return true;
if (d > 0) return false;
EggGroup *g1 = k1._weights[i].second;
EggGroup *g2 = k2._weights[i].second;
if (g1 < g2) return true;
if (g1 > g2) return false;
}
return false;
}
};
typedef phash_set<MaxEggVertex, MEV_Compare> VertTable;
typedef phash_map<LTexCoordd, int> TVertTable;
typedef phash_map<LColor, int> CVertTable;
class MaxEggMesh
{
public:
std::string _name;
TriObject *_obj;
Mesh *_mesh;
INode *_node;
IDerivedObject *_dobj;
Modifier *_skin_mod;
ISkin *_iskin;
ISkinImportData *_iskin_import;
int _vert_count;
int _tvert_count;
int _cvert_count;
int _face_count;
VertTable _vert_tab;
TVertTable _tvert_tab;
CVertTable _cvert_tab;
int GetVert(EggVertex *vert, EggGroup *context);
int GetTVert(const LTexCoordd &uv);
int GetCVert(const LColor &col);
int AddFace(int v0, int v1, int v2, int tv0, int tv1, int tv2, int cv0, int cv1, int cv2, int tex);
EggGroup *GetControlJoint(void);
};
#define CTRLJOINT_DEFORM ((EggGroup*)((char*)(-1)))
int MaxEggMesh::GetVert(EggVertex *vert, EggGroup *context)
{
MaxEggVertex vtx;
vtx._pos = vert->get_pos3();
vtx._normal = vert->get_normal();
vtx._index = 0;
EggVertex::GroupRef::const_iterator gri;
for (gri = vert->gref_begin(); gri != vert->gref_end(); ++gri) {
EggGroup *egg_joint = (*gri);
double membership = egg_joint->get_vertex_membership(vert);
vtx._weights.push_back(MaxEggWeight(membership, egg_joint));
}
if (vtx._weights.size()==0) {
if (context != 0)
vtx._weights.push_back(MaxEggWeight(1.0, context));
}
VertTable::const_iterator vti = _vert_tab.find(vtx);
if (vti != _vert_tab.end())
return vti->_index;
if (_vert_count == _mesh->numVerts) {
int nsize = _vert_count*2 + 100;
_mesh->setNumVerts(nsize, _vert_count?TRUE:FALSE);
}
vtx._index = _vert_count++;
_vert_tab.insert(vtx);
_mesh->setVert(vtx._index, MakeMaxPoint(vtx._pos));
return vtx._index;
}
int MaxEggMesh::GetTVert(const LTexCoordd &uv)
{
if (_tvert_tab.count(uv))
return _tvert_tab[uv];
if (_tvert_count == _mesh->numTVerts) {
int nsize = _tvert_count*2 + 100;
_mesh->setNumTVerts(nsize, _tvert_count?TRUE:FALSE);
}
int idx = _tvert_count++;
_mesh->setTVert(idx, uv.get_x(), uv.get_y(), 0.0);
_tvert_tab[uv] = idx;
return idx;
}
int MaxEggMesh::GetCVert(const LColor &col)
{
if (_cvert_tab.count(col))
return _cvert_tab[col];
if (_cvert_count == _mesh->numCVerts) {
int nsize = _cvert_count*2 + 100;
_mesh->setNumVertCol(nsize, _cvert_count?TRUE:FALSE);
}
int idx = _cvert_count++;
_mesh->vertCol[idx] = Point3(col.get_x(), col.get_y(), col.get_z());
_cvert_tab[col] = idx;
return idx;
}
MaxEggMesh *MaxEggLoader::GetMesh(EggVertexPool *pool)
{
MaxEggMesh *result = _mesh_tab[pool];
if (result == 0) {
std::string name = pool->get_name();
int nsize = name.size();
if ((nsize > 6) && (name.rfind(".verts")==(nsize-6)))
name.resize(nsize-6);
result = new MaxEggMesh;
result->_name = name;
result->_obj = CreateNewTriObject();
result->_mesh = &result->_obj->GetMesh();
result->_mesh->setMapSupport(0, TRUE);
result->_node = GetCOREInterface()->CreateObjectNode(result->_obj);
result->_dobj = 0;
result->_skin_mod = 0;
result->_iskin = 0;
result->_iskin_import = 0;
result->_vert_count = 0;
result->_tvert_count = 0;
result->_cvert_count = 0;
result->_face_count = 0;
#ifdef _UNICODE
TCHAR wname[1024];
wname[1023] = 0;
mbstowcs(wname, name.c_str(), 1023);
result->_node->SetName(wname);
#else
result->_node->SetName((char*) name.c_str());
#endif
_mesh_tab[pool] = result;
}
return result;
}
int MaxEggMesh::AddFace(int v0, int v1, int v2, int tv0, int tv1, int tv2, int cv0, int cv1, int cv2, int tex)
{
static int dump = 0;
if (_face_count == _mesh->numFaces) {
int nsize = _face_count*2 + 100;
BOOL keep = _mesh->numFaces ? TRUE : FALSE;
_mesh->setNumFaces(nsize, keep);
_mesh->setNumTVFaces(nsize, keep, _face_count);
_mesh->setNumVCFaces(nsize, keep, _face_count);
}
int idx = _face_count++;
_mesh->faces[idx].setVerts(v0,v1,v2);
_mesh->faces[idx].smGroup = 1;
_mesh->faces[idx].flags = EDGE_ALL | HAS_TVERTS;
_mesh->faces[idx].setMatID(tex);
_mesh->tvFace[idx].setTVerts(tv0,tv1,tv2);
_mesh->vcFace[idx].setTVerts(cv0,cv1,cv2);
return idx;
}
EggGroup *MaxEggMesh::GetControlJoint(void)
{
EggGroup *result;
VertTable::const_iterator vert = _vert_tab.begin();
if (vert == _vert_tab.end()) return 0;
switch (vert->_weights.size()) {
case 0:
for (++vert; vert != _vert_tab.end(); ++vert)
if (vert->_weights.size() != 0)
return CTRLJOINT_DEFORM;
return 0;
case 1:
result = vert->_weights[0].second;
for (++vert; vert != _vert_tab.end(); ++vert)
if ((vert->_weights.size() != 1) || (vert->_weights[0].second != result))
return CTRLJOINT_DEFORM;
return result;
default:
return CTRLJOINT_DEFORM;
}
}
void MaxEggLoader::CreateSkinModifier(MaxEggMesh *M)
{
vector <MaxEggJoint *> joints;
M->_dobj = CreateDerivedObject(M->_obj);
M->_node->SetObjectRef(M->_dobj);
M->_skin_mod = (Modifier*)CreateInstance(OSM_CLASS_ID, SKIN_CLASSID);
M->_iskin = (ISkin*)M->_skin_mod->GetInterface(I_SKIN);
M->_iskin_import = (ISkinImportData*)M->_skin_mod->GetInterface(I_SKINIMPORTDATA);
M->_dobj->SetAFlag(A_LOCK_TARGET);
M->_dobj->AddModifier(M->_skin_mod);
M->_dobj->ClearAFlag(A_LOCK_TARGET);
GetCOREInterface()->ForceCompleteRedraw();
VertTable::const_iterator vert;
for (vert=M->_vert_tab.begin(); vert != M->_vert_tab.end(); ++vert) {
for (int i=0; i<vert->_weights.size(); i++) {
double strength = vert->_weights[i].first;
MaxEggJoint *joint = FindJoint(vert->_weights[i].second);
if (!joint->_inskin) {
joint->_inskin = true;
joints.push_back(joint);
}
}
}
for (int i=0; i<joints.size(); i++) {
BOOL last = (i == (joints.size()-1)) ? TRUE : FALSE;
M->_iskin_import->AddBoneEx(joints[i]->_node, last);
joints[i]->_inskin = false;
}
GetCOREInterface()->SetCommandPanelTaskMode(TASK_MODE_MODIFY);
GetCOREInterface()->SelectNode(M->_node);
GetCOREInterface()->ForceCompleteRedraw();
for (vert=M->_vert_tab.begin(); vert != M->_vert_tab.end(); ++vert) {
Tab<INode*> maxJoints;
Tab<PN_stdfloat> maxWeights;
maxJoints.ZeroCount();
maxWeights.ZeroCount();
for (int i=0; i<vert->_weights.size(); i++) {
PN_stdfloat strength = (PN_stdfloat)(vert->_weights[i].first);
MaxEggJoint *joint = FindJoint(vert->_weights[i].second);
maxWeights.Append(1,&strength);
maxJoints.Append(1,&(joint->_node));
}
M->_iskin_import->AddWeights(M->_node, vert->_index, maxJoints, maxWeights);
}
}
// TraverseEggData We have an EggData in memory, and now we're going to copy
// that over into the max scene graph.
void MaxEggLoader::TraverseEggNode(EggNode *node, EggGroup *context)
{
vector<int> vertIndices;
vector<int> tvertIndices;
vector<int> cvertIndices;
if (node->is_of_type(EggPolygon::get_class_type())) {
EggPolygon *poly = DCAST(EggPolygon, node);
int texid;
LMatrix3d uvtrans = LMatrix3d::ident_mat();
if (poly->has_texture()) {
EggTexture *tex = poly->get_texture(0);
texid = GetTex(tex->get_fullpath())->_id;
if (tex->has_transform())
uvtrans = tex->get_transform2d();
} else {
texid = GetTex(Filename())->_id;
}
EggPolygon::const_iterator ci;
MaxEggMesh *mesh = GetMesh(poly->get_pool());
vertIndices.clear();
tvertIndices.clear();
cvertIndices.clear();
for (ci = poly->begin(); ci != poly->end(); ++ci) {
EggVertex *vtx = (*ci);
EggVertexPool *pool = poly->get_pool();
LTexCoordd uv = vtx->get_uv();
vertIndices.push_back(mesh->GetVert(vtx, context));
tvertIndices.push_back(mesh->GetTVert(uv * uvtrans));
cvertIndices.push_back(mesh->GetCVert(vtx->get_color()));
}
for (int i=1; i<vertIndices.size()-1; i++)
mesh->AddFace(vertIndices[0], vertIndices[i], vertIndices[i+1],
tvertIndices[0], tvertIndices[i], tvertIndices[i+1],
cvertIndices[0], cvertIndices[i], cvertIndices[i+1],
texid);
} else if (node->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *group = DCAST(EggGroupNode, node);
if (node->is_of_type(EggGroup::get_class_type())) {
EggGroup *group = DCAST(EggGroup, node);
if (group->is_joint()) {
MakeJoint(group, context);
context = group;
}
}
EggGroupNode::const_iterator ci;
for (ci = group->begin(); ci != group->end(); ++ci) {
TraverseEggNode(*ci, context);
}
}
}
bool MaxEggLoader::ConvertEggData(EggData *data, bool merge, bool model, bool anim)
{
if (!merge) {
maxloader_cat.error() << "Currently, only 'merge' mode is implemented.\n";
return false;
}
if ((anim) || (!model)) {
maxloader_cat.error() << "Currently, only model-loading is implemented.\n";
return false;
}
MeshIterator ci;
JointIterator ji;
TexIterator ti;
data->set_coordinate_system(CS_zup_right);
SuspendAnimate();
SuspendSetKeyMode();
AnimateOff();
_next_tex = 0;
TraverseEggNode(data, nullptr);
for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
MaxEggMesh *mesh = (*ci);
mesh->_mesh->setNumVerts(mesh->_vert_count, TRUE);
mesh->_mesh->setNumTVerts(mesh->_tvert_count, TRUE);
mesh->_mesh->setNumVertCol(mesh->_cvert_count, TRUE);
mesh->_mesh->setNumFaces(mesh->_face_count, TRUE);
mesh->_mesh->setNumTVFaces(mesh->_face_count, TRUE, mesh->_face_count);
mesh->_mesh->setNumVCFaces(mesh->_face_count, TRUE, mesh->_face_count);
mesh->_mesh->InvalidateTopologyCache();
mesh->_mesh->InvalidateGeomCache();
mesh->_mesh->buildNormals();
}
double thickness = 0.0;
for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) {
double dfo = ((*ji)->GetPos()).length();
if (dfo > thickness) thickness = dfo;
}
thickness = thickness * 0.025;
for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) {
MaxEggJoint *joint = *ji;
joint->ChooseEndPos(thickness);
joint->CreateMaxBone();
}
for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
MaxEggMesh *mesh = (*ci);
EggGroup *joint = mesh->GetControlJoint();
if (joint) CreateSkinModifier(mesh);
}
if (_next_tex) {
TSTR name;
MultiMtl *mtl = NewDefaultMultiMtl();
mtl->SetNumSubMtls(_next_tex);
for (ti = _tex_tab.begin(); ti != _tex_tab.end(); ++ti) {
MaxEggTex *tex = *ti;
mtl->SetSubMtlAndName(tex->_id, tex->_mat, name);
}
for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) {
MaxEggMesh *mesh = *ci;
mesh->_node->SetMtl(mtl);
}
}
for (ci = _mesh_tab.begin(); ci != _mesh_tab.end(); ++ci) delete *ci;
for (ji = _joint_tab.begin(); ji != _joint_tab.end(); ++ji) delete *ji;
for (ti = _tex_tab.begin(); ti != _tex_tab.end(); ++ti) delete *ti;
ResumeSetKeyMode();
ResumeAnimate();
maxloader_cat.info() << "Egg import successful\n";
return true;
}
bool MaxEggLoader::ConvertEggFile(const char *name, bool merge, bool model, bool anim)
{
EggData data;
Filename datafn = Filename::from_os_specific(name);
if (!data.read(datafn)) {
maxloader_cat.error() << "Cannot read Egg file for import\n";
return false;
}
return ConvertEggData(&data, merge, model, anim);
}
// The two global functions that form the API of this module.
bool MaxLoadEggData(EggData *data, bool merge, bool model, bool anim)
{
MaxEggLoader loader;
return loader.ConvertEggData(data, merge, model, anim);
}
bool MaxLoadEggFile(const char *name, bool merge, bool model, bool anim)
{
MaxEggLoader loader;
return loader.ConvertEggFile(name, merge, model, anim);
}

View File

@ -1,22 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file maxEggLoader.h
* @author jyelon
* @date 2005-07-15
*/
#ifndef MAXEGGLOADER_H
#define MAXEGGLOADER_H
class EggData;
bool MaxLoadEggData(EggData *data, bool merge, bool model, bool anim);
bool MaxLoadEggFile(const char *name, bool merge, bool model, bool anim);
#endif

View File

@ -1,198 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file maxNodeDesc.cxx
* @author crevilla
* from mayaNodeDesc.cxx created by: drose (06Jun03)
*/
#include "maxEgg.h"
TypeHandle MaxNodeDesc::_type_handle;
/**
* Creates a MaxNodeDesc. The name is copied from the given max node. Use
* from_INode to actually associate the desc with a given max node.
*/
MaxNodeDesc::
MaxNodeDesc(MaxNodeDesc *parent, INode *max_node) :
_parent(parent) {
if (max_node != nullptr) {
const TCHAR *max_name = max_node->GetName();
#ifdef _UNICODE
char name_mb [1024];
name_mb[1023] = 0;
wcstombs(name_mb, max_name, 1023);
set_name(name_mb);
#else
set_name(max_name);
#endif
}
_max_node = nullptr;
_egg_group = nullptr;
_egg_table = nullptr;
_anim = nullptr;
_joint_type = JT_none;
_joint_entry = nullptr;
// Add ourselves to our parent.
if (_parent != nullptr) {
_parent->_children.push_back(this);
}
}
/**
*
*/
MaxNodeDesc::
~MaxNodeDesc() {}
/**
* Indicates an associated between the MaxNodeDesc and some Max Node instance.
*/
void MaxNodeDesc::
from_INode(INode *max_node) {
if (_max_node == nullptr) {
_max_node = max_node;
// This is how I decided to check to see if this max node is a joint. It
// works in all instances I've seen so far, but this may be a good
// starting place to look if joints are not being picked up correctly in
// the future.
// Check to see if the node's controller is a biped If so treat it as a
// joint Get the node's transform control
Control *c = max_node->GetTMController();
if (_max_node->GetBoneNodeOnOff() ||
(c && //c exists and it's type is a biped
((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
(c->ClassID() == FOOTPRINT_CLASS_ID)))) {
// This node is a joint.
_joint_type = JT_node_joint;
if (_parent != nullptr) {
_parent->mark_joint_parent();
}
}
}
}
/**
* Returns true if a Max INode has been associated with this node, false
* otherwise.
*/
bool MaxNodeDesc::
has_max_node() const {
return (_max_node != nullptr);
}
/**
* Returns the INode associated with this node. It is an error to call this
* unless has_max_node() returned true.
*/
INode *MaxNodeDesc::
get_max_node() const {
nassertr(_max_node != nullptr, _max_node);
return _max_node;
}
void MaxNodeDesc::
set_joint(bool onoff) {
if (onoff)
_joint_type = JT_joint;
else
_joint_type = JT_none;
}
/**
* Returns true if the node should be treated as a joint by the converter.
*/
bool MaxNodeDesc::
is_joint() const {
return _joint_type == JT_joint || _joint_type == JT_pseudo_joint;
}
/**
* Returns true if the node is the parent or ancestor of a joint.
*/
bool MaxNodeDesc::
is_joint_parent() const {
return _joint_type == JT_joint_parent;
}
/**
* Returns true if the node is the parent or ancestor of a joint.
*/
bool MaxNodeDesc::
is_node_joint() const {
return _joint_type == JT_node_joint;
}
/**
* Recursively clears the egg pointers from this node and all children.
*/
void MaxNodeDesc::
clear_egg() {
_egg_group = nullptr;
_egg_table = nullptr;
_anim = nullptr;
Children::const_iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
MaxNodeDesc *child = (*ci);
child->clear_egg();
}
}
/**
* Indicates that this node has at least one child that is a joint or a
* pseudo-joint.
*/
void MaxNodeDesc::
mark_joint_parent() {
if (_joint_type == JT_none) {
_joint_type = JT_joint_parent;
if (_parent != nullptr) {
_parent->mark_joint_parent();
}
}
}
/**
* Walks the hierarchy, looking for non-joint nodes that are both children and
* parents of a joint. These nodes are deemed to be pseudo joints, since the
* converter must treat them as joints.
*/
void MaxNodeDesc::
check_pseudo_joints(bool joint_above) {
if (_joint_type == JT_joint_parent && joint_above) {
// This is one such node: it is the parent of a joint (JT_joint_parent is
// set), and it is the child of a joint (joint_above is set).
_joint_type = JT_pseudo_joint;
}
if (_joint_type == JT_joint) {
// If this node is itself a joint, then joint_above is true for all child
// nodes.
joint_above = true;
}
// Don't bother traversing further if _joint_type is none, since that means
// this node has no joint children.
if (_joint_type != JT_none) {
Children::const_iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
MaxNodeDesc *child = (*ci);
child->check_pseudo_joints(joint_above);
}
}
}

View File

@ -1,82 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file maxNodeDesc.h
* @author crevilla
* from mayaNodeDesc.h created by: drose (06Jun03)
*/
#ifndef MAXNODEDESC_H
#define MAXNODEDESC_H
/**
* Describes a single instance of a node in the Max scene graph, relating it
* to the corresponding egg structures (e.g. node, group, or table entry)
* that will be created.
*/
class MaxNodeDesc : public ReferenceCount, public Namable {
public:
MaxNodeDesc(MaxNodeDesc *parent = nullptr, INode *max_node = nullptr);
~MaxNodeDesc();
void from_INode(INode *max_node);
bool has_max_node() const;
INode *get_max_node() const;
void set_joint(bool onoff);
bool is_joint() const;
bool is_joint_parent() const;
bool is_node_joint() const;
MaxNodeDesc *_parent;
MaxNodeDesc *_joint_entry;
typedef pvector< MaxNodeDesc* > Children;
Children _children;
private:
void clear_egg();
void mark_joint_parent();
void check_pseudo_joints(bool joint_above);
INode *_max_node;
EggGroup *_egg_group;
EggTable *_egg_table;
EggXfmSAnim *_anim;
enum JointType {
JT_none, // Not a joint.
JT_node_joint, // Node that represents a joint in the geometry
// but not the actual joint itself
JT_joint, // An actual joint in Max.
JT_pseudo_joint, // Not a joint in Max, but treated just like a
// joint for the purposes of the converter.
JT_joint_parent, // A parent or ancestor of a joint or pseudo joint.
};
JointType _joint_type;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
ReferenceCount::init_type();
Namable::init_type();
register_type(_type_handle, "MaxNodeDesc",
ReferenceCount::get_class_type(),
Namable::get_class_type());
}
private:
static TypeHandle _type_handle;
friend class MaxNodeTree;
};
#endif

View File

@ -1,447 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file maxNodeTree.cxx
* @author crevilla
* from mayaNodeTree.cxx created by: drose (06Jun03)
*/
#include "maxEgg.h"
/**
*
*/
MaxNodeTree::
MaxNodeTree() {
_root = new MaxNodeDesc;
_fps = 0.0;
_export_mesh = false;
_egg_data = nullptr;
_egg_root = nullptr;
_skeleton_node = nullptr;
}
/**
* Returns a pointer to the node corresponding to the indicated INode object,
* creating it first if necessary.
*/
MaxNodeDesc *MaxNodeTree::
build_node(INode *max_node) {
MaxNodeDesc *node_desc = r_build_node(max_node);
node_desc->from_INode(max_node);
if (node_desc->is_node_joint()) {
node_desc->_joint_entry = build_joint(max_node, node_desc);
}
return node_desc;
}
/**
* Returns a pointer to the node corresponding to the indicated INode object,
* creating it first if necessary.
*/
MaxNodeDesc *MaxNodeTree::
build_joint(INode *max_node, MaxNodeDesc *node_joint) {
MaxNodeDesc *node_desc = r_build_joint(node_joint, max_node);
node_desc->from_INode(max_node);
node_desc->set_joint(true);
return node_desc;
}
bool MaxNodeTree::node_in_list(ULONG handle, ULONG *list, int len) {
if (!list) return true;
for (int i = 0; i < len; i++)
if (list[i] == handle) return true;
return false;
}
bool MaxNodeTree::is_joint(INode *node) {
Control *c = node->GetTMController();
return (node->GetBoneNodeOnOff() || //joints
(c && //bipeds
((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
(c->ClassID() == FOOTPRINT_CLASS_ID))));
}
bool MaxNodeTree::
r_build_hierarchy(INode *root, ULONG *selection_list, int len) {
if (node_in_list(root->GetHandle(), selection_list, len))
build_node(root);
// Export children
for ( int i = 0; i < root->NumberOfChildren(); i++ ) {
// *** Should probably be checking the return value of the following line
r_build_hierarchy(root->GetChildNode(i), selection_list, len);
}
return true;
}
/**
* Walks through the complete Max hierarchy and builds up the corresponding
* tree.
*/
bool MaxNodeTree::
build_complete_hierarchy(INode *root, ULONG *selection_list, int len) {
// Get the entire Max scene.
if (root == nullptr) {
// *** Log an error
return false;
}
bool all_ok = true;
r_build_hierarchy(root, selection_list, len);
if (all_ok) {
_root->check_pseudo_joints(false);
}
return all_ok;
}
/**
* Returns the total number of nodes in the hierarchy, not counting the root
* node.
*/
int MaxNodeTree::
get_num_nodes() const {
return _nodes.size();
}
/**
* Returns the nth node in the hierarchy, in an arbitrary ordering.
*/
MaxNodeDesc *MaxNodeTree::
get_node(int n) const {
nassertr(n >= 0 && n < (int)_nodes.size(), nullptr);
return _nodes[n];
}
/**
* Removes all of the references to generated egg structures from the tree,
* and prepares the tree for generating new egg structures.
*/
void MaxNodeTree::
clear_egg(EggData *egg_data, EggGroupNode *egg_root,
EggGroupNode *skeleton_node) {
_root->clear_egg();
_egg_data = egg_data;
_egg_root = egg_root;
_skeleton_node = skeleton_node;
}
/**
* Returns the EggGroupNode corresponding to the group or joint for the
* indicated node. Creates the group node if it has not already been created.
*/
EggGroup *MaxNodeTree::
get_egg_group(MaxNodeDesc *node_desc) {
nassertr(_egg_root != nullptr, nullptr);
if (node_desc->_egg_group == nullptr) {
// We need to make a new group node.
EggGroup *egg_group;
nassertr(node_desc->_parent != nullptr, nullptr);
egg_group = new EggGroup(node_desc->get_name());
if (node_desc->is_joint()) {
egg_group->set_group_type(EggGroup::GT_joint);
}
if (node_desc->_parent == _root) {
// The parent is the root. Set collision properties for the root if it
// has them:
if(!_export_mesh)
{
set_collision_tags(node_desc, egg_group);
}
_egg_root->add_child(egg_group);
} else {
// The parent is another node. if export mesh, the tag should be added
// at the second level
if(_export_mesh)
{
if(node_desc->_parent->_parent == _root)
{
set_collision_tags(node_desc, egg_group);
}
}
EggGroup *parent_egg_group = get_egg_group(node_desc->_parent);
parent_egg_group->add_child(egg_group);
}
node_desc->_egg_group = egg_group;
}
return node_desc->_egg_group;
}
/**
* Returns the EggTable corresponding to the joint for the indicated node.
* Creates the table node if it has not already been created.
*/
EggTable *MaxNodeTree::
get_egg_table(MaxNodeDesc *node_desc) {
nassertr(_skeleton_node != nullptr, nullptr);
nassertr(node_desc->is_joint(), nullptr);
if (node_desc->_egg_table == nullptr) {
// We need to make a new table node.
nassertr(node_desc->_parent != nullptr, nullptr);
EggTable *egg_table = new EggTable(node_desc->get_name());
node_desc->_anim = new EggXfmSAnim("xform",
_egg_data->get_coordinate_system());
node_desc->_anim->set_fps(_fps);
egg_table->add_child(node_desc->_anim);
if (!node_desc->_parent->is_joint()) {
// The parent is not a joint; put it at the top.
_skeleton_node->add_child(egg_table);
} else {
// The parent is another joint.
EggTable *parent_egg_table = get_egg_table(node_desc->_parent);
parent_egg_table->add_child(egg_table);
}
node_desc->_egg_table = egg_table;
}
return node_desc->_egg_table;
}
/**
* Returns the anim table corresponding to the joint for the indicated node.
* Creates the table node if it has not already been created.
*/
EggXfmSAnim *MaxNodeTree::
get_egg_anim(MaxNodeDesc *node_desc) {
get_egg_table(node_desc);
return node_desc->_anim;
}
/**
* The recursive implementation of build_node().
*/
MaxNodeDesc *MaxNodeTree::
r_build_node(INode* max_node) {
// If we have already encountered this pathname, return the corresponding
// MaxNodeDesc immediately.
ULONG node_handle = 0;
if (max_node) {
node_handle = max_node->GetHandle();
}
NodesByPath::const_iterator ni = _nodes_by_path.find(node_handle);
if (ni != _nodes_by_path.end()) {
return (*ni).second;
}
// Otherwise, we have to create it. Do this recursively, so we create each
// node along the path.
MaxNodeDesc *node_desc;
if (!max_node) {
// This is the top.
node_desc = _root;
} else {
INode *parent_node;
if (max_node->IsRootNode()) {
parent_node = nullptr;
} else {
parent_node = max_node->GetParentNode();
}
MaxNodeDesc *parent_node_desc = r_build_node(parent_node);
node_desc = new MaxNodeDesc(parent_node_desc, max_node);
_nodes.push_back(node_desc);
}
_nodes_by_path.insert(NodesByPath::value_type(node_handle, node_desc));
return node_desc;
}
/**
* The recursive implementation of build_joint().
*/
MaxNodeDesc *MaxNodeTree::
r_build_joint(MaxNodeDesc *node_desc, INode *max_node)
{
MaxNodeDesc *node_joint;
if (node_desc == _root) {
node_joint = new MaxNodeDesc(_root, max_node);
_nodes.push_back(node_joint);
return node_joint;
} else if (node_desc->is_node_joint() && node_desc->_joint_entry) {
node_joint = new MaxNodeDesc(node_desc->_joint_entry, max_node);
_nodes.push_back(node_joint);
return node_joint;
} else {
return r_build_joint(node_desc->_parent, max_node);
}
}
/**
* The recursive implementation of build_node().
*/
MaxNodeDesc *MaxNodeTree::
find_node(INode* max_node) {
// If we have already encountered this pathname, return the corresponding
// MaxNodeDesc immediately.
ULONG node_handle = 0;
if (max_node) {
node_handle = max_node->GetHandle();
}
NodesByPath::const_iterator ni = _nodes_by_path.find(node_handle);
if (ni != _nodes_by_path.end()) {
return (*ni).second;
}
return nullptr;
}
/**
* The recursive implementation of build_node().
*/
MaxNodeDesc *MaxNodeTree::
find_joint(INode* max_node)
{
MaxNodeDesc *node = find_node(max_node);
if (!node || (is_joint(max_node) && !node->is_node_joint()))
node = build_node(max_node);
return node->_joint_entry;
}
/**
* Sets the corresponding collision tag to the egg_group based on the User
* Defined Tab in the object properties panel
*/
void MaxNodeTree::set_collision_tags(MaxNodeDesc *node_desc, EggGroup *egg_group) {
// Max has huge problems passing strings and bools to Get and SetUserProp
// So instead we have to use Integers. Now we have to check for every
// collide type, then get its collide flags and do some number crunching
// to get the actual flag into the group
int check = 1; //is the value true. This could be anything really
// We have to check each collision type in turn to see if it's true Ugly
// but it works per object, not globaly
if (node_desc->get_max_node()->GetUserPropInt(_T("polyset"), check)) {
// we have a polyset.
if (check == 1) {
egg_group->set_collision_name(node_desc->get_name());
egg_group->set_cs_type(EggGroup::CST_polyset);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("plane"), check)) {
// plane
if (check == 1) {
egg_group->set_collision_name(node_desc->get_name());
egg_group->set_cs_type(EggGroup::CST_plane);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("polygon"), check)) {
// polygon
if (check == 1) {
egg_group->set_collision_name(node_desc->get_name());
egg_group->set_cs_type(EggGroup::CST_polygon);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("sphere"), check)) {
// sphere
if (check == 1) {
egg_group->set_collision_name(node_desc->get_name());
egg_group->set_cs_type(EggGroup::CST_sphere);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("inv-sphere"), check)) {
// invsphere
if (check == 1) {
egg_group->set_collision_name(node_desc->get_name());
egg_group->set_cs_type(EggGroup::CST_inv_sphere);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("invsphere"), check)) {
// invsphere (different spelling)
if (check == 1) {
egg_group->set_collision_name(node_desc->get_name());
egg_group->set_cs_type(EggGroup::CST_inv_sphere);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("tube"), check)) {
// tube
if (check == 1) {
egg_group->set_collision_name(node_desc->get_name());
egg_group->set_cs_type(EggGroup::CST_tube);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("floor-mesh"), check)) {
// floor-mesh
if (check == 1) {
egg_group->set_collision_name(node_desc->get_name());
egg_group->set_cs_type(EggGroup::CST_floor_mesh);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("descend"), check)) {
if (check == 1) {
// we have the descend flag specified
egg_group->set_collide_flags(EggGroup::CF_descend);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("event"), check)) {
if (check == 1) {
// we have the event flag specified
egg_group->set_collide_flags(EggGroup::CF_event);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("keep"), check)) {
if (check == 1) {
// we have the keep flag specified
egg_group->set_collide_flags(EggGroup::CF_keep);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("solid"), check)) {
if (check == 1) {
// we have the solid flag specified
egg_group->set_collide_flags(EggGroup::CF_solid);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("center"), check)) {
if (check == 1) {
// we have the center flag specified
egg_group->set_collide_flags(EggGroup::CF_center);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("turnstile"), check)) {
if (check == 1) {
// we have the turnstile flag specified
egg_group->set_collide_flags(EggGroup::CF_turnstile);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("level"), check)) {
if (check == 1) {
// we have the level flag specified
egg_group->set_collide_flags(EggGroup::CF_level);
}
}
if (node_desc->get_max_node()->GetUserPropInt(_T("intangible"), check)) {
if (check == 1) {
// we have the intangible flag specified
egg_group->set_collide_flags(EggGroup::CF_intangible);
}
}
return;
}

View File

@ -1,66 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file maxNodeTree.h
* @author crevilla
* from mayaNodeTree.h created by: drose (06Jun03)
*/
#ifndef MAXNODETREE_H
#define MAXNODETREE_H
class EggData;
class EggGroupNode;
/**
* Describes a complete tree of max nodes for conversion.
*/
class MaxNodeTree {
public:
MaxNodeTree();
MaxNodeDesc *build_node(INode *max_node);
MaxNodeDesc *build_joint(INode *max_node, MaxNodeDesc *node_joint);
bool build_complete_hierarchy(INode *root, ULONG *selection_list, int len);
MaxNodeDesc *find_node(INode *max_node);
MaxNodeDesc *find_joint(INode *max_node);
int get_num_nodes() const;
MaxNodeDesc *get_node(int n) const;
void clear_egg(EggData *egg_data, EggGroupNode *egg_root,
EggGroupNode *skeleton_node);
EggGroup *get_egg_group(MaxNodeDesc *node_desc);
EggTable *get_egg_table(MaxNodeDesc *node_desc);
EggXfmSAnim *get_egg_anim(MaxNodeDesc *node_desc);
MaxNodeDesc* _root;
PN_stdfloat _fps;
// the flag for the setting up collision bool _has_collision;
// EggGroup::CollideFlags _cf_type; EggGroup::CollisionSolidType _cs_type;
bool _export_mesh;
private:
EggData *_egg_data;
EggGroupNode *_egg_root;
EggGroupNode *_skeleton_node;
MaxNodeDesc *r_build_node(INode *max_node);
MaxNodeDesc *r_build_joint(MaxNodeDesc *node_desc, INode *max_node);
bool node_in_list(ULONG handle, ULONG *list, int len);
bool r_build_hierarchy(INode *root, ULONG *selection_list, int len);
bool is_joint(INode *node);
void set_collision_tags(MaxNodeDesc *node_desc, EggGroup *egg_group);
typedef pmap<ULONG, MaxNodeDesc *> NodesByPath;
NodesByPath _nodes_by_path;
typedef pvector<MaxNodeDesc *> Nodes;
Nodes _nodes;
};
#endif

View File

@ -1,701 +0,0 @@
/*
maxEggExpOptions.cxx
Created by Phillip Saltzman, 2/15/05
Carnegie Mellon University, Entetainment Technology Center
This file implements the classes that are used to choose
what to export from 3D Studio max
Updated by Fei Wang, Carnegie Mellon University Entertainment
Technology Center student, 14Aug2009: added enableAddCollisionChoices
*/
#include "maxEgg.h"
// Disable the forcing int to true or false performance warning
#pragma warning(disable: 4800)
void SetICustEdit(HWND wnd, int nIDDlgItem, TCHAR *text)
{
ICustEdit *edit = GetICustEdit(GetDlgItem(wnd, nIDDlgItem));
edit->SetText(text);
ReleaseICustEdit(edit);
}
void SetICustEdit(HWND wnd, int nIDDlgItem, int n)
{
TCHAR text[80];
_stprintf(text, _T("%d"), n);
ICustEdit *edit = GetICustEdit(GetDlgItem(wnd, nIDDlgItem));
edit->SetText(text);
ReleaseICustEdit(edit);
}
TCHAR *GetICustEditT(HWND wnd)
{
static TCHAR buffer[2084];
ICustEdit *edit = GetICustEdit(wnd);
edit->GetText(buffer, 2084);
ReleaseICustEdit(edit);
return buffer;
}
int GetICustEditI(HWND wnd, BOOL *valid)
{
ICustEdit *edit = GetICustEdit(wnd);
int i = edit->GetInt(valid);
ReleaseICustEdit(edit);
return i;
}
void ChunkSave(ISave *isave, int chunkid, int value)
{
ULONG nb;
isave->BeginChunk(chunkid);
isave->Write(&value, sizeof(int), &nb);
isave->EndChunk();
}
void ChunkSave(ISave *isave, int chunkid, ULONG value)
{
ULONG nb;
isave->BeginChunk(chunkid);
isave->Write(&value, sizeof(ULONG), &nb);
isave->EndChunk();
}
void ChunkSave(ISave *isave, int chunkid, bool value)
{
ULONG nb;
isave->BeginChunk(chunkid);
isave->Write(&value, sizeof(bool), &nb);
isave->EndChunk();
}
void ChunkSave(ISave *isave, int chunkid, TCHAR *value)
{
ULONG nb;
isave->BeginChunk(chunkid);
int length = _tcslen(value) + 1;
isave->Write(&length, sizeof(int), &nb);
isave->Write(value, length * sizeof(TCHAR), &nb);
isave->EndChunk();
}
TCHAR *ChunkLoadString(ILoad *iload, TCHAR *buffer, int maxLength)
{
ULONG nb;
int length;
IOResult res;
res = iload->Read(&length, sizeof(int), &nb);
assert(res == IO_OK && length <= maxLength);
res = iload->Read(buffer, length * sizeof(TCHAR), &nb);
assert(res == IO_OK);
return buffer;
}
int ChunkLoadInt(ILoad *iload)
{
ULONG nb;
int value;
IOResult res;
res = iload->Read(&value, sizeof(int), &nb);
assert(res == IO_OK);
return value;
}
int ChunkLoadULONG(ILoad *iload)
{
ULONG nb, value;
IOResult res;
res = iload->Read(&value, sizeof(ULONG), &nb);
assert(res == IO_OK);
return value;
}
bool ChunkLoadBool(ILoad *iload)
{
ULONG nb;
bool value;
IOResult res;
res = iload->Read(&value, sizeof(bool), &nb);
assert(res == IO_OK);
return value;
}
void showAnimControls(HWND hWnd, BOOL val) {
ShowWindow(GetDlgItem(hWnd, IDC_EF_LABEL), val);
ShowWindow(GetDlgItem(hWnd, IDC_EF), val);
ShowWindow(GetDlgItem(hWnd, IDC_SF_LABEL), val);
SetWindowText(GetDlgItem(hWnd, IDC_EXP_SEL_FRAMES),
val ? _T("Use Range:") : _T("Use Frame:"));
}
void enableAnimControls(HWND hWnd, BOOL val) {
EnableWindow(GetDlgItem(hWnd, IDC_SF_LABEL), val);
EnableWindow(GetDlgItem(hWnd, IDC_SF), val);
EnableWindow(GetDlgItem(hWnd, IDC_EF_LABEL), val);
EnableWindow(GetDlgItem(hWnd, IDC_EF), val);
}
void enableChooserControls(HWND hWnd, BOOL val) {
EnableWindow(GetDlgItem(hWnd, IDC_LIST_EXPORT), val);
EnableWindow(GetDlgItem(hWnd, IDC_ADD_EXPORT), val);
EnableWindow(GetDlgItem(hWnd, IDC_REMOVE_EXPORT), val);
}
#define ANIM_RAD_NONE 0
#define ANIM_RAD_EXPALL 1
#define ANIM_RAD_EXPSEL 2
#define ANIM_RAD_ALL 3
void enableAnimRadios(HWND hWnd, int mask) {
EnableWindow(GetDlgItem(hWnd, IDC_EXP_ALL_FRAMES), mask & ANIM_RAD_EXPALL);
EnableWindow(GetDlgItem(hWnd, IDC_EXP_SEL_FRAMES), mask & ANIM_RAD_EXPSEL);
}
// Handles the work of actually picking the target.
class AddNodeCB : public HitByNameDlgCallback
{
public:
MaxOptionsDialog *ph; //Pointer to the parent class
HWND hWnd; //Handle to the parent dialog
AddNodeCB (MaxOptionsDialog *instance, HWND wnd) :
ph(instance), hWnd(wnd) {}
#if MAX_VERSION_MAJOR < 15
virtual TCHAR *dialogTitle() {return _T("Objects to Export");}
virtual TCHAR *buttonText() {return _T("Select");}
#else
virtual const MCHAR *dialogTitle() {return _M("Objects to Export");}
virtual const MCHAR *buttonText() {return _M("Select");}
#endif
virtual int filter(INode *node);
virtual void proc(INodeTab &nodeTab);
};
// This tells what should be in the list Allow only triangular objects, nurbs,
// and joints
int AddNodeCB::filter(INode *node) {
if (!node) return 0;
Object *obj = node->EvalWorldState(0).obj;
Control *c = node->GetTMController();
NURBSSet getSet;
bool is_bone = (node->GetBoneNodeOnOff() || //True for bones
(c && //True for bipeds
((c->ClassID() == BIPSLAVE_CONTROL_CLASS_ID) ||
(c->ClassID() == BIPBODY_CONTROL_CLASS_ID) ||
(c->ClassID() == FOOTPRINT_CLASS_ID))));
if (IsDlgButtonChecked(hWnd, IDC_ANIMATION) == BST_CHECKED)
return is_bone && !ph->FindNode(node->GetHandle());
else
return (
is_bone || ((obj->SuperClassID() == HELPER_CLASS_ID && obj->ClassID() != MaxEggPlugin_CLASS_ID)) ||
((obj->SuperClassID() == GEOMOBJECT_CLASS_ID && //Allow geometrics
obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) ||
(obj->SuperClassID() == SHAPE_CLASS_ID && //Allow CV NURBS
obj->ClassID() == EDITABLE_SURF_CLASS_ID &&
GetNURBSSet(obj, 0, getSet, TRUE) &&
getSet.GetNURBSObject(0)->GetType() == kNCVCurve)) &&
!ph->FindNode(node->GetHandle())); //Only allow items not already selected
}
// Adds all of the selected items to the list
void AddNodeCB::proc(INodeTab &nodeTab) {
for (int i = 0; i < nodeTab.Count(); i++)
ph->AddNode(nodeTab[i]->GetHandle());
ph->RefreshNodeList(hWnd);
}
// This callback class generates a list of nodes that have previously been
// selected
class RemoveNodeCB : public HitByNameDlgCallback
{
public:
MaxOptionsDialog *ph; //Pointer to the parent class
HWND hWnd; //Handle to the parent dialog
RemoveNodeCB (MaxOptionsDialog *instance, HWND wnd) :
ph(instance), hWnd(wnd) {}
#if MAX_VERSION_MAJOR < 15
virtual TCHAR *dialogTitle() {return _T("Objects to Remove");}
virtual TCHAR *buttonText() {return _T("Remove");}
#else
virtual const MCHAR *dialogTitle() {return _M("Objects to Remove");}
virtual const MCHAR *buttonText() {return _M("Remove");}
#endif
virtual int filter(INode *node) {return (node && ph->FindNode(node->GetHandle()));}
virtual void proc(INodeTab &nodeTab);
};
// Adds all of the selected items to the list
void RemoveNodeCB::proc(INodeTab &nodeTab) {
for (int i = 0; i < nodeTab.Count(); i++)
ph->RemoveNodeByHandle(nodeTab[i]->GetHandle());
ph->RefreshNodeList(hWnd);
}
MaxEggOptions::MaxEggOptions() {
_max_interface = nullptr;
_anim_type = MaxEggOptions::AT_model;
_start_frame = INT_MIN;
_end_frame = INT_MIN;
_double_sided = false;
_file_name[0]=0;
_short_name[0]=0;
_path_replace = new PathReplace;
_path_replace->_path_store = PS_relative;
_export_whole_scene = true;
_export_all_frames = true;
_successful = false;
}
INT_PTR CALLBACK MaxOptionsDialogProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
TCHAR tempFilename[2048];
// We pass in our plugin through the lParam variable. Let's convert it
// back.
MaxOptionsDialog *imp = (MaxOptionsDialog*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
if ( !imp && message != WM_INITDIALOG ) return FALSE;
switch(message) {
case WM_INITDIALOG:
// this line is very necessary to pass the plugin as the lParam
SetWindowLongPtr(hWnd,GWLP_USERDATA,lParam);
((MaxOptionsDialog*)lParam)->UpdateUI(hWnd);
return TRUE; break;
case WM_CLOSE:
EndDialog(hWnd, FALSE);
return TRUE; break;
case WM_COMMAND:
// The modified control is found in the lower word of the wParam long.
switch( LOWORD(wParam) ) {
case IDC_MODEL:
if (HIWORD(wParam) == BN_CLICKED) {
SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
_T("Export Meshes:"));
enableAnimRadios(hWnd, ANIM_RAD_NONE);
showAnimControls(hWnd, TRUE);
enableAnimControls(hWnd, FALSE);
if (imp->_prev_type == MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
imp->_prev_type = MaxEggOptions::AT_model;
return TRUE;
}
break;
case IDC_ANIMATION:
if (HIWORD(wParam) == BN_CLICKED) {
SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
_T("Export Bones:"));
enableAnimRadios(hWnd, ANIM_RAD_ALL);
showAnimControls(hWnd, TRUE);
enableAnimControls(hWnd, IsDlgButtonChecked(hWnd, IDC_EXP_SEL_FRAMES));
if (imp->_prev_type != MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
imp->_prev_type = MaxEggOptions::AT_chan;
CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, IDC_EXP_ALL_FRAMES);
return TRUE;
}
break;
case IDC_BOTH:
if (HIWORD(wParam) == BN_CLICKED) {
SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
_T("Export Models:"));
enableAnimRadios(hWnd, ANIM_RAD_ALL);
showAnimControls(hWnd, TRUE);
enableAnimControls(hWnd, IsDlgButtonChecked(hWnd, IDC_EXP_SEL_FRAMES));
if (imp->_prev_type == MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
imp->_prev_type = MaxEggOptions::AT_both;
CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, IDC_EXP_ALL_FRAMES);
return TRUE;
}
break;
case IDC_POSE:
if (HIWORD(wParam) == BN_CLICKED) {
SetWindowText(GetDlgItem(hWnd, IDC_EXPORT_SELECTED),
_T("Export Meshes:"));
enableAnimRadios(hWnd, ANIM_RAD_EXPSEL);
showAnimControls(hWnd, FALSE);
enableAnimControls(hWnd, TRUE);
CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, IDC_EXP_SEL_FRAMES);
if (imp->_prev_type == MaxEggOptions::AT_chan) imp->ClearNodeList(hWnd);
imp->_prev_type = MaxEggOptions::AT_pose;
return TRUE;
}
break;
case IDC_EXP_ALL_FRAMES:
if (HIWORD(wParam) == BN_CLICKED) {
enableAnimControls(hWnd, FALSE);
if(imp->_prev_type == MaxEggOptions::AT_chan)
{
CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_ANIMATION);
}
if(imp->_prev_type == MaxEggOptions::AT_both)
{
CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_BOTH);
}
return TRUE;
}
break;
case IDC_EXP_SEL_FRAMES:
if (HIWORD(wParam) == BN_CLICKED) {
enableAnimControls(hWnd, TRUE);
if(imp->_prev_type == MaxEggOptions::AT_chan)
{
CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_ANIMATION);
}
if(imp->_prev_type == MaxEggOptions::AT_both)
{
CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, IDC_BOTH);
}
return TRUE;
}
break;
case IDC_EXPORT_ALL:
if (HIWORD(wParam) == BN_CLICKED) {
enableChooserControls(hWnd, FALSE);
return TRUE;
}
break;
case IDC_EXPORT_SELECTED:
if (HIWORD(wParam) == BN_CLICKED) {
enableChooserControls(hWnd, TRUE);
return TRUE;
}
break;
// deal with adding meshes
case IDC_ADD_EXPORT:
{
if (!imp->_choosing_nodes) {
AddNodeCB PickCB(imp, hWnd);
imp->_choosing_nodes = true;
imp->_max_interface->DoHitByNameDialog(&PickCB);
imp->_choosing_nodes = false;
}
}
return TRUE; break;
case IDC_REMOVE_EXPORT:
{
if (!imp->_choosing_nodes) {
imp->_choosing_nodes = true;
RemoveNodeCB PickCB(imp, hWnd);
imp->_max_interface->DoHitByNameDialog(&PickCB);
imp->_choosing_nodes = false;
}
}
return TRUE; break;
case IDC_OK:
if (imp->UpdateFromUI(hWnd)) EndDialog(hWnd, TRUE);
return TRUE; break;
case IDC_CANCEL:
EndDialog(hWnd, FALSE);
return TRUE; break;
case IDC_BROWSE:
OPENFILENAME ofn;
_tcscpy(tempFilename, GetICustEditT(GetDlgItem(hWnd, IDC_FILENAME)));
memset(&ofn, 0, sizeof(ofn));
ofn.nMaxFile = 2047;
ofn.lpstrFile = tempFilename;
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.Flags = OFN_HIDEREADONLY | OFN_NOREADONLYRETURN | OFN_PATHMUSTEXIST;
ofn.lpstrDefExt = _T("egg");
ofn.lpstrFilter = _T("Panda3D Egg Files (*.egg)\0*.egg\0All Files (*.*)\0*.*\0");
SetFocus(GetDlgItem(hWnd, IDC_FILENAME));
if (GetSaveFileName(&ofn))
SetICustEdit(hWnd, IDC_FILENAME, ofn.lpstrFile);
// else { char buf[255]; sprintf(buf, "%d",
// CommDlgExtendedError()); MessageBox(hWnd, buf, "Error on
// GetSaveFileName", MB_OK); }
return TRUE; break;
case IDC_CHECK1:
if (IsDlgButtonChecked(hWnd, IDC_CHECK1))
if (MessageBox(hWnd, _T("Warning: Exporting double-sided polygons can severely hurt ")
_T("performance in Panda3D.\n\nAre you sure you want to export them?"),
_T("Panda3D Exporter"), MB_YESNO | MB_ICONQUESTION) != IDYES)
CheckDlgButton(hWnd, IDC_CHECK1, BST_UNCHECKED);
return TRUE; break;
default:
// char buf[255]; sprintf(buf, "%d", LOWORD(wParam));
// MessageBox(hWnd, buf, "Unknown WParam", MB_OK);
break;
}
}
return FALSE;
}
void MaxOptionsDialog::SetAnimRange() {
// Get the start and end frames and the animation frame rate from Max
Interval anim_range = _max_interface->GetAnimRange();
_min_frame = anim_range.Start()/GetTicksPerFrame();
_max_frame = anim_range.End()/GetTicksPerFrame();
}
MaxOptionsDialog::MaxOptionsDialog() :
MaxEggOptions(),
_min_frame(0),
_max_frame(0),
_checked(true),
_choosing_nodes(false),
_prev_type(AT_model)
{
}
MaxOptionsDialog::~MaxOptionsDialog ()
{
}
void MaxOptionsDialog::UpdateUI(HWND hWnd) {
int typeButton = IDC_MODEL;
int anim_exp = _export_all_frames ? IDC_EXP_ALL_FRAMES : IDC_EXP_SEL_FRAMES;
int model_exp = _export_whole_scene ? IDC_EXPORT_ALL : IDC_EXPORT_SELECTED;
switch (_anim_type) {
case MaxEggOptions::AT_chan: typeButton = IDC_ANIMATION; break;
case MaxEggOptions::AT_both: typeButton = IDC_BOTH; break;
case MaxEggOptions::AT_pose: typeButton = IDC_POSE; break;
case MaxEggOptions::AT_model: typeButton = IDC_MODEL; break;
}
_prev_type = _anim_type;
CheckRadioButton(hWnd, IDC_MODEL, IDC_POSE, typeButton);
SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(typeButton, BN_CLICKED), 0);
CheckRadioButton(hWnd, IDC_EXPORT_ALL, IDC_EXPORT_SELECTED, model_exp);
SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(model_exp, BN_CLICKED), 0);
CheckRadioButton(hWnd, IDC_EXP_ALL_FRAMES, IDC_EXP_SEL_FRAMES, anim_exp);
SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(anim_exp, BN_CLICKED), 0);
CheckDlgButton(hWnd, IDC_CHECK1,
_double_sided ? BST_CHECKED : BST_UNCHECKED);
SetICustEdit(hWnd, IDC_FILENAME, _file_name);
if (_start_frame != INT_MIN) {
SetICustEdit(hWnd, IDC_SF, _start_frame);
SetICustEdit(hWnd, IDC_EF, _end_frame);
} else {
SetICustEdit(hWnd, IDC_SF, _min_frame);
SetICustEdit(hWnd, IDC_EF, _max_frame);
}
RefreshNodeList(hWnd);
}
void MaxOptionsDialog::ClearNodeList(HWND hWnd) {
_node_list.clear();
RefreshNodeList(hWnd);
}
void MaxOptionsDialog::RefreshNodeList(HWND hWnd) {
// Clear and repopulate the node box
HWND nodeLB = GetDlgItem(hWnd, IDC_LIST_EXPORT);
SendMessage(nodeLB, LB_RESETCONTENT, 0, 0);
for (int i = 0; i < _node_list.size(); i++) {
INode *temp = _max_interface->GetINodeByHandle(_node_list[i]);
const TCHAR *name = _T("Unknown Node");
if (temp) name = temp->GetName();
SendMessage(nodeLB, LB_ADDSTRING, 0, (LPARAM)name);
}
}
bool MaxOptionsDialog::UpdateFromUI(HWND hWnd) {
BOOL valid;
Anim_Type newAnimType;
int newSF = INT_MIN, newEF = INT_MIN;
TCHAR msg[1024];
if (IsDlgButtonChecked(hWnd, IDC_MODEL)) newAnimType = MaxEggOptions::AT_model;
else if (IsDlgButtonChecked(hWnd, IDC_ANIMATION)) newAnimType = MaxEggOptions::AT_chan;
else if (IsDlgButtonChecked(hWnd, IDC_BOTH)) newAnimType = MaxEggOptions::AT_both;
else newAnimType = MaxEggOptions::AT_pose;
if (newAnimType != MaxEggOptions::AT_model && IsDlgButtonChecked(hWnd, IDC_EXP_SEL_FRAMES)) {
newSF = GetICustEditI(GetDlgItem(hWnd, IDC_SF), &valid);
if (!valid) {
MessageBox(hWnd, _T("Start Frame must be an integer"), _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
return false;
}
if (newSF < _min_frame) {
_stprintf(msg, _T("Start Frame must be at least %d"), _min_frame);
MessageBox(hWnd, msg, _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
return false;
}
if (newSF > _max_frame) {
_stprintf(msg, _T("Start Frame must be at most %d"), _max_frame);
MessageBox(hWnd, msg, _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
return false;
}
if (newAnimType != MaxEggOptions::AT_pose) {
newEF = GetICustEditI(GetDlgItem(hWnd, IDC_EF), &valid);
if (!valid) {
MessageBox(hWnd, _T("End Frame must be an integer"), _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
return false;
}
if (newEF > _max_frame) {
_stprintf(msg, _T("End Frame must be at most %d"), _max_frame);
MessageBox(hWnd, msg, _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
return false;
}
if (newEF < newSF) {
MessageBox(hWnd, _T("End Frame must be greater than the start frame"), _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
return false;
}
}
}
TCHAR *temp = GetICustEditT(GetDlgItem(hWnd, IDC_FILENAME));
if (!_tcslen(temp)) {
MessageBox(hWnd, _T("The filename cannot be empty"), _T("Invalid Value"), MB_OK | MB_ICONEXCLAMATION);
return false;
}
if (_tcslen(temp) < 4 || _tcsncmp(_T(".egg"), temp+(_tcslen(temp) - 4), 4)) {
_stprintf(_file_name, _T("%s.egg"), temp);
} else {
_tcscpy(_file_name, temp);
}
temp = _tcsrchr(_file_name, '\\');
if (!temp) temp = _file_name;
else temp++;
if (_tcslen(temp) > sizeof(_short_name))
_stprintf(_short_name, _T("%.*s..."), sizeof(_short_name)-4, temp);
else {
_tcscpy(_short_name, temp);
_short_name[_tcslen(_short_name) - 4] = 0; //Cut off the .egg
}
_start_frame = newSF;
_end_frame = newEF;
_anim_type = newAnimType;
_double_sided = IsDlgButtonChecked(hWnd, IDC_CHECK1);
_export_whole_scene = IsDlgButtonChecked(hWnd, IDC_EXPORT_ALL);
_export_all_frames = IsDlgButtonChecked(hWnd, IDC_EXP_ALL_FRAMES);
return true;
}
bool MaxOptionsDialog::FindNode(ULONG INodeHandle) {
for (int i = 0; i < _node_list.size(); i++)
if (_node_list[i] == INodeHandle) return true;
return false;
}
void MaxOptionsDialog::AddNode(ULONG INodeHandle) {
if (FindNode(INodeHandle)) return;
_node_list.push_back(INodeHandle);
}
void MaxOptionsDialog::CullBadNodes() {
if (!_max_interface) return;
std::vector<ULONG> good;
for (int i=0; i<_node_list.size(); i++) {
ULONG handle = _node_list[i];
if (_max_interface->GetINodeByHandle(handle)) {
good.push_back(handle);
}
}
_node_list = good;
}
void MaxOptionsDialog::RemoveNode(int i) {
if (i >= 0 && i < _node_list.size()) {
for (int j = i+1; j < _node_list.size(); j++)
_node_list[i++] = _node_list[j++];
_node_list.pop_back();
}
}
void MaxOptionsDialog::RemoveNodeByHandle(ULONG INodeHandle) {
for (int i = 0; i < _node_list.size(); i++) {
if (_node_list[i] == INodeHandle) {
RemoveNode(i);
return;
}
}
}
IOResult MaxOptionsDialog::Save(ISave *isave) {
isave->BeginChunk(CHUNK_EGG_EXP_OPTIONS);
ChunkSave(isave, CHUNK_ANIM_TYPE, _anim_type);
ChunkSave(isave, CHUNK_FILENAME, _file_name);
ChunkSave(isave, CHUNK_SHORTNAME, _short_name);
ChunkSave(isave, CHUNK_SF, _start_frame);
ChunkSave(isave, CHUNK_EF, _end_frame);
ChunkSave(isave, CHUNK_DBL_SIDED, _double_sided);
ChunkSave(isave, CHUNK_EGG_CHECKED, _checked);
ChunkSave(isave, CHUNK_ALL_FRAMES, _export_all_frames);
ChunkSave(isave, CHUNK_EXPORT_FULL, _export_whole_scene);
isave->BeginChunk(CHUNK_NODE_LIST);
for (int i = 0; i < _node_list.size(); i++)
ChunkSave(isave, CHUNK_NODE_HANDLE, _node_list[i]);
isave->EndChunk();
isave->EndChunk();
return IO_OK;
}
IOResult MaxOptionsDialog::Load(ILoad *iload) {
IOResult res = iload->OpenChunk();
while (res == IO_OK) {
switch(iload->CurChunkID()) {
case CHUNK_ANIM_TYPE: _anim_type = (Anim_Type)ChunkLoadInt(iload); break;
case CHUNK_FILENAME: ChunkLoadString(iload, _file_name, sizeof(_file_name)); break;
case CHUNK_SHORTNAME: ChunkLoadString(iload, _short_name, sizeof(_short_name)); break;
case CHUNK_SF: _start_frame = ChunkLoadInt(iload); break;
case CHUNK_EF: _end_frame = ChunkLoadInt(iload); break;
case CHUNK_DBL_SIDED: _double_sided = ChunkLoadBool(iload); break;
case CHUNK_EGG_CHECKED: _checked = ChunkLoadBool(iload); break;
case CHUNK_ALL_FRAMES: _export_all_frames = ChunkLoadBool(iload); break;
case CHUNK_EXPORT_FULL: _export_whole_scene = ChunkLoadBool(iload); break;
case CHUNK_NODE_LIST:
res = iload->OpenChunk();
while (res == IO_OK) {
if (iload->CurChunkID() == CHUNK_NODE_HANDLE) AddNode(ChunkLoadULONG(iload));
iload->CloseChunk();
res = iload->OpenChunk();
}
break;
}
iload->CloseChunk();
res = iload->OpenChunk();
}
if (res == IO_END) return IO_OK;
return IO_ERROR;
}

View File

@ -1,112 +0,0 @@
/*
maxEggExpOptions.h
Created by Phillip Saltzman, 2/15/05
Carnegie Mellon University, Entetainment Technology Center
This file contains a class that allows users to specify
export options, and then execute the export
*/
#ifndef __maxEggExpOptions__H
#define __maxEggExpOptions__H
#include "pathReplace.h"
#pragma conform(forScope, off)
/* Externed Globals */
extern HINSTANCE hInstance;
// Saveload chunk definitions
#define CHUNK_OVERWRITE_FLAG 0x1000
#define CHUNK_PVIEW_FLAG 0x1001
#define CHUNK_LOG_OUTPUT 0x1002
#define CHUNK_EGG_EXP_OPTIONS 0x1100
#define CHUNK_ANIM_TYPE 0x1101
#define CHUNK_EGG_CHECKED 0x1102
#define CHUNK_DBL_SIDED 0x1103
#define CHUNK_SF 0x1104
#define CHUNK_EF 0x1105
#define CHUNK_FILENAME 0x1106
#define CHUNK_SHORTNAME 0x1107
#define CHUNK_EXPORT_FULL 0x1108
#define CHUNK_ALL_FRAMES 0x1109
#define CHUNK_NODE_LIST 0x1200
#define CHUNK_NODE_HANDLE 0x1201
// #define CHUNK_ADD_COLLISION 0x1202 #define CHUNK_CS_TYPE 0x1203
// #define CHUNK_CF_TYPE 0x1204
// Global functions
void ChunkSave(ISave *isave, int chunkid, int value);
void ChunkSave(ISave *isave, int chunkid, bool value);
void ChunkSave(ISave *isave, int chunkid, char *value);
TCHAR *ChunkLoadString(ILoad *iload, TCHAR *buffer, int maxLength);
int ChunkLoadInt(ILoad *iload);
bool ChunkLoadBool(ILoad *iload);
void SetICustEdit(HWND wnd, int nIDDlgItem, TCHAR *text);
INT_PTR CALLBACK MaxOptionsDialogProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam );
struct MaxEggOptions
{
MaxEggOptions();
enum Anim_Type {
AT_none,
AT_model,
AT_chan,
AT_pose,
AT_strobe,
AT_both
};
IObjParam *_max_interface;
Anim_Type _anim_type;
int _start_frame;
int _end_frame;
bool _double_sided;
bool _successful;
bool _export_whole_scene;
bool _export_all_frames;
TCHAR _file_name[2048];
TCHAR _short_name[256];
PT(PathReplace) _path_replace;
std::vector<ULONG> _node_list;
};
class MaxOptionsDialog : public MaxEggOptions
{
friend class MaxEggPlugin;
public:
int _min_frame, _max_frame;
bool _checked;
bool _choosing_nodes;
MaxEggOptions::Anim_Type _prev_type;
MaxOptionsDialog();
~MaxOptionsDialog();
// All these List functions should probably take what list they need to
// operate on rather than just operating on a global list
void SetMaxInterface(IObjParam *iface) { _max_interface = iface; }
void UpdateUI(HWND hWnd);
bool UpdateFromUI(HWND hWnd);
void RefreshNodeList(HWND hWnd);
void SetAnimRange();
bool FindNode(ULONG INodeHandle); //returns true if the node is already in the list
void AddNode(ULONG INodeHandle);
void RemoveNode(int i);
void RemoveNodeByHandle(ULONG INodeHandle);
void ClearNodeList(HWND hWnd);
void CullBadNodes();
ULONG GetNode(int i) { return (i >= 0 && i < _node_list.size()) ? _node_list[i] : ULONG_MAX; }
IOResult Load(ILoad *iload);
IOResult Save(ISave *isave);
};
#endif // __MaxEggExpOptions__H

View File

@ -1,53 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by maxEgg.rc
//
#define IDS_LIBDESCRIPTION 1
#define IDS_CATEGORY 2
#define IDS_CLASS_NAME 3
#define IDS_PARAMS 4
#define IDS_SPIN 5
#define IDD_PANEL 101
#define IDD_EGG_DETAILS 102
#define IDC_EGGS_LABEL 1019
#define IDC_ADD_EGG 1021
#define IDC_EDIT_EGG 1022
#define IDC_REMOVE_EGG 1023
#define IDC_LIST_EGGS 1024
#define IDC_OVERWRITE_CHECK 1027
#define IDC_EXPORT 1028
#define IDC_PANEL_TITLE 1029
#define IDC_OVERWRITE_CHECK2 1030
#define IDC_PVIEW_CHECK 1030
#define IDC_MODEL 1033
#define IDC_ANIMATION 1034
#define IDC_BOTH 1035
#define IDC_POSE 1036
#define IDC_FILENAME 1038
#define IDC_BROWSE 1039
#define IDC_EXPORT_ALL 1040
#define IDC_EXPORT_SELECTED 1041
#define IDC_ADD_EXPORT 1043
#define IDC_LIST_EXPORT 1044
#define IDC_REMOVE_EXPORT 1046
#define IDC_EXP_ALL_FRAMES 1049
#define IDC_EXP_SEL_FRAMES 1050
#define IDC_SF 1051
#define IDC_SF_LABEL 1052
#define IDC_EF 1053
#define IDC_CHECK1 1054
#define IDC_EF_LABEL 1057
#define IDC_OK 1058
#define IDC_CANCEL 1059
#define IDC_LOGGING 1060
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1080
#define _APS_NEXT_SYMED_VALUE 102
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,111 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file maxToEggConverter.h
* @author Corey Revilla and Ken Strickland
* @date 2003-06-22
* from mayaToEggConverter.cxx created by drose (10Nov99)
*/
#ifndef __maxToEggConverter__H
#define __maxToEggConverter__H
#pragma conform(forScope, off)
/* Error-Reporting Includes
*/
#define MTEC Logger::ST_MAP_ME_TO_APP_SPECIFIC_SYSTEM4
/* Helpful Defintions and Casts
*/
#define null 0
#define PHYSIQUE_CLASSID Class_ID(PHYSIQUE_CLASS_ID_A, PHYSIQUE_CLASS_ID_B)
/* External Helper Functions for UI
*/
// *** Figure out why this is causing link errors DWORD WINAPI
// ProgressBarFunction(LPVOID arg);
/**
* This class supervises the construction of an EggData structure from a Max
* model
*/
class MaxToEggConverter {
public:
MaxToEggConverter();
~MaxToEggConverter();
bool convert(MaxEggOptions *options);
private:
struct PandaMaterial {
std::vector<PT(EggTexture)> _texture_list;
LColor _color;
std::vector<int> _map_channels;
bool _any_diffuse;
bool _any_opacity;
bool _any_gloss;
bool _any_normal;
};
typedef std::map<Mtl*,PandaMaterial> MaterialMap;
MaxEggOptions *_options;
int _current_frame;
PT(EggData) _egg_data;
std::string _program_name;
MaxNodeTree _tree;
int _cur_tref;
EggTextureCollection _textures;
MaterialMap _material_map;
void reset();
bool convert_char_model();
bool convert_char_chan(double start_frame, double end_frame,
double frame_inc, double output_frame_rate);
bool convert_hierarchy(EggGroupNode *egg_root);
bool process_model_node(MaxNodeDesc *node_desc);
void get_transform(INode *max_node, EggGroup *egg_group);
LMatrix4d get_object_transform(INode *max_node);
void get_joint_transform(INode *max_node, EggGroup *egg_group);
void get_joint_transform(INode *max_node, INode *parent_node,
EggGroup *egg_group);
bool make_nurbs_curve(INode *max_node, NURBSCVCurve *curve,
TimeValue time, EggGroup *egg_group);
void make_polyset(INode *max_node,
Mesh *mesh,
EggGroup *egg_group,
Shader *default_shader = nullptr);
Point3 get_max_vertex_normal(Mesh *mesh, int faceNo, int vertNo);
VertColor get_max_vertex_color(Mesh *mesh, int FaceNo, int VertexNo);
VertColor get_max_vertex_color(Mesh *mesh,int FaceNo,int VertexNo, int channel);
UVVert get_max_vertex_texcoord(Mesh *mesh, int faceNo, int vertNo, int channel);
void get_vertex_weights(INode *max_node, EggVertexPool *vpool);
const PandaMaterial &get_panda_material(Mtl *mtl, MtlID id);
void analyze_diffuse_maps(PandaMaterial &pandaMat, Texmap *m);
void analyze_opacity_maps(PandaMaterial &pandaMat, Texmap *m);
void analyze_gloss_maps(PandaMaterial &pandaMat, Texmap *m);
void analyze_glow_maps(PandaMaterial &pandaMat, Texmap *m);
void analyze_normal_maps(PandaMaterial &pandaMat, Texmap *m);
void add_map_channel(PandaMaterial &pandaMat, int channel);
void apply_texture_properties(EggTexture &tex, int channel);
std::string generate_tex_name();
std::string get_uv_name(int n);
bool reparent_decals(EggGroupNode *egg_parent);
public:
Modifier* FindSkinModifier (INode* node, const Class_ID &type);
};
#endif

View File

@ -1,6 +0,0 @@
#include "maxNodeDesc.cxx"
#include "maxNodeTree.cxx"
#include "maxOptionsDialog.cxx"
#include "maxToEggConverter.cxx"
#include "maxEgg.cxx"

View File

@ -1,277 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file maxEggImport.cxx
* @author jyelon
* @date 2005-07-15
*
* This is the wrapper code for the max importer plugin.
* It includes:
*
* - user interface dialogs and popups
* - plugin initialization/registration
*
* It does not include the actual code to traverse the EggData.
*/
// Include this before everything
#include "pandatoolbase.h"
using std::min;
using std::max;
// local includes
#include "maxEggLoader.h"
#include "maxImportRes.h"
// MAX includes
#include <Max.h>
#include <istdplug.h>
// panda includes.
#include "notifyCategoryProxy.h"
#include <iostream>
#include <sstream>
class MaxEggImporter : public SceneImport
{
public:
// GUI-related methods
MaxEggImporter();
~MaxEggImporter();
int ExtCount(); // Number of extensions supported
const TCHAR * Ext(int n); // Extension #n (i.e. "EGG")
const TCHAR * LongDesc(); // Long ASCII description (i.e. "Egg Importer")
const TCHAR * ShortDesc(); // Short ASCII description (i.e. "Egg")
const TCHAR * AuthorName(); // ASCII Author name
const TCHAR * CopyrightMessage();// ASCII Copyright message
const TCHAR * OtherMessage1(); // Other message #1
const TCHAR * OtherMessage2(); // Other message #2
unsigned int Version(); // Version number * 100 (i.e. v3.01 = 301)
void ShowAbout(HWND hWnd); // Show DLL's "About..." box
int DoImport(const TCHAR *name,ImpInterface *ei,Interface *i, BOOL suppressPrompts);
public:
// GUI-related fields
static BOOL _merge;
static BOOL _importmodel;
static BOOL _importanim;
};
BOOL MaxEggImporter::_merge = TRUE;
BOOL MaxEggImporter::_importmodel = TRUE;
BOOL MaxEggImporter::_importanim = FALSE;
MaxEggImporter::MaxEggImporter()
{
}
MaxEggImporter::~MaxEggImporter()
{
}
int MaxEggImporter::ExtCount()
{
// Number of different extensions handled by this importer.
return 1;
}
const TCHAR * MaxEggImporter::Ext(int n)
{
// Fetch the extensions handled by this importer.
switch(n) {
case 0: return _T("egg");
default: return _T("");
}
}
const TCHAR * MaxEggImporter::LongDesc()
{
return _T("Panda3D Egg Importer");
}
const TCHAR * MaxEggImporter::ShortDesc()
{
return _T("Panda3D Egg");
}
const TCHAR * MaxEggImporter::AuthorName()
{
return _T("Joshua Yelon");
}
const TCHAR * MaxEggImporter::CopyrightMessage()
{
return _T("Copyight (c) 2005 Josh Yelon");
}
const TCHAR * MaxEggImporter::OtherMessage1()
{
return _T("");
}
const TCHAR * MaxEggImporter::OtherMessage2()
{
return _T("");
}
unsigned int MaxEggImporter::Version()
{
return 100;
}
static INT_PTR CALLBACK AboutBoxDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_INITDIALOG:
CenterWindow(hWnd, GetParent(hWnd));
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
EndDialog(hWnd, 1);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
void MaxEggImporter::ShowAbout(HWND hWnd)
{
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ABOUTBOX),
hWnd, AboutBoxDlgProc, 0);
}
static INT_PTR CALLBACK ImportDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
MaxEggImporter *imp = (MaxEggImporter*) GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch (msg) {
case WM_INITDIALOG:
imp = (MaxEggImporter*)lParam;
SetWindowLongPtr(hWnd, GWLP_USERDATA, lParam);
CenterWindow(hWnd, GetParent(hWnd));
CheckDlgButton(hWnd, IDC_MERGE, imp->_merge);
CheckDlgButton(hWnd, IDC_IMPORTMODEL, imp->_importmodel);
CheckDlgButton(hWnd, IDC_IMPORTANIM, imp->_importanim);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
imp->_merge = IsDlgButtonChecked(hWnd, IDC_MERGE);
imp->_importmodel = IsDlgButtonChecked(hWnd, IDC_IMPORTMODEL);
imp->_importanim = IsDlgButtonChecked(hWnd, IDC_IMPORTANIM);
EndDialog(hWnd, 1);
break;
case IDCANCEL:
EndDialog(hWnd, 0);
break;
}
break;
default:
return FALSE;
}
return TRUE;
}
int MaxEggImporter::
DoImport(const TCHAR *name, ImpInterface *ii, Interface *i, BOOL suppressPrompts) {
// Prompt the user with our dialogbox.
if (!DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_IMPORT_DLG),
i->GetMAXHWnd(), ImportDlgProc, (LPARAM)this)) {
return 1;
}
std::ostringstream log;
Notify::ptr()->set_ostream_ptr(&log, false);
#ifdef _UNICODE
char sname[2048];
sname[2047] = 0;
wcstombs(sname, name, 2047);
bool ok = MaxLoadEggFile(sname, _merge ? true:false, _importmodel ? true:false, _importanim ? true:false);
#else
bool ok = MaxLoadEggFile(name, _merge ? true:false, _importmodel ? true:false, _importanim ? true:false);
#endif
std::string txt = log.str();
if (txt != "") {
MessageBoxA(nullptr, txt.c_str(), "Panda3D Importer", MB_OK);
} else if (!ok) {
MessageBoxA(nullptr, "Import Failed, unknown reason\n", "Panda3D Importer", MB_OK);
}
Notify::ptr()->set_ostream_ptr(nullptr, false);
return 1;
}
// Plugin Initialization The following code enables Max to load this DLL, get
// a list of the classes defined in this DLL, and provides a means for Max to
// create instances of those classes.
HINSTANCE hInstance;
BOOL WINAPI DllMain(HINSTANCE hinstDLL,ULONG fdwReason,LPVOID lpvReserved) {
static int controlsInit = FALSE;
hInstance = hinstDLL;
if (!controlsInit) {
controlsInit = TRUE;
// It appears that InitCustomControls is deprecated in 2012. I'm not sure
// if we can just remove it like this, but I've heard that it seems to
// work, so let's do it like this.
#if MAX_VERSION_MAJOR < 14
InitCustomControls(hInstance);
#endif
InitCommonControls();
}
return (TRUE);
}
#define PANDAEGGIMP_CLASS_ID1 0x377193ab
#define PANDAEGGIMP_CLASS_ID2 0x897afe12
class MaxEggImporterClassDesc: public ClassDesc {
public:
int IsPublic() {return 1;}
void *Create(BOOL loading = FALSE) {return new MaxEggImporter;}
const TCHAR *ClassName() {return _T("MaxEggImporter");}
SClass_ID SuperClassID() {return SCENE_IMPORT_CLASS_ID;}
Class_ID ClassID() {return Class_ID(PANDAEGGIMP_CLASS_ID1,PANDAEGGIMP_CLASS_ID2);}
const TCHAR *Category() {return _T("Chrutilities");}
};
static MaxEggImporterClassDesc MaxEggImporterDesc;
__declspec( dllexport ) const TCHAR* LibDescription()
{
return _T("Panda3D Egg Importer");
}
__declspec( dllexport ) int LibNumberClasses()
{
return 1;
}
__declspec( dllexport ) ClassDesc* LibClassDesc(int i)
{
switch(i) {
case 0: return &MaxEggImporterDesc;
default: return 0;
}
}
__declspec( dllexport ) ULONG LibVersion()
{
return VERSION_3DSMAX;
}

View File

@ -1,7 +0,0 @@
EXPORTS
LibDescription @1
LibNumberClasses @2
LibClassDesc @3
LibVersion @4
SECTIONS
.data READ WRITE

View File

@ -1,21 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by maxImportRes.rc
//
#define IDD_PANEL 101
#define IDD_ABOUTBOX 102
#define IDD_IMPORT_DLG 103
#define IDC_MERGE 1002
#define IDC_IMPORTMODEL 1003
#define IDC_IMPORTANIM 1004
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1020
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -1,122 +0,0 @@
// Microsoft Visual C++ generated resource script.
//
#include "maxImportRes.h"
#define APSTUDIO_READONLY_SYMBOLS
////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "WinResrc.h"
#define IDC_STATIC -1
////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 176
TOPMARGIN, 7
BOTTOMMARGIN, 60
END
IDD_IMPORT_DLG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 187
TOPMARGIN, 7
BOTTOMMARGIN, 71
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"maxImportRes.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOGEX 0, 0, 183, 67
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Panda3D Egg Importer"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,66,45,50,14
CTEXT "Panda3D Egg Importer\n\nCarnegie Mellon\nEntertainment Technology Center",
IDC_STATIC,7,7,169,36
END
IDD_IMPORT_DLG DIALOGEX 0, 0, 194, 78
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Panda3D Egg Import"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,137,10,50,14
PUSHBUTTON "Cancel",IDCANCEL,137,30,50,14
CONTROL "Merge with Current Scene",IDC_MERGE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,15,20,106,10
GROUPBOX "Input Options",IDC_STATIC,5,7,126,64
CONTROL "Import Model",IDC_IMPORTMODEL,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,15,41,73,10
CONTROL "Import Animation",IDC_IMPORTANIM,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,15,54,73,10
END
#endif // English (U.S.) resources
////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED