Skip to content
Browse files

Added phys sky to appleseed. Added new renderer kray.

Signed-off-by: haggi <git@haggi.de>
  • Loading branch information...
1 parent 04cda6d commit 9366edbb41f67c3b6764c03e60d15dbe13826dc8 haggi committed Dec 23, 2012
Showing with 5,082 additions and 24 deletions.
  1. +1 −1 .gitignore
  2. +14 −0 src/common/cpp/mayarendernodes/renderGlobalsNode.cpp
  3. +5 −0 src/common/cpp/mayarendernodes/renderGlobalsNode.h
  4. +1 −1 src/mayaToAppleseed/devkit/.gitignore
  5. BIN src/mayaToAppleseed/mtap_devmodule/bin/appleseed.dll
  6. BIN src/mayaToAppleseed/mtap_devmodule/bin/appleseed.shared.dll
  7. BIN src/mayaToAppleseed/mtap_devmodule/plug-ins/mayatoappleseed.mll
  8. +57 −20 src/mayaToAppleseed/mtap_devmodule/scripts/mtap_initialize.py
  9. +30 −0 src/mayaToAppleseed/src/appleseed/appleseed.cpp
  10. +31 −1 src/mayaToAppleseed/src/mtap_common/mtap_renderGlobals.cpp
  11. +11 −0 src/mayaToAppleseed/src/mtap_common/mtap_renderGlobals.h
  12. +43 −1 src/mayaToAppleseed/src/mtap_common/mtap_renderGlobalsNode.cpp
  13. +13 −0 src/mayaToAppleseed/src/mtap_common/mtap_renderGlobalsNode.h
  14. +18 −0 src/mayaToKray/.gitignore
  15. +5 −0 src/mayaToKray/deployment/mayaToKray/mayaToKray.mod
  16. BIN src/mayaToKray/mtkr_devmodule/bin/kray.dll_
  17. BIN src/mayaToKray/mtkr_devmodule/bin/kray3l_32.exe
  18. BIN src/mayaToKray/mtkr_devmodule/bin/kray3l_64.exe
  19. BIN src/mayaToKray/mtkr_devmodule/bin/kray3rsrc.ka
  20. +5 −0 src/mayaToKray/mtkr_devmodule/mayaToKray.mod
  21. BIN src/mayaToKray/mtkr_devmodule/plug-ins/mayaToKray.mll
  22. +91 −0 src/mayaToKray/mtkr_devmodule/ressources/_Renderer.xml
  23. +17 −0 src/mayaToKray/mtkr_devmodule/scripts/.project
  24. +34 −0 src/mayaToKray/mtkr_devmodule/scripts/AETemplates/AEkrayNodeTemplate.py
  25. 0 src/mayaToKray/mtkr_devmodule/scripts/AETemplates/__init__.py
  26. +227 −0 src/mayaToKray/mtkr_devmodule/scripts/asutils.py
  27. +281 −0 src/mayaToKray/mtkr_devmodule/scripts/mtkr_initialize.py
  28. +99 −0 src/mayaToKray/mtkr_devmodule/scripts/optimizeTextures.py
  29. +1,054 −0 src/mayaToKray/mtkr_devmodule/scripts/path.py
  30. +177 −0 src/mayaToKray/src/kray/krayEventListener.cpp
  31. +37 −0 src/mayaToKray/src/kray/krayEventListener.h
  32. +138 −0 src/mayaToKray/src/kray/krayGeometry.cpp
  33. +13 −0 src/mayaToKray/src/kray/krayGeometry.h
  34. 0 src/mayaToKray/src/kray/krayLights.cpp
  35. 0 src/mayaToKray/src/kray/krayLights.h
  36. 0 src/mayaToKray/src/kray/krayMaterials.cpp
  37. 0 src/mayaToKray/src/kray/krayMaterials.h
  38. +99 −0 src/mayaToKray/src/kray/krayRenderer.cpp
  39. +39 −0 src/mayaToKray/src/kray/krayRenderer.h
  40. +56 −0 src/mayaToKray/src/kray/krayTestScene.cpp
  41. +15 −0 src/mayaToKray/src/kray/krayTestScene.h
  42. +125 −0 src/mayaToKray/src/mayatokray.cpp
  43. +24 −0 src/mayaToKray/src/mayatokray.h
  44. +103 −0 src/mayaToKray/src/mtkr_common/mtkr_mayaObject.cpp
  45. +32 −0 src/mayaToKray/src/mtkr_common/mtkr_mayaObject.h
  46. +341 −0 src/mayaToKray/src/mtkr_common/mtkr_mayaScene.cpp
  47. +50 −0 src/mayaToKray/src/mtkr_common/mtkr_mayaScene.h
  48. +206 −0 src/mayaToKray/src/mtkr_common/mtkr_renderGlobals.cpp
  49. +55 −0 src/mayaToKray/src/mtkr_common/mtkr_renderGlobals.h
  50. +395 −0 src/mayaToKray/src/mtkr_common/mtkr_renderGlobalsNode.cpp
  51. +117 −0 src/mayaToKray/src/mtkr_common/mtkr_renderGlobalsNode.h
  52. +78 −0 src/mayaToKray/src/pluginMain.cpp
  53. BIN src/mayaToKray/tests/apple_test.exr
  54. +301 −0 src/mayaToKray/tests/apple_test.ma
  55. +21 −0 src/mayaToKray/vs2010/.gitignore
  56. +38 −0 src/mayaToKray/vs2010/mayaToKray.sln
  57. +347 −0 src/mayaToKray/vs2010/mayaToKray.vcxproj
  58. +230 −0 src/mayaToKray/vs2010/mayaToKray.vcxproj.filters
  59. +8 −0 src/mayaToKray/vs2010/mayaToKray.vcxproj.user
  60. 0 src/mayaToKray/vs2010/sourceCodeDocs/assemblyWorkflow.txt
View
2 .gitignore
@@ -22,4 +22,4 @@
*pydevproject
src/mayaToMitsuba
src/mayaToLux
-src/mayaToKray
+src/mayaToNox
View
14 src/common/cpp/mayarendernodes/renderGlobalsNode.cpp
@@ -38,6 +38,10 @@ MObject MayaRenderGlobalsNode::basePath;
MObject MayaRenderGlobalsNode::imagePath;
MObject MayaRenderGlobalsNode::maxTraceDepth;
+MObject MayaRenderGlobalsNode::exportSceneFile;
+MObject MayaRenderGlobalsNode::exportSceneFileName;
+MObject MayaRenderGlobalsNode::sceneScale;
+
MayaRenderGlobalsNode::MayaRenderGlobalsNode()
{
@@ -60,6 +64,16 @@ MStatus MayaRenderGlobalsNode::initialize()
MFnEnumAttribute eAttr;
MStatus stat = MStatus::kSuccess;
+ sceneScale = nAttr.create("sceneScale", "sceneScale", MFnNumericData::kFloat, 1.0f);
+ CHECK_MSTATUS(addAttribute( sceneScale ));
+
+ exportSceneFile = nAttr.create("exportSceneFile", "exportSceneFile", MFnNumericData::kBoolean, false);
+ CHECK_MSTATUS(addAttribute( exportSceneFile ));
+
+ exportSceneFileName = tAttr.create("exportSceneFileName", "exportSceneFileName", MFnNumericData::kString);
+ tAttr.setUsedAsFilename(true);
+ CHECK_MSTATUS(addAttribute( exportSceneFileName ));
+
// sampling adaptive
minSamples = nAttr.create("minSamples", "minSamples", MFnNumericData::kInt, 1);
CHECK_MSTATUS(addAttribute( minSamples ));
View
5 src/common/cpp/mayarendernodes/renderGlobalsNode.h
@@ -54,6 +54,11 @@ class MayaRenderGlobalsNode : public MPxNode
// raytracing
static MObject maxTraceDepth;
+ static MObject exportSceneFile;
+ static MObject exportSceneFileName;
+ static MObject sceneScale;
+
+
};
View
2 src/mayaToAppleseed/devkit/.gitignore
@@ -15,4 +15,4 @@
*devkit.zip
*devkit_win64*
-
+data
View
BIN src/mayaToAppleseed/mtap_devmodule/bin/appleseed.dll
Binary file not shown.
View
BIN src/mayaToAppleseed/mtap_devmodule/bin/appleseed.shared.dll
Binary file not shown.
View
BIN src/mayaToAppleseed/mtap_devmodule/plug-ins/mayatoappleseed.mll
Binary file not shown.
View
77 src/mayaToAppleseed/mtap_devmodule/scripts/mtap_initialize.py
@@ -49,6 +49,7 @@ def updateTest(self, dummy = None):
def addUserTabs(self):
pm.renderer(self.rendererName, edit=True, addGlobalsTab=self.renderTabMelProcedure("AOVs"))
+ pm.renderer(self.rendererName, edit=True, addGlobalsTab=self.renderTabMelProcedure("Environment"))
def updateEnvironment(self, dummy=None):
envDict = self.rendererTabUiDict['environment']
@@ -75,6 +76,62 @@ def updateEnvironment(self, dummy=None):
envDict['gradientZenit'].setEnable(False)
envDict['environmentMap'].setEnable(True)
+ def AppleseedEnvironmentCreateTab(self):
+ log.debug("AppleseedEnvironmentCreateTab()")
+ self.createGlobalsNode()
+ parentForm = pm.setParent(query = True)
+ pm.setUITemplate("attributeEditorTemplate", pushTemplate = True)
+ scLo = self.rendererName + "AOScrollLayout"
+ with pm.scrollLayout(scLo, horizontalScrollBarThickness = 0):
+ with pm.columnLayout(self.rendererName + "ColumnLayout", adjustableColumn = True, width = 400):
+ with pm.frameLayout(label="Environment Lighting", collapsable = False):
+ envDict = {}
+ self.rendererTabUiDict['environment'] = envDict
+ attr = pm.Attribute(self.renderGlobalsNodeName + ".environmentType")
+ ui = pm.attrEnumOptionMenu(label = "Environemnt Type", cc=self.updateEnvironment, at=self.renderGlobalsNodeName + ".environmentType", ei = self.getEnumList(attr))
+ #modify via script job
+
+ with pm.frameLayout(label="Environment Colors", collapsable = False):
+ ui = pm.floatFieldGrp(label="Environemnt Intensity:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(ui, self.renderGlobalsNodeName + ".environmentIntensity", index = 2 )
+ envDict['environmentColor'] = pm.attrColorSliderGrp(label = "Environment Color", at=self.renderGlobalsNodeName + ".environmentColor")
+ envDict['gradientHorizon'] = pm.attrColorSliderGrp(label = "Gradient Horizon", at=self.renderGlobalsNodeName + ".gradientHorizon")
+ envDict['gradientZenit'] = pm.attrColorSliderGrp(label = "Gradient Zenit", at=self.renderGlobalsNodeName + ".gradientZenit")
+ envDict['environmentMap'] = pm.attrColorSliderGrp(label = "Environment Map", at=self.renderGlobalsNodeName + ".environmentMap")
+ envDict['latLongHShift'] = pm.floatFieldGrp(label="LatLong Horiz Shift:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['latLongHShift'], self.renderGlobalsNodeName + ".latlongHoShift", index = 2 )
+ envDict['latLongVShift'] = pm.floatFieldGrp(label="LatLong Vertical Shift:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['latLongVShift'], self.renderGlobalsNodeName + ".latlongVeShift", index = 2 )
+
+ with pm.frameLayout(label="Physical Sky", collapsable = False):
+ attr = pm.Attribute(self.renderGlobalsNodeName + ".skyModel")
+ envDict['pskModel'] = pm.attrEnumOptionMenu(label = "Sky Model", cc=self.updateEnvironment, at=self.renderGlobalsNodeName + ".skyModel", ei = self.getEnumList(attr))
+ envDict['pskGrAlbedo'] = pm.floatFieldGrp(label="Ground Albedo:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['pskGrAlbedo'], self.renderGlobalsNodeName + ".ground_albedo", index = 2 )
+ envDict['pskGrHShit'] = pm.floatFieldGrp(label="Horizon Shift:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['pskGrHShit'], self.renderGlobalsNodeName + ".horizon_shift", index = 2 )
+ envDict['pskLumMulti'] = pm.floatFieldGrp(label="Luminance Multiplier:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['pskLumMulti'], self.renderGlobalsNodeName + ".luminance_multiplier", index = 2 )
+ envDict['pskSatMulti'] = pm.floatFieldGrp(label="Saturation Multiplier:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['pskSatMulti'], self.renderGlobalsNodeName + ".saturation_multiplier", index = 2 )
+ envDict['pskSunAzi'] = pm.floatFieldGrp(label="Sun Azimut:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['pskSunAzi'], self.renderGlobalsNodeName + ".sun_phi", index = 2 )
+ envDict['pskSunEle'] = pm.floatFieldGrp(label="Sun Elevation:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['pskSunEle'], self.renderGlobalsNodeName + ".sun_theta", index = 2 )
+ envDict['pskTurb'] = pm.floatFieldGrp(label="Turbidity:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['pskTurb'], self.renderGlobalsNodeName + ".turbidity", index = 2 )
+ envDict['pskTurbMax'] = pm.floatFieldGrp(label="Turbidity Max:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['pskTurbMax'], self.renderGlobalsNodeName + ".turbidity_max", index = 2 )
+ envDict['pskTurbMin'] = pm.floatFieldGrp(label="Turbidity Min:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(envDict['pskTurbMin'], self.renderGlobalsNodeName + ".turbidity_min", index = 2 )
+
+ pm.setUITemplate("attributeEditorTemplate", popTemplate = True)
+ pm.formLayout(parentForm, edit = True, attachForm = [ (scLo, "top", 0), (scLo, "bottom", 0), (scLo, "left", 0), (scLo, "right", 0) ])
+
+
+ def AppleseedEnvironmentUpdateTab(self):
+ log.debug("AppleseedEnvironmentUpdateTab()")
+
def AppleseedAOVsCreateTab(self):
log.debug("AppleseedAOVsCreateTab()")
self.createGlobalsNode()
@@ -145,26 +202,6 @@ def AppleseedRendererCreateTab(self):
pm.connectControl(ui, self.renderGlobalsNodeName + ".glossyDepth", index = 2 )
ui = pm.intFieldGrp(label="Direct Light Samples:", value1 = 4, numberOfFields = 1)
pm.connectControl(ui, self.renderGlobalsNodeName + ".directLightSamples", index = 2 )
- with pm.frameLayout(label="Environment Lighting", collapsable = True, collapse=True):
- envDict = {}
- self.rendererTabUiDict['environment'] = envDict
- attr = pm.Attribute(self.renderGlobalsNodeName + ".environmentType")
- ui = pm.attrEnumOptionMenu(label = "Environemnt Type", cc=self.updateEnvironment, at=self.renderGlobalsNodeName + ".environmentType", ei = self.getEnumList(attr))
- ui = pm.floatFieldGrp(label="Environemnt Intensity:", value1 = 1.0, numberOfFields = 1)
- pm.connectControl(ui, self.renderGlobalsNodeName + ".environmentIntensity", index = 2 )
-
- envDict['environmentColor'] = pm.attrColorSliderGrp(label = "Environment Color", at=self.renderGlobalsNodeName + ".environmentColor")
- #attr = pm.Attribute(self.renderGlobalsNodeName + ".environmentColor")
- envDict['gradientHorizon'] = pm.attrColorSliderGrp(label = "Gradient Horizon", at=self.renderGlobalsNodeName + ".gradientHorizon")
- #attr = pm.Attribute(self.renderGlobalsNodeName + ".gradientHorizon")
- envDict['gradientZenit'] = pm.attrColorSliderGrp(label = "Gradient Zenit", at=self.renderGlobalsNodeName + ".gradientZenit")
- #attr = pm.Attribute(self.renderGlobalsNodeName + ".gradientZenit")
- envDict['environmentMap'] = pm.attrColorSliderGrp(label = "Environment Map", at=self.renderGlobalsNodeName + ".environmentMap")
- #attr = pm.Attribute(self.renderGlobalsNodeName + ".environmentMap")
- ui = pm.floatFieldGrp(label="LatLong Horiz Shift:", value1 = 1.0, numberOfFields = 1)
- pm.connectControl(ui, self.renderGlobalsNodeName + ".latlongHoShift", index = 2 )
- ui = pm.floatFieldGrp(label="LatLong Vertical Shift:", value1 = 1.0, numberOfFields = 1)
- pm.connectControl(ui, self.renderGlobalsNodeName + ".latlongVeShift", index = 2 )
with pm.frameLayout(label="Renderer", collapsable = True, collapse=False):
View
30 src/mayaToAppleseed/src/appleseed/appleseed.cpp
@@ -276,6 +276,7 @@ void AppleseedRenderer::defineEnvironment(mtap_RenderGlobals *renderGlobals)
MFnDependencyNode globalsFn(renderGlobals->renderGlobalsMobject);
MString envMapAttrName = envMapName;
this->defineTexture(globalsFn, envMapAttrName, envMapName);
+ int skyModel = this->renderGlobals->skyModel;
asf::auto_release_ptr<asr::EnvironmentEDF> environmentEDF;
@@ -323,6 +324,35 @@ void AppleseedRenderer::defineEnvironment(mtap_RenderGlobals *renderGlobals)
.insert("exitance", envMapName.asChar())
.insert("exitance_multiplier", renderGlobals->environmentIntensity));
break;
+ case 4: // physical sky
+ if(skyModel == 0) // preetham
+ {
+ environmentEDF = asr::PreethamEnvironmentEDFFactory().create(
+ "sky_edf",
+ asr::ParamArray()
+ .insert("horizon_shift", renderGlobals->horizon_shift)
+ .insert("luminance_multiplier", renderGlobals->luminance_multiplier)
+ .insert("saturation_multiplier", renderGlobals->saturation_multiplier)
+ .insert("sun_phi", renderGlobals->sun_phi)
+ .insert("sun_theta", 90.0f - renderGlobals->sun_theta)
+ .insert("turbidity", renderGlobals->turbidity)
+ .insert("turbidity_max", renderGlobals->turbidity_max)
+ .insert("turbidity_min", renderGlobals->turbidity_min));
+ }else{ // hosek
+ environmentEDF = asr::HosekEnvironmentEDFFactory().create(
+ "sky_edf",
+ asr::ParamArray()
+ .insert("ground_albedo", renderGlobals->ground_albedo)
+ .insert("horizon_shift", renderGlobals->horizon_shift)
+ .insert("luminance_multiplier", renderGlobals->luminance_multiplier)
+ .insert("saturation_multiplier", renderGlobals->saturation_multiplier)
+ .insert("sun_phi", renderGlobals->sun_phi)
+ .insert("sun_theta", 90.0f - renderGlobals->sun_theta)
+ .insert("turbidity", renderGlobals->turbidity)
+ .insert("turbidity_max", renderGlobals->turbidity_max)
+ .insert("turbidity_min", renderGlobals->turbidity_min));
+ }
+ break;
default:
environmentEDF = asr::ConstantEnvironmentEDFFactory().create(
"sky_edf",
View
32 src/mayaToAppleseed/src/mtap_common/mtap_renderGlobals.cpp
@@ -186,7 +186,37 @@ bool mtap_RenderGlobals::getMtapGlobals()
if(!getFloat(MString("latlongVeShift"), appleseedGlobals, this->latlongVeShift))
throw("problem reading appleseedGlobals.latlongVeShift");
-
+
+ if(!getEnum(MString("skyModel"), appleseedGlobals, this->skyModel))
+ throw("problem reading appleseedGlobals.skyModel");
+
+ if(!getFloat(MString("ground_albedo"), appleseedGlobals, this->ground_albedo))
+ throw("problem reading appleseedGlobals.ground_albedo");
+
+ if(!getFloat(MString("horizon_shift"), appleseedGlobals, this->horizon_shift))
+ throw("problem reading appleseedGlobals.horizon_shift");
+
+ if(!getFloat(MString("luminance_multiplier"), appleseedGlobals, this->luminance_multiplier))
+ throw("problem reading appleseedGlobals.luminance_multiplier");
+
+ if(!getFloat(MString("saturation_multiplier"), appleseedGlobals, this->saturation_multiplier))
+ throw("problem reading appleseedGlobals.saturation_multiplier");
+
+ if(!getFloat(MString("sun_phi"), appleseedGlobals, this->sun_phi))
+ throw("problem reading appleseedGlobals.sun_phi");
+
+ if(!getFloat(MString("sun_theta"), appleseedGlobals, this->sun_theta))
+ throw("problem reading appleseedGlobals.sun_theta");
+
+ if(!getFloat(MString("turbidity"), appleseedGlobals, this->turbidity))
+ throw("problem reading appleseedGlobals.turbidity");
+
+ if(!getFloat(MString("turbidity_max"), appleseedGlobals, this->turbidity_max))
+ throw("problem reading appleseedGlobals.turbidity_max");
+
+ if(!getFloat(MString("turbidity_min"), appleseedGlobals, this->turbidity_min))
+ throw("problem reading appleseedGlobals.turbidity_min");
+
this->sceneScaleMatrix.setToIdentity();
this->sceneScaleMatrix.matrix[0][0] = this->sceneScale;
this->sceneScaleMatrix.matrix[1][1] = this->sceneScale;
View
11 src/mayaToAppleseed/src/mtap_common/mtap_renderGlobals.h
@@ -44,6 +44,17 @@ class mtap_RenderGlobals : public RenderGlobals
float latlongHoShift;
float latlongVeShift;
+ int skyModel;
+ float ground_albedo;
+ float horizon_shift;
+ float luminance_multiplier;
+ float saturation_multiplier;
+ float sun_phi;
+ float sun_theta;
+ float turbidity;
+ float turbidity_max;
+ float turbidity_min;
+
virtual MString getImageExt();
private:
View
44 src/mayaToAppleseed/src/mtap_common/mtap_renderGlobalsNode.cpp
@@ -35,7 +35,16 @@ MObject MayaToAppleseedGlobals::latlongHoShift;
MObject MayaToAppleseedGlobals::latlongVeShift;
MObject MayaToAppleseedGlobals::AOVs;
-
+MObject MayaToAppleseedGlobals::ground_albedo;
+MObject MayaToAppleseedGlobals::horizon_shift;
+MObject MayaToAppleseedGlobals::luminance_multiplier;
+MObject MayaToAppleseedGlobals::saturation_multiplier;
+MObject MayaToAppleseedGlobals::sun_phi;
+MObject MayaToAppleseedGlobals::sun_theta;
+MObject MayaToAppleseedGlobals::turbidity;
+MObject MayaToAppleseedGlobals::turbidity_max;
+MObject MayaToAppleseedGlobals::turbidity_min;
+MObject MayaToAppleseedGlobals::skyModel;
MayaToAppleseedGlobals::MayaToAppleseedGlobals()
{}
@@ -126,6 +135,7 @@ MStatus MayaToAppleseedGlobals::initialize()
stat = eAttr.addField( "Gradient", 1 );
stat = eAttr.addField( "Latitude Longitude", 2 );
stat = eAttr.addField( "Mirror Ball", 3 );
+ stat = eAttr.addField( "Physical Sky", 4 );
CHECK_MSTATUS(addAttribute( environmentType ));
environmentColor = nAttr.createColor("environmentColor", "environmentColor");
@@ -176,6 +186,38 @@ MStatus MayaToAppleseedGlobals::initialize()
mAttr.setArray(true);
CHECK_MSTATUS(addAttribute( AOVs ));
+ ground_albedo = nAttr.create("ground_albedo", "ground_albedo", MFnNumericData::kFloat, .0f);
+ CHECK_MSTATUS(addAttribute( ground_albedo ));
+
+ horizon_shift = nAttr.create("horizon_shift", "horizon_shift", MFnNumericData::kFloat, -0.05f);
+ CHECK_MSTATUS(addAttribute( horizon_shift ));
+
+ luminance_multiplier = nAttr.create("luminance_multiplier", "luminance_multiplier", MFnNumericData::kFloat, 1.0f);
+ CHECK_MSTATUS(addAttribute( luminance_multiplier ));
+
+ saturation_multiplier = nAttr.create("saturation_multiplier", "saturation_multiplier", MFnNumericData::kFloat, 1.0f);
+ CHECK_MSTATUS(addAttribute( saturation_multiplier ));
+
+ sun_phi = nAttr.create("sun_phi", "sun_phi", MFnNumericData::kFloat, .0f);
+ CHECK_MSTATUS(addAttribute( sun_phi ));
+
+ sun_theta = nAttr.create("sun_theta", "sun_theta", MFnNumericData::kFloat, 60.0f);
+ CHECK_MSTATUS(addAttribute( sun_theta ));
+
+ turbidity = nAttr.create("turbidity", "turbidity", MFnNumericData::kFloat, 3.0f);
+ CHECK_MSTATUS(addAttribute( turbidity ));
+
+ turbidity_max = nAttr.create("turbidity_max", "turbidity_max", MFnNumericData::kFloat, 3.0f);
+ CHECK_MSTATUS(addAttribute( turbidity_max ));
+
+ turbidity_min = nAttr.create("turbidity_min", "turbidity_min", MFnNumericData::kFloat, 3.0f);
+ CHECK_MSTATUS(addAttribute( turbidity_min ));
+
+ skyModel = eAttr.create( "skyModel", "skyModel", 0, &stat);
+ stat = eAttr.addField( "Preetham", 0 );
+ stat = eAttr.addField( "Hosek", 1 );
+ CHECK_MSTATUS(addAttribute( skyModel ));
+
return stat;
}
View
13 src/mayaToAppleseed/src/mtap_common/mtap_renderGlobalsNode.h
@@ -44,12 +44,25 @@ class MayaToAppleseedGlobals : public MayaRenderGlobalsNode
static MObject environmentIntensity;
static MObject latlongHoShift;
static MObject latlongVeShift;
+
+ //sky shader
+ static MObject skyModel;
+ static MObject ground_albedo;
+ static MObject horizon_shift;
+ static MObject luminance_multiplier;
+ static MObject saturation_multiplier;
+ static MObject sun_phi;
+ static MObject sun_theta;
+ static MObject turbidity;
+ static MObject turbidity_max;
+ static MObject turbidity_min;
static MObject imageFormat;
static MObject sceneScale;
static MObject AOVs;
+
};
#endif
View
18 src/mayaToKray/.gitignore
@@ -0,0 +1,18 @@
+# Compiled Object files
+*.slo
+*.lo
+*.o
+
+# Compiled Dynamic libraries
+*.so
+*.dll
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+
+# kray devkit files
+devkit
+
+
View
5 src/mayaToKray/deployment/mayaToKray/mayaToKray.mod
@@ -0,0 +1,5 @@
++ LOCALE:en_US mtkr 0.1.0 ../mtkr_devmodule
+MTAP_LOCATION:=
+MTAP_SHADERS_LOCATION:=shaders
+MAYA_RENDER_DESC_PATH+:=ressources
+PATH+:=bin
View
BIN src/mayaToKray/mtkr_devmodule/bin/kray.dll_
Binary file not shown.
View
BIN src/mayaToKray/mtkr_devmodule/bin/kray3l_32.exe
Binary file not shown.
View
BIN src/mayaToKray/mtkr_devmodule/bin/kray3l_64.exe
Binary file not shown.
View
BIN src/mayaToKray/mtkr_devmodule/bin/kray3rsrc.ka
Binary file not shown.
View
5 src/mayaToKray/mtkr_devmodule/mayaToKray.mod
@@ -0,0 +1,5 @@
++ LOCALE:en_US mtkr 0.1.0 ../mtkr_devmodule
+MTAP_LOCATION:=
+MTAP_SHADERS_LOCATION:=shaders
+MAYA_RENDER_DESC_PATH+:=ressources
+PATH+:=bin
View
BIN src/mayaToKray/mtkr_devmodule/plug-ins/mayaToKray.mll
Binary file not shown.
View
91 src/mayaToKray/mtkr_devmodule/ressources/_Renderer.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!DOCTYPE renderer SYSTEM "renderer.dtd">
+<!--
+ Top level tag, mandatory:
+ <renderer>: "desc" gives a one line description.
+
+ Header tags, not mandatory, must be specified only once.
+ <melheader>: "s" is a mel script executed just after the file is read
+ <meltrailer>: "s" is a mel script executed after all flags are converted
+ to mel. Should contain at least the rendering command.
+
+ Other tags:
+ <sep>: "desc" produces a line in the help. Blank if desc is missing.
+ <attr>: produces a setAttr line.
+ "n" is the flag name.
+ "s" the attribute name.
+ "t" the parameter type, used in help description.
+ "h" the help description.
+ <attrString>: produces a setAttr line for a string attribute.
+ Same parameters as <attr>, but for string attributes.
+ <mel>: Calls a mel script.
+ "n" is the flag name.
+ "p" the number of parameters.
+ "s" the string defining the action %1 ... %p are replaced with values
+ read after the flag.
+ "t" the parameter types, used in help description.
+ "h" the help description.
+-->
+<renderer desc="Mantra renderer">
+ <melheader s='string $opt=""; string $rl=""; string $rp=""; float $resize=-1.; loadPlugin mayatomantra;'/>
+ <meltrailer s='setMayaSoftwareLayers($rl, $rp); setImageSizePercent($resize);mayaBatchRenderProcedure(0, "", "", "Mantra", $opt); '/>
+ <sep/>
+ <!-- ______________________________________________________________ -->
+ <sep desc="General purpose flags:"/>
+ <mel n="rd" p="1" s='workspace -rt "images" "%1";workspace -rt "depth" "%1";' t="path" h="Directory in which to store image files"/>
+ <attrString n="im" s="defaultRenderGlobals.imageFilePrefix" t="filename" h="Image file output name"/>
+ <attr n="v" s="mayaToMantraGlobals.translatorVerbosity" t="int" h="Verbosity level (0-6)"/>
+ <sep/>
+ <!-- ______________________________________________________________ -->
+ <sep desc="Frame numbering options"/>
+ <mel n="s" p="1" t="float" s="removeRenderLayerAdjustmentAndUnlock defaultRenderGlobals.animation; setAttr defaultRenderGlobals.animation 1; removeRenderLayerAdjustmentAndUnlock defaultRenderGlobals.startFrame; setAttr defaultRenderGlobals.startFrame %1" h="Starting frame for an animation sequence"/>
+ <mel n="e" p="1" t="float" s="removeRenderLayerAdjustmentAndUnlock defaultRenderGlobals.animation; setAttr defaultRenderGlobals.animation 1; removeRenderLayerAdjustmentAndUnlock defaultRenderGlobals.endFrame; setAttr defaultRenderGlobals.endFrame %1" h="End frame for an animation sequence"/>
+ <attr n="b" s="defaultRenderGlobals.byFrameStep" t="float" h="By frame (or step) for an animation sequence"/>
+ <attr n="pad" s="defaultRenderGlobals.extensionPadding" t="int" h="Number of digits in the output image frame file name\n\t\t extension"/>
+ <sep/>
+ <!-- ______________________________________________________________ -->
+ <sep desc="Render Layers and Passes"/>
+ <mel n="rl" s='$rl="%1"' p="1" t="boolean|name(s)" h="Render each render layer separately"/>
+ <mel n="rp" s='$rp="%1"' p="1" t="boolean|name(s)" h="Render passes separately. 'all' will render all passes"/>
+ <mel n="sel" p="1" s="select -add %1; removeRenderLayerAdjustmentAndUnlock defaultRenderGlobals.renderAll; setAttr defaultRenderGlobals.renderAll 0" t="boolean|name(s)" h="Selects which objects, groups and/or sets to render"/>
+ <mel n="l" p="1" s="selectLayerMembers %1; removeRenderLayerAdjustmentAndUnlock defaultRenderGlobals.renderAll; setAttr defaultRenderGlobals.renderAll 0" t="boolean|name(s)" h="Selects which display and render layers to render"/>
+ <sep/>
+ <!-- ______________________________________________________________ -->
+ <sep desc="Camera options"/>
+ <mel n="cam" s='makeCameraRenderable("%1")' p="1" t="name" h="Specify which camera to be rendered"/>
+ <sep/>
+ <!-- ______________________________________________________________ -->
+ <sep desc="Resolution options"/>
+ <attr n="x" s="defaultResolution.width" t="int" h="Set X resolution of the final image"/>
+ <attr n="y" s="defaultResolution.height" t="int" h="Set Y resolution of the final image"/>
+ <mel n="percentRes" s="$resize=%1" p="1" t="float" h="Renders the image using percent of the resolution"/>
+ <attr n="ard" s="defaultResolution.deviceAspectRatio" t="float" h="Device aspect ratio for the rendered image"/>
+ <sep/>
+ <!-- ______________________________________________________________ -->
+ <sep desc="Samples options"/>
+ <attr n="sx" s="mayaToMantraGlobals.samples0" t="int" h="SamplesX"/>
+ <attr n="sy" s="mayaToMantraGlobals.samples1" t="int" h="SamplesY"/>
+ <sep/>
+ <!-- ______________________________________________________________ -->
+ <sep desc="Mel callbacks"/>
+ <mel n="preRender" p="1" s='string $pm=`getAttr defaultRenderGlobals.preMel`; setAttr -type "string" defaultRenderGlobals.preMel ($pm + ";%1");' t="string" h="add Mel code executed before rendering"/>
+ <mel n="postRender" p="1" s='string $pm=`getAttr defaultRenderGlobals.postMel`; setAttr -type "string" defaultRenderGlobals.postMel ($pm + ";%1");' t="string" h="add Mel code executed after rendering"/>
+ <mel n="preLayer" p="1" s='string $pm=`getAttr defaultRenderGlobals.preRenderLayerMel`; setAttr -type "string" defaultRenderGlobals.preRenderLayerMel ($pm + ";%1");' t="string" h="add Mel code executed before each render layer"/>
+ <mel n="postLayer" p="1" s='string $pm=`getAttr defaultRenderGlobals.postRenderLayerMel`; setAttr -type "string" defaultRenderGlobals.postRenderLayerMel ($pm + ";%1");' t="string" h="add Mel code executed after each render layer"/>
+ <mel n="preFrame" p="1" s='string $pm=`getAttr defaultRenderGlobals.preRenderMel`; setAttr -type "string" defaultRenderGlobals.preRenderMel ($pm + ";%1");' t="string" h="add Mel code executed before each frame"/>
+ <mel n="postFrame" p="1" s='string $pm=`getAttr defaultRenderGlobals.postRenderMel`; setAttr -type "string" defaultRenderGlobals.postRenderMel ($pm + ";%1");' t="string" h="add Mel code executed after each frame"/>
+
+ <mel n="insertPreRender" p="1" s='string $pm=`getAttr defaultRenderGlobals.preMel`; setAttr -type "string" defaultRenderGlobals.preMel ("%1;" + $pm);' t="string" h="insert Mel code executed before rendering"/>
+ <mel n="insertPostRender" p="1" s='string $pm=`getAttr defaultRenderGlobals.postMel`; setAttr -type "string" defaultRenderGlobals.postMel ("%1;" + $pm);' t="string" h="insert Mel code executed after rendering"/>
+ <mel n="insertPreLayer" p="1" s='string $pm=`getAttr defaultRenderGlobals.preRenderLayerMel`; setAttr -type "string" defaultRenderGlobals.preRenderLayerMel ("%1;" + $pm);' t="string" h="insert Mel code executed before each render layer"/>
+ <mel n="insertPostLayer" p="1" s='string $pm=`getAttr defaultRenderGlobals.postRenderLayerMel`; setAttr -type "string" defaultRenderGlobals.postRenderLayerMel ("%1;" + $pm);' t="string" h="insert Mel code executed after each render layer"/>
+ <mel n="insertPreFrame" p="1" s='string $pm=`getAttr defaultRenderGlobals.preRenderMel`; setAttr -type "string" defaultRenderGlobals.preRenderMel ("%1;" + $pm);' t="string" h="insert Mel code executed before each frame"/>
+ <mel n="insertPostFrame" p="1" s='string $pm=`getAttr defaultRenderGlobals.postRenderMel`; setAttr -type "string" defaultRenderGlobals.postRenderMel ("%1;" + $pm);' t="string" h="insert Mel code executed after each frame"/>
+ <sep/>
+ <!-- ______________________________________________________________ -->
+ <sep desc=" *** Remember to place a space between option flags and their arguments. ***"/>
+ <sep desc="Any boolean flag will take the following values as TRUE: on, yes, true, or 1."/>
+ <sep desc="Any boolean flag will take the following values as FALSE: off, no, false, or 0."/>
+ <sep/>
+ <sep desc=" e.g. -s 1 -e 10 -x 512 -y 512 -cam persp -as 4 -hs 2 -dif 2 file."/>
+</renderer>
View
17 src/mayaToKray/mtkr_devmodule/scripts/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>mayaToKray</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.python.pydev.PyDevBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.python.pydev.pythonNature</nature>
+ </natures>
+</projectDescription>
View
34 src/mayaToKray/mtkr_devmodule/scripts/AETemplates/AEkrayNodeTemplate.py
@@ -0,0 +1,34 @@
+import pymel.core as pm
+import logging
+
+log = logging.getLogger("ui")
+
+class BaseTemplate(pm.ui.AETemplate):
+
+ def addControl(self, control, label=None, **kwargs):
+ pm.ui.AETemplate.addControl(self, control, label=label, **kwargs)
+
+ def beginLayout(self, name, collapse=True):
+ pm.ui.AETemplate.beginLayout(self, name, collapse=collapse)
+
+
+class AEkrayNodeTemplate(BaseTemplate):
+ def __init__(self, nodeName):
+ BaseTemplate.__init__(self,nodeName)
+ self.thisNode = None
+ self.node = pm.PyNode(self.nodeName)
+ self.buildBody(nodeName)
+ log.debug("AEkrayNodeTemplate")
+
+ def buildKrayTemplates(self, nodeName):
+ self.thisNode = pm.PyNode(nodeName)
+ if self.thisNode.type() == "camera":
+ self.beginLayout("Kray" ,collapse=1)
+ self.endLayout()
+ if self.thisNode.type() == "mesh":
+ self.beginLayout("Kray" ,collapse=1)
+ self.endLayout()
+
+ def buildBody(self, nodeName):
+ self.buildKrayTemplates(nodeName)
+
View
0 src/mayaToKray/mtkr_devmodule/scripts/AETemplates/__init__.py
No changes.
View
227 src/mayaToKray/mtkr_devmodule/scripts/asutils.py
@@ -0,0 +1,227 @@
+import pymel.core as pm
+import maya.OpenMaya as om
+
+def unload_plugin():
+ pm.newFile(force=True)
+ if pm.pluginInfo("mayatoappleseed.mll", query=True, loaded=True):
+ pm.unloadPlugin("mayatoappleseed.mll")
+ pm.newFile(force=True)
+
+def load_plugin():
+ if not pm.pluginInfo("mayatoappleseed.mll", query=True, loaded=True):
+ pm.loadPlugin("mayatoappleseed.mll")
+
+def reloadPlugin():
+ unload_plugin()
+ load_plugin()
+
+
+class assembly:
+ def __init__(self, dp, dn, name, parentAss = None):
+ self.geoList = []
+ self.dagPath = dp
+ self.dagNode = dn
+ self.name = name
+ self.parentAss = parentAss
+ self.assemblies = []
+ self.assembly_instances = []
+ self.transformMatrix = om.MTransformationMatrix().identity.asMatrix()
+ self.geometry = []
+
+class mobject:
+ def __init__(self, dagPath):
+ self.dagPath = dagPath
+ self.dagNode = om.MFnDagNode(self.dagPath.node())
+ self.node = pm.PyNode(dagPath.fullPathName())
+ self.assembly = None
+
+def getWorld():
+ di = om.MItDag(om.MItDag.kDepthFirst, om.MFn.kInvalid)
+ while not di.isDone():
+ dp = om.MDagPath()
+ di.getPath(dp)
+ if dp.node().apiType() == om.MFn.kWorld:
+ return dp
+ di.next()
+
+def needsAssembly(node):
+ if node.parentCount() > 1:
+ return True
+ try:
+ pnode = pm.PyNode(node.fullPathName())
+ except:
+ return False
+ if pnode.type() == "transform":
+ if len(pnode.inputs()) > 0:
+ return True
+ return False
+
+def isGeo(mobj):
+ if mobj.hasFn(om.MFn.kMesh):
+ return True
+ return False
+
+def isTransform(mobj):
+ if mobj.hasFn(om.MFn.kTransform):
+ return True
+ return False
+
+instList = []
+
+def parseChildren(parentNode, pAssembly, assemblyList):
+
+ numChildren = parentNode.childCount()
+ dagPath = om.MDagPath()
+ parentNode.getPath(dagPath)
+ parentObj = dagPath.node()
+# if dagPath.instanceNumber() > 0:
+# print "is inst", dagPath.fullPathName()
+# return
+
+ if dagPath.isInstanced():
+ instList.append(dagPath)
+
+ #print "Parse", parentNode.fullPathName()
+ for cId in range(numChildren):
+ childObj = parentNode.child(cId)
+ childNode = om.MFnDagNode(childObj)
+ childDagPath = om.MDagPath()
+ childNode.getPath(childDagPath)
+
+ childParent = childNode.parent(0)
+ childParentNode = om.MFnDagNode(childParent)
+
+ if childNode.parent(0) != parentObj:
+ print "parent von ", childNode.fullPathName(), "==", childParentNode.fullPathName(), "current parent:", parentNode.fullPathName()
+ continue
+
+ if isTransform(childObj):
+ print "ParentAss Transform", pAssembly.name
+
+ if isGeo(childObj):
+ print "Put geo", childNode.partialPathName(), "into parent assembly", pAssembly.name
+ pAssembly.geometry.append(childNode.partialPathName())
+
+ parentAssembly = pAssembly
+ if needsAssembly(childNode):
+ print "Child node", childNode.fullPathName(), "needs assembly"
+ parentAssembly = assembly(childDagPath, childNode, childNode.fullPathName(), parentAss=pAssembly)
+ pAssembly.assembly_instances.append(parentAssembly)
+ assemblyList.append(parentAssembly)
+ #parentAssembly = pAssembly
+
+ parseChildren(childNode, parentAssembly, assemblyList)
+
+def printAss(level, ass = None):
+ sp = ""
+ for i in range(level):
+ sp += " "
+ print sp+"AName: ", ass.name
+ for i in ass.geometry:
+ print sp, "geo:", i.partialPathName()
+ for i in ass.assembly_instances:
+ print sp, "Ainstance", i.name
+ for i in ass.assemblies:
+ printAss(level+4, i)
+
+
+def hierarchyA():
+ worldDag = getWorld()
+ worldDagNode = om.MFnDagNode(worldDag)
+ assemblyList = []
+ worldAssembly = assembly(worldDag, worldDagNode, "root")
+ assemblyList.append(worldAssembly)
+ #tMatrix = om.MMatrix()
+ parseChildren(worldDagNode, worldAssembly, assemblyList)
+ #printAss(0, worldAssembly)
+
+# for ass in assemblyList:
+# parentAss = ass.parentAss
+# if parentAss:
+# print "Assembly List: ", ass.name, "parent", ass.parentAss.name
+# else:
+# print "Assembly List: ", ass.name, "parent", "world"
+# for ai in ass.assembly_instances:
+# print ass.name, "Instance:", ai.name
+# for ai in ass.geometry:
+# print "->Geo:", ai
+
+ for i in instList:
+ print "Instance", i.fullPathName()
+ dpa = om.MDagPathArray()
+ dn = om.MFnDagNode(i)
+ dn.getAllPaths(dpa)
+ print "NumPaths", dpa.length()
+ for dp in range(dpa.length()):
+ print dpa[dp].fullPathName()
+
+def hierarchy():
+
+ assDagDict = {}
+ liste = []
+ di = om.MItDag(om.MItDag.kDepthFirst, om.MFn.kInvalid)
+ while not di.isDone():
+ dp = om.MDagPath()
+ di.getPath(dp)
+ obj = dp.node()
+ print "Object", dp.fullPathName()
+ if obj.apiType() == om.MFn.kWorld:
+ "Object", dp.fullPathName(), "==kWorld"
+ if dp.instanceNumber() > 0:
+ di.next()
+ continue
+ dn = om.MFnDagNode(dp.node())
+
+ if dp.node().hasFn(om.MFn.kMesh) or dp.node().hasFn(om.MFn.kTransform):
+ node = None
+ try:
+ node = pm.PyNode(dp.fullPathName())
+ except:
+ pass
+ if node:
+ #print dp.fullPathName()
+ liste.append(mobject(dp))
+
+ di.next()
+
+ for mo in liste:
+ if mo.node.type() == "transform":
+ print "Check T", mo.node
+ if mo.node.inputs():
+ print "Has input"
+ mo.assembly = assembly()
+ assDagDict[mo.dagNode.fullPathName()] = mo
+ if mo.node.type() == "mesh":
+ print "Check M", mo.node
+ if mo.dagNode.parentCount() > 1:
+ print "Has multi parents"
+ mo.assembly = assembly()
+ assDagDict[mo.dagNode.fullPathName()] = mo
+
+ print assDagDict
+
+ for mo in liste:
+ if mo.node.type() == "mesh":
+ print "Check Mesh Path", mo.node
+ parentNode = mo.dagNode
+ while parentNode:
+ print "ParentPath", parentNode.fullPathName()
+ if assDagDict.has_key(parentNode.fullPathName()):
+ mobj = assDagDict[parentNode.fullPathName()]
+ print "Put", mo.node, "into assembly", mobj.dagNode.fullPathName()
+ break
+ pobj = parentNode.parent(0)
+ #print pobj, pobj.apiTypeStr()
+ if pobj.apiType() == om.MFn.kWorld:
+ print "Found world", "put node", mo.node, "into scene"
+ break
+ parentNode = om.MFnDagNode(pobj)
+ #print parentNode, parentNode.fullPathName()
+ #if parentNode.dagPath().apiTypeStr() == om.MFn.kWorld:
+ # print "World!"
+ # break
+
+
+
+
+
View
281 src/mayaToKray/mtkr_devmodule/scripts/mtkr_initialize.py
@@ -0,0 +1,281 @@
+import pymel.core as pm
+import logging
+import Renderer as Renderer
+import traceback
+import sys
+import os
+import optimizeTextures
+
+reload(Renderer)
+
+log = logging.getLogger("mtkrLogger")
+
+RENDERER_NAME="Kray"
+
+class KrayRenderer(Renderer.MayaToRenderer):
+ theRendererInstance = None
+ @staticmethod
+ def theRenderer(arg = None):
+ if not KrayRenderer.theRendererInstance:
+ KrayRenderer.theRendererInstance = KrayRenderer(RENDERER_NAME , __name__)
+ return KrayRenderer.theRendererInstance
+
+ def __init__(self, rendererName, moduleName):
+ Renderer.MayaToRenderer.__init__(self, rendererName, moduleName)
+ self.rendererTabUiDict = {}
+
+
+ def getEnumList(self, attr):
+ return [(i, v) for i,v in enumerate(attr.getEnums().keys())]
+
+ def updateTest(self, dummy = None):
+ print "UpdateTest", dummy
+
+ def addUserTabs(self):
+ pm.renderer(self.rendererName, edit=True, addGlobalsTab=self.renderTabMelProcedure("Photons"))
+ pm.renderer(self.rendererName, edit=True, addGlobalsTab=self.renderTabMelProcedure("FinalGathering"))
+ #pm.renderer(self.rendererName, edit=True, addGlobalsTab=self.renderTabMelProcedure("Sampling"))
+ pm.renderer(self.rendererName, edit=True, addGlobalsTab=self.renderTabMelProcedure("Quality"))
+
+ def KrayPhotonsCreateTab(self):
+ log.debug("KrayPhotonsCreateTab()")
+ self.createGlobalsNode()
+ parentForm = pm.setParent(query = True)
+ pm.setUITemplate("attributeEditorTemplate", pushTemplate = True)
+ scLo = self.rendererName + "PhotonsScrollLayout"
+ with pm.scrollLayout(scLo, horizontalScrollBarThickness = 0):
+ with pm.columnLayout(self.rendererName + "ColumnLayout", adjustableColumn = True, width = 400):
+ with pm.frameLayout(label="Photons frame", collapsable = True, collapse=False):
+ ui = pm.checkBoxGrp(label="Dummy:", value1 = False)
+ pm.setUITemplate("attributeEditorTemplate", popTemplate = True)
+ pm.formLayout(parentForm, edit = True, attachForm = [ (scLo, "top", 0), (scLo, "bottom", 0), (scLo, "left", 0), (scLo, "right", 0) ])
+
+ def KrayPhotonsUpdateTab(self):
+ log.debug("KrayPhotonsUpdateTab()")
+
+ def KrayFinalGatheringCreateTab(self):
+ log.debug("KrayFinalGatheringCreateTab()")
+ self.createGlobalsNode()
+ parentForm = pm.setParent(query = True)
+ pm.setUITemplate("attributeEditorTemplate", pushTemplate = True)
+ scLo = self.rendererName + "PhotonsScrollLayout"
+ with pm.scrollLayout(scLo, horizontalScrollBarThickness = 0):
+ with pm.columnLayout(self.rendererName + "ColumnLayout", adjustableColumn = True, width = 400):
+ with pm.frameLayout(label="Photons frame", collapsable = True, collapse=False):
+ ui = pm.checkBoxGrp(label="Dummy:", value1 = False)
+ pm.setUITemplate("attributeEditorTemplate", popTemplate = True)
+ pm.formLayout(parentForm, edit = True, attachForm = [ (scLo, "top", 0), (scLo, "bottom", 0), (scLo, "left", 0), (scLo, "right", 0) ])
+
+ def KrayFinalGatheringUpdateTab(self):
+ log.debug("KrayFinalGatheringUpdateTab()")
+
+# def KraySamplingCreateTab(self):
+# log.debug("KraySamplingCreateTab()")
+# self.createGlobalsNode()
+# parentForm = pm.setParent(query = True)
+# pm.setUITemplate("attributeEditorTemplate", pushTemplate = True)
+# scLo = self.rendererName + "PhotonsScrollLayout"
+# with pm.scrollLayout(scLo, horizontalScrollBarThickness = 0):
+# with pm.columnLayout(self.rendererName + "ColumnLayout", adjustableColumn = True, width = 400):
+# with pm.frameLayout(label="Photons frame", collapsable = True, collapse=False):
+# ui = pm.checkBoxGrp(label="Dummy:", value1 = False)
+# pm.setUITemplate("attributeEditorTemplate", popTemplate = True)
+# pm.formLayout(parentForm, edit = True, attachForm = [ (scLo, "top", 0), (scLo, "bottom", 0), (scLo, "left", 0), (scLo, "right", 0) ])
+#
+# def KraySamplingUpdateTab(self):
+# log.debug("KraySamplingUpdateTab()")
+
+
+ def KrayQualityCreateTab(self):
+ log.debug("KrayFinalGatheringCreateTab()")
+ self.createGlobalsNode()
+ parentForm = pm.setParent(query = True)
+ pm.setUITemplate("attributeEditorTemplate", pushTemplate = True)
+ scLo = self.rendererName + "PhotonsScrollLayout"
+ with pm.scrollLayout(scLo, horizontalScrollBarThickness = 0):
+ with pm.columnLayout(self.rendererName + "ColumnLayout", adjustableColumn = True, width = 400):
+ with pm.frameLayout(label="Photons frame", collapsable = True, collapse=False):
+ ui = pm.checkBoxGrp(label="Dummy:", value1 = False)
+ pm.setUITemplate("attributeEditorTemplate", popTemplate = True)
+ pm.formLayout(parentForm, edit = True, attachForm = [ (scLo, "top", 0), (scLo, "bottom", 0), (scLo, "left", 0), (scLo, "right", 0) ])
+
+ def KrayQualityUpdateTab(self):
+ log.debug("KrayQualityUpdateTab()")
+
+
+ def KrayRendererCreateTab(self):
+ log.debug("KrayRendererCreateTab()")
+ self.createGlobalsNode()
+ parentForm = pm.setParent(query = True)
+ pm.setUITemplate("attributeEditorTemplate", pushTemplate = True)
+ scLo = self.rendererName + "ScrollLayout"
+ with pm.scrollLayout(scLo, horizontalScrollBarThickness = 0):
+ with pm.columnLayout(self.rendererName + "ColumnLayout", adjustableColumn = True, width = 400):
+ with pm.frameLayout(label="Sampling", collapsable = True, collapse=False):
+ attr = pm.Attribute(self.renderGlobalsNodeName + ".samplingType")
+ ui = pm.attrEnumOptionMenuGrp(label = "Sampling Type", at=self.renderGlobalsNodeName + ".samplingType", ei = self.getEnumList(attr))
+ ui = pm.intFieldGrp(label="Grid Size:", numberOfFields = 1)
+ pm.connectControl(ui, self.renderGlobalsNodeName + ".gridSize", index = 2 )
+ ui = pm.checkBoxGrp(label="Grid Rotate:", value1 = False)
+ pm.connectControl(ui, self.renderGlobalsNodeName + ".rotateGrid", index = 2 )
+
+ with pm.frameLayout(label="Filtering", collapsable = True, collapse=False):
+ attr = pm.Attribute(self.renderGlobalsNodeName + ".filtertype")
+ ui = pm.attrEnumOptionMenuGrp(label = "Filter Type", at=self.renderGlobalsNodeName + ".filtertype", ei = self.getEnumList(attr))
+ ui = pm.intFieldGrp(label="Filter Size:", numberOfFields = 1)
+ pm.connectControl(ui, self.renderGlobalsNodeName + ".filtersize", index = 2 )
+
+
+ pm.setUITemplate("attributeEditorTemplate", popTemplate = True)
+ pm.formLayout(parentForm, edit = True, attachForm = [ (scLo, "top", 0), (scLo, "bottom", 0), (scLo, "left", 0), (scLo, "right", 0) ])
+ self.KrayRendererUpdateTab()
+
+ def KrayRendererUpdateTab(self, dummy = None):
+ self.createGlobalsNode()
+ self.updateEnvironment()
+ log.debug("KrayRendererUpdateTab()")
+
+ def xmlFileBrowse(self, args=None):
+ filename = pm.fileDialog2(fileMode=0, caption="Kray Export File Name")
+ if len(filename) > 0:
+ print "Got filename", filename
+ self.rendererTabUiDict['xml']['xmlFile'].setText(filename[0])
+
+ def dirBrowse(self, args=None):
+ dirname = pm.fileDialog2(fileMode=3, caption="Select dir")
+ if len(dirname) > 0:
+ self.rendererTabUiDict['opti']['optiField'].setText(dirname[0])
+
+ def KrayTranslatorCreateTab(self):
+ log.debug("KrayTranslatorCreateTab()")
+ self.createGlobalsNode()
+ parentForm = pm.setParent(query = True)
+ pm.setUITemplate("attributeEditorTemplate", pushTemplate = True)
+ scLo = self.rendererName + "TrScrollLayout"
+
+ with pm.scrollLayout(scLo, horizontalScrollBarThickness = 0):
+ with pm.columnLayout(self.rendererName + "TrColumnLayout", adjustableColumn = True, width = 400):
+ with pm.frameLayout(label="Translator", collapsable = True, collapse=False):
+ attr = pm.Attribute(self.renderGlobalsNodeName + ".translatorVerbosity")
+ ui = pm.attrEnumOptionMenuGrp(label = "Translator Verbosity", at=self.renderGlobalsNodeName + ".translatorVerbosity", ei = self.getEnumList(attr))
+ with pm.frameLayout(label="Kray Scene export", collapsable = True, collapse=False):
+ ui = pm.checkBoxGrp(label="Export Scene File:", value1 = False)
+ pm.connectControl(ui, self.renderGlobalsNodeName + ".exportSceneFile", index = 2 )
+ xmlDict = {}
+ self.rendererTabUiDict['xml'] = xmlDict
+ with pm.rowColumnLayout(nc=3, width = 120):
+ pm.text(label="SceneFileName:", width = 60, align="right")
+ defaultXMLPath = pm.workspace.path + "/" + pm.sceneName().basename().split(".")[0] + ".kray"
+ xmlDict['xmlFile'] = pm.textField(text = defaultXMLPath, width = 60)
+ pm.symbolButton(image="navButtonBrowse.png", c=self.xmlFileBrowse)
+ pm.connectControl(xmlDict['xmlFile'], self.renderGlobalsNodeName + ".exportSceneFileName", index = 2 )
+ with pm.frameLayout(label="Optimize Textures", collapsable = True, collapse=False):
+ with pm.rowColumnLayout(nc=3, width = 120):
+ optiDict = {}
+# pm.text(label="OptimizedTex Dir:", width = 60, align="right")
+# self.rendererTabUiDict['opti'] = optiDict
+# pm.symbolButton(image="navButtonBrowse.png", c=self.dirBrowse)
+# optiDict['optiField'] = pm.textField(text = self.renderGlobalsNode.optimizedTexturePath.get(), width = 60)
+# pm.connectControl(optiDict['optiField'], self.renderGlobalsNodeName + ".optimizedTexturePath", index = 2 )
+ with pm.frameLayout(label="Additional Settings", collapsable = True, collapse=False):
+ ui = pm.floatFieldGrp(label="Scene scale:", value1 = 1.0, numberOfFields = 1)
+ pm.connectControl(ui, self.renderGlobalsNodeName + ".sceneScale", index = 2 )
+
+ pm.setUITemplate("attributeEditorTemplate", popTemplate = True)
+ pm.formLayout(parentForm, edit = True, attachForm = [ (scLo, "top", 0), (scLo, "bottom", 0), (scLo, "left", 0), (scLo, "right", 0) ])
+
+ def KrayTranslatorUpdateTab(self):
+ log.debug("KrayTranslatorUpdateTab()")
+
+ def createImageFormats(self):
+ self.imageFormats.append('exr')
+ self.imageFormats.append('png')
+
+ def registerNodeExtensions(self):
+ """Register Kray specific node extensions. e.g. camera type, diaphram_blades and others
+ """
+ pass
+
+ def setImageName(self):
+ self.renderGlobalsNode.basePath.set(pm.workspace.path)
+ self.renderGlobalsNode.imagePath.set(pm.workspace.path + pm.workspace.fileRules['images'])
+ imageName = pm.sceneName().basename().replace(".ma", "").replace(".mb", "")
+ # check for mayabatch name like sceneName_number
+ numberPart = imageName.split("__")[-1]
+ try:
+ number = int(numberPart)
+ if number > 999:
+ imageName = imageName.replace("__" + numberPart, "")
+ except:
+ pass
+ self.renderGlobalsNode.imageName.set(imageName)
+
+ def renderProcedure(self, width, height, doShadows, doGlow, camera, options):
+ log.debug("renderProcedure")
+ self.removeLogFile()
+ print "renderProcedure", width, height, doShadows, doGlow, camera, options
+ self.createGlobalsNode()
+ self.preRenderProcedure()
+ self.setImageName()
+
+ if pm.about(batch=True):
+ pm.mayatokray()
+ else:
+ pm.mayatokray(width=width, height=height, camera=camera)
+
+ if not self.ipr_isrunning:
+ self.showLogFile()
+ self.postRenderProcedure()
+
+ def startIprRenderProcedure(self, editor, resolutionX, resolutionY, camera):
+ self.ipr_isrunning = True
+ log.debug("startIprRenderProcedure")
+ print "startIprRenderProcedure", editor, resolutionX, resolutionY, camera
+ self.createGlobalsNode()
+ self.preRenderProcedure()
+ self.setImageName()
+ pm.mayatokray(width=resolutionX, height=resolutionY, camera=camera, startIpr=True)
+ self.postRenderProcedure()
+
+ def stopIprRenderProcedure(self):
+ self.ipr_isrunning = False
+ log.debug("stopIprRenderProcedure")
+ pm.mayatokray(stopIpr=True)
+ self.postRenderProcedure()
+
+ def preRenderProcedure(self):
+ self.createGlobalsNode()
+ if self.renderGlobalsNode.threads.get() == 0:
+ #TODO this is windows only, search for another solution...
+ numThreads = int(os.environ['NUMBER_OF_PROCESSORS'])
+ self.renderGlobalsNode.threads.set(numThreads)
+
+# if not self.renderGlobalsNode.optimizedTexturePath.get() or len(self.renderGlobalsNode.optimizedTexturePath.get()) == 0:
+# optimizedPath = pm.workspace.path / pm.workspace.fileRules['renderData'] / "optimizedTextures"
+# if not os.path.exists(optimizedPath):
+# optimizedPath.makedirs()
+# self.renderGlobalsNode.optimizedTexturePath.set(str(optimizedPath))
+#
+# #craete optimized exr textures
+# optimizeTextures.preRenderOptimizeTextures(optimizedFilePath = self.renderGlobalsNode.optimizedTexturePath.get())
+
+ def postRenderProcedure(self):
+ pass
+# optimizeTextures.postRenderOptimizeTextures()
+
+
+def theRenderer():
+ return KrayRenderer.theRenderer()
+
+def initRenderer():
+ try:
+ log.debug("Init renderer Kray")
+ theRenderer().registerRenderer()
+ except:
+ traceback.print_exc(file=sys.__stderr__)
+ log.error("Init renderer Kray FAILED")
+
+def unregister():
+ theRenderer().unRegisterRenderer()
+ log.debug("Unregister done")
+
View
99 src/mayaToKray/mtkr_devmodule/scripts/optimizeTextures.py
@@ -0,0 +1,99 @@
+import pymel.core as pm
+import path
+import logging
+import os
+import subprocess
+import shutil
+
+log = logging.getLogger("krayLogger")
+
+def isOlderThan(fileA, fileB):
+ return path.path(fileA).mtime < path.path(fileB).mtime
+
+def makeExr( filePath, exrFile ):
+ log.debug("Convert %s to exr %s" % (filePath, exrFile))
+
+ #TODO:currently use mentalrays imf_copy, maybe there is a better way...
+ cmd = "\"" + os.environ['MENTALRAY_LOCATION'] + "bin/imf_copy\" "
+ cmd += filePath + " " + exrFile
+ log.debug(cmd)
+ try:
+ if subprocess.call(cmd, shell = True) is not 0:
+ log.error("Conversion failed")
+ return False
+ except:
+ log.warning("Conversion to exr failed " + str(sys.exc_info()[0]) + " - skipping")
+ return False
+ return True
+
+def preRenderOptimizeTextures(destFormat = "exr", optimizedFilePath = ""):
+ for fileTexture in pm.ls(type="file"):
+ fileNamePath = path.path(fileTexture.fileTextureName.get())
+ log.debug("Check file texture:" + fileNamePath)
+
+ if not fileNamePath.exists():
+ log.debug("file texture could not be found, skipping.")
+ continue
+
+ if fileNamePath.ext[1:] == destFormat:
+ log.debug("file texture is already an " + destFormat + " skipping.")
+ continue
+
+ if fileTexture.useFrameExtension.get():
+ log.debug("file texture is animated skipping.")
+ continue
+
+ # path will contain either contain a leading slash for
+ # unix /server/textures/file.exr
+ # or a drive in windows like c:
+ # or a dfs name like //server/textures....
+ optimizedFilePath = path.path(optimizedFilePath)
+ log.debug("optimizedFilePath " + optimizedFilePath)
+ if fileNamePath[1] == ":":
+ localPath = optimizedFilePath / fileNamePath[3:]
+ if fileNamePath.startswith("//"):
+ localPath = optimizedFilePath / fileNamePath[2:]
+ if fileNamePath.startswith("/"):
+ localPath = optimizedFilePath / fileNamePath[1:]
+ localPath += ".exr"
+ localPath = path.path(localPath)
+ log.debug("local path " + localPath.realpath())
+ localPath = localPath.realpath()
+
+ doConvert = True
+ if localPath.exists():
+ if isOlderThan(fileNamePath, localPath):
+ log.debug(localPath + " already exists and is older then original file. No conversion needed.")
+ doConvert = False
+
+ if doConvert:
+ # make it a exr
+ if not makeExr(fileNamePath.realpath(), path.path(localPath.replace(".exr", "_t.exr")).realpath()):
+ log.debug("Problem converting " + fileNamePath)
+ continue
+
+ #shutil.copy(localPath.replace(".exr", "_t.exr"), localPath)
+ # executable: maketiledexr(.exe)
+ cmd = "maketiledexr"
+
+ cmd += " " + localPath.replace(".exr", "_t.exr") + " " + localPath
+
+ try:
+ subprocess.call(cmd, shell = True)
+ except:
+ log.warning("Conversion to tiled exr failed " + str(sys.exc_info()[0]) + " - skipping")
+ continue
+
+ os.remove(localPath.replace(".exr", "_t.exr"))
+
+ if not fileTexture.hasAttr("origFilePath"):
+ fileTexture.addAttr("origFilePath", dt="string")
+ fileTexture.origFilePath.set(fileNamePath)
+ fileTexture.fileTextureName.set(localPath)
+
+def postRenderOptimizeTextures():
+ for fileTexture in pm.ls(type="file"):
+ if fileTexture.hasAttr("origFilePath"):
+ fileTexture.fileTextureName.set(fileTexture.origFilePath.get())
+ fileTexture.origFilePath.delete()
+
View
1,054 src/mayaToKray/mtkr_devmodule/scripts/path.py
@@ -0,0 +1,1054 @@
+#
+# Copyright (c) 2010 Mikhail Gusarov
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+
+""" path.py - An object representing a path to a file or directory.
+
+Original author:
+ Jason Orendorff <jason.orendorff\x40gmail\x2ecom>
+
+Contributors:
+ Mikhail Gusarov <dottedmag@dottedmag.net>
+ Marc Abramowitz <marc@marc-abramowitz.com>
+
+Example:
+
+from path import path
+d = path('/home/guido/bin')
+for f in d.files('*.py'):
+ f.chmod(0755)
+
+This module requires Python 2.3 or later.
+"""
+
+from __future__ import generators
+
+import sys
+import warnings
+import os
+import fnmatch
+import glob
+import shutil
+import codecs
+import hashlib
+import errno
+
+__version__ = '2.4.1'
+__all__ = ['path']
+
+# Platform-specific support for path.owner
+if os.name == 'nt':
+ try:
+ import win32security
+ except ImportError:
+ win32security = None
+else:
+ try:
+ import pwd
+ except ImportError:
+ pwd = None
+
+# Pre-2.3 support. Are unicode filenames supported?
+_base = str
+_getcwd = os.getcwd
+try:
+ if os.path.supports_unicode_filenames:
+ _base = unicode
+ _getcwd = os.getcwdu
+except AttributeError:
+ pass
+
+# Pre-2.3 workaround for basestring.
+try:
+ basestring
+except NameError:
+ basestring = (str, unicode)
+
+# Universal newline support
+_textmode = 'U'
+if hasattr(__builtins__, 'file') and not hasattr(file, 'newlines'):
+ _textmode = 'r'
+
+class TreeWalkWarning(Warning):
+ pass
+
+class path(_base):
+ """ Represents a filesystem path.
+
+ For documentation on individual methods, consult their
+ counterparts in os.path.
+ """
+
+ # --- Special Python methods.
+
+ def __repr__(self):
+ return 'path(%s)' % _base.__repr__(self)
+
+ # Adding a path and a string yields a path.
+ def __add__(self, more):
+ try:
+ resultStr = _base.__add__(self, more)
+ except TypeError: # Python bug
+ resultStr = NotImplemented
+ if resultStr is NotImplemented:
+ return resultStr
+ return self.__class__(resultStr)
+
+ def __radd__(self, other):
+ if isinstance(other, basestring):
+ return self.__class__(other.__add__(self))
+ else:
+ return NotImplemented
+
+ # The / operator joins paths.
+ def __div__(self, rel):
+ """ fp.__div__(rel) == fp / rel == fp.joinpath(rel)
+
+ Join two path components, adding a separator character if
+ needed.
+ """
+ return self.__class__(os.path.join(self, rel))
+
+ # Make the / operator work even when true division is enabled.
+ __truediv__ = __div__
+
+ def __enter__(self):
+ self._old_dir = self.getcwd()
+ os.chdir(self)
+
+ def __exit__(self, *_):
+ os.chdir(self._old_dir)
+
+ def getcwd(cls):
+ """ Return the current working directory as a path object. """
+ return cls(_getcwd())
+ getcwd = classmethod(getcwd)
+
+ #
+ # --- Operations on path strings.
+
+ def abspath(self): return self.__class__(os.path.abspath(self))
+ def normcase(self): return self.__class__(os.path.normcase(self))
+ def normpath(self): return self.__class__(os.path.normpath(self))
+ def realpath(self): return self.__class__(os.path.realpath(self))
+ def expanduser(self): return self.__class__(os.path.expanduser(self))
+ def expandvars(self): return self.__class__(os.path.expandvars(self))
+ def dirname(self): return self.__class__(os.path.dirname(self))
+ def basename(self): return self.__class__(os.path.basename(self))
+
+ def expand(self):
+ """ Clean up a filename by calling expandvars(),
+ expanduser(), and normpath() on it.
+
+ This is commonly everything needed to clean up a filename
+ read from a configuration file, for example.
+ """
+ return self.expandvars().expanduser().normpath()
+
+ def _get_namebase(self):
+ base, ext = os.path.splitext(self.name)
+ return base
+
+ def _get_ext(self):
+ f, ext = os.path.splitext(_base(self))
+ return ext
+
+ def _get_drive(self):
+ drive, r = os.path.splitdrive(self)
+ return self.__class__(drive)
+
+ parent = property(
+ dirname, None, None,
+ """ This path's parent directory, as a new path object.
+
+ For example, path('/usr/local/lib/libpython.so').parent == path('/usr/local/lib')
+ """)
+
+ name = property(
+ basename, None, None,
+ """ The name of this file or directory without the full path.
+
+ For example, path('/usr/local/lib/libpython.so').name == 'libpython.so'
+ """)
+
+ namebase = property(
+ _get_namebase, None, None,
+ """ The same as path.name, but with one file extension stripped off.
+
+ For example, path('/home/guido/python.tar.gz').name == 'python.tar.gz',
+ but path('/home/guido/python.tar.gz').namebase == 'python.tar'
+ """)
+
+ ext = property(
+ _get_ext, None, None,
+ """ The file extension, for example '.py'. """)
+
+ drive = property(
+ _get_drive, None, None,
+ """ The drive specifier, for example 'C:'.
+ This is always empty on systems that don't use drive specifiers.
+ """)
+
+ def splitpath(self):
+ """ p.splitpath() -> Return (p.parent, p.name). """
+ parent, child = os.path.split(self)
+ return self.__class__(parent), child
+
+ def splitdrive(self):
+ """ p.splitdrive() -> Return (p.drive, <the rest of p>).
+
+ Split the drive specifier from this path. If there is
+ no drive specifier, p.drive is empty, so the return value
+ is simply (path(''), p). This is always the case on Unix.
+ """
+ drive, rel = os.path.splitdrive(self)
+ return self.__class__(drive), rel
+
+ def splitext(self):
+ """ p.splitext() -> Return (p.stripext(), p.ext).
+
+ Split the filename extension from this path and return
+ the two parts. Either part may be empty.
+
+ The extension is everything from '.' to the end of the
+ last path segment. This has the property that if
+ (a, b) == p.splitext(), then a + b == p.
+ """
+ filename, ext = os.path.splitext(self)
+ return self.__class__(filename), ext
+
+ def stripext(self):
+ """ p.stripext() -> Remove one file extension from the path.
+
+ For example, path('/home/guido/python.tar.gz').stripext()
+ returns path('/home/guido/python.tar').
+ """
+ return self.splitext()[0]
+
+ if hasattr(os.path, 'splitunc'):
+ def splitunc(self):
+ unc, rest = os.path.splitunc(self)
+ return self.__class__(unc), rest
+
+ def _get_uncshare(self):
+ unc, r = os.path.splitunc(self)
+ return self.__class__(unc)
+
+ uncshare = property(
+ _get_uncshare, None, None,
+ """ The UNC mount point for this path.
+ This is empty for paths on local drives. """)
+
+ def joinpath(self, *args):
+ """ Join two or more path components, adding a separator
+ character (os.sep) if needed. Returns a new path
+ object.
+ """
+ return self.__class__(os.path.join(self, *args))
+
+ def splitall(self):
+ r""" Return a list of the path components in this path.
+
+ The first item in the list will be a path. Its value will be
+ either os.curdir, os.pardir, empty, or the root directory of
+ this path (for example, '/' or 'C:\\'). The other items in
+ the list will be strings.
+
+ path.path.joinpath(*result) will yield the original path.
+ """
+ parts = []
+ loc = self
+ while loc != os.curdir and loc != os.pardir:
+ prev = loc
+ loc, child = prev.splitpath()
+ if loc == prev:
+ break
+ parts.append(child)
+ parts.append(loc)
+ parts.reverse()
+ return parts
+
+ def relpath(self):
+ """ Return this path as a relative path,
+ based from the current working directory.
+ """
+ cwd = self.__class__(os.getcwd())
+ return cwd.relpathto(self)
+
+ def relpathto(self, dest):
+ """ Return a relative path from self to dest.
+
+ If there is no relative path from self to dest, for example if
+ they reside on different drives in Windows, then this returns
+ dest.abspath().
+ """
+ origin = self.abspath()
+ dest = self.__class__(dest).abspath()
+
+ orig_list = origin.normcase().splitall()
+ # Don't normcase dest! We want to preserve the case.
+ dest_list = dest.splitall()
+
+ if orig_list[0] != os.path.normcase(dest_list[0]):
+ # Can't get here from there.
+ return dest
+
+ # Find the location where the two paths start to differ.
+ i = 0
+ for start_seg, dest_seg in zip(orig_list, dest_list):
+ if start_seg != os.path.normcase(dest_seg):
+ break
+ i += 1
+
+ # Now i is the point where the two paths diverge.
+ # Need a certain number of "os.pardir"s to work up
+ # from the origin to the point of divergence.
+ segments = [os.pardir] * (len(orig_list) - i)
+ # Need to add the diverging part of dest_list.
+ segments += dest_list[i:]
+ if len(segments) == 0:
+ # If they happen to be identical, use os.curdir.
+ relpath = os.curdir
+ else:
+ relpath = os.path.join(*segments)
+ return self.__class__(relpath)
+
+ # --- Listing, searching, walking, and matching
+
+ def listdir(self, pattern=None):
+ """ D.listdir() -> List of items in this directory.
+
+ Use D.files() or D.dirs() instead if you want a listing
+ of just files or just subdirectories.
+
+ The elements of the list are path objects.
+
+ With the optional 'pattern' argument, this only lists
+ items whose names match the given pattern.
+ """
+ names = os.listdir(self)
+ if pattern is not None:
+ names = fnmatch.filter(names, pattern)
+ return [self / child for child in names]
+
+ def dirs(self, pattern=None):
+ """ D.dirs() -> List of this directory's subdirectories.
+
+ The elements of the list are path objects.
+ This does not walk recursively into subdirectories
+ (but see path.walkdirs).
+
+ With the optional 'pattern' argument, this only lists
+ directories whose names match the given pattern. For
+ example, d.dirs('build-*').
+ """
+ return [p for p in self.listdir(pattern) if p.isdir()]
+
+ def files(self, pattern=None):
+ """ D.files() -> List of the files in this directory.
+
+ The elements of the list are path objects.
+ This does not walk into subdirectories (see path.walkfiles).
+
+ With the optional 'pattern' argument, this only lists files
+ whose names match the given pattern. For example,
+ d.files('*.pyc').
+ """
+
+ return [p for p in self.listdir(pattern) if p.isfile()]
+
+ def walk(self, pattern=None, errors='strict'):
+ """ D.walk() -> iterator over files and subdirs, recursively.
+
+ The iterator yields path objects naming each child item of
+ this directory and its descendants. This requires that
+ D.isdir().
+
+ This performs a depth-first traversal of the directory tree.
+ Each directory is returned just before all its children.
+
+ The errors= keyword argument controls behavior when an
+ error occurs. The default is 'strict', which causes an
+ exception. The other allowed values are 'warn', which
+ reports the error via warnings.warn(), and 'ignore'.
+ """
+ if errors not in ('strict', 'warn', 'ignore'):
+ raise ValueError("invalid errors parameter")
+
+ try:
+ childList = self.listdir()
+ except Exception:
+ if errors == 'ignore':
+ return
+ elif errors == 'warn':
+ warnings.warn(
+ "Unable to list directory '%s': %s"
+ % (self, sys.exc_info()[1]),
+ TreeWalkWarning)
+ return
+ else:
+ raise
+
+ for child in childList:
+ if pattern is None or child.fnmatch(pattern):
+ yield child
+ try:
+ isdir = child.isdir()
+ except Exception:
+ if errors == 'ignore':
+ isdir = False
+ elif errors == 'warn':
+ warnings.warn(
+ "Unable to access '%s': %s"
+ % (child, sys.exc_info()[1]),
+ TreeWalkWarning)
+ isdir = False
+ else:
+ raise
+
+ if isdir:
+ for item in child.walk(pattern, errors):
+ yield item
+
+ def walkdirs(self, pattern=None, errors='strict'):
+ """ D.walkdirs() -> iterator over subdirs, recursively.
+
+ With the optional 'pattern' argument, this yields only
+ directories whose names match the given pattern. For
+ example, mydir.walkdirs('*test') yields only directories
+ with names ending in 'test'.
+
+ The errors= keyword argument controls behavior when an
+ error occurs. The default is 'strict', which causes an
+ exception. The other allowed values are 'warn', which
+ reports the error via warnings.warn(), and 'ignore'.
+ """
+ if errors not in ('strict', 'warn', 'ignore'):
+ raise ValueError("invalid errors parameter")
+
+ try:
+ dirs = self.dirs()
+ except Exception:
+ if errors == 'ignore':
+ return
+ elif errors == 'warn':
+ warnings.warn(
+ "Unable to list directory '%s': %s"
+ % (self, sys.exc_info()[1]),
+ TreeWalkWarning)
+ return
+ else:
+ raise
+
+ for child in dirs:
+ if pattern is None or child.fnmatch(pattern):
+ yield child
+ for subsubdir in child.walkdirs(pattern, errors):
+ yield subsubdir
+
+ def walkfiles(self, pattern=None, errors='strict'):
+ """ D.walkfiles() -> iterator over files in D, recursively.
+
+ The optional argument, pattern, limits the results to files
+ with names that match the pattern. For example,
+ mydir.walkfiles('*.tmp') yields only files with the .tmp
+ extension.
+ """
+ if errors not in ('strict', 'warn', 'ignore'):
+ raise ValueError("invalid errors parameter")
+
+ try:
+ childList = self.listdir()
+ except Exception:
+ if errors == 'ignore':
+ return
+ elif errors == 'warn':
+ warnings.warn(
+ "Unable to list directory '%s': %s"
+ % (self, sys.exc_info()[1]),
+ TreeWalkWarning)
+ return
+ else:
+ raise
+
+ for child in childList:
+ try:
+ isfile = child.isfile()
+ isdir = not isfile and child.isdir()
+ except:
+ if errors == 'ignore':
+ continue
+ elif errors == 'warn':
+ warnings.warn(
+ "Unable to access '%s': %s"
+ % (self, sys.exc_info()[1]),
+ TreeWalkWarning)
+ continue
+ else:
+ raise
+
+ if isfile:
+ if pattern is None or child.fnmatch(pattern):
+ yield child
+ elif isdir:
+ for f in child.walkfiles(pattern, errors):
+ yield f
+
+ def fnmatch(self, pattern):
+ """ Return True if self.name matches the given pattern.
+
+ pattern - A filename pattern with wildcards,
+ for example '*.py'.
+ """
+ return fnmatch.fnmatch(self.name, pattern)
+
+ def glob(self, pattern):
+ """ Return a list of path objects that match the pattern.
+
+ pattern - a path relative to this directory, with wildcards.
+
+ For example, path('/users').glob('*/bin/*') returns a list
+ of all the files users have in their bin directories.
+ """
+ cls = self.__class__
+ return [cls(s) for s in glob.glob(_base(self / pattern))]
+
+ #
+ # --- Reading or writing an entire file at once.
+
+ def open(self, mode='r'):
+ """ Open this file. Return a file object. """
+ return open(self, mode)
+
+ def bytes(self):
+ """ Open this file, read all bytes, return them as a string. """
+ f = self.open('rb')
+ try:
+ return f.read()
+ finally:
+ f.close()
+
+ def write_bytes(self, bytes, append=False):
+ """ Open this file and write the given bytes to it.
+
+ Default behavior is to overwrite any existing file.
+ Call p.write_bytes(bytes, append=True) to append instead.
+ """
+ if append:
+ mode = 'ab'
+ else:
+ mode = 'wb'
+ f = self.open(mode)
+ try:
+ f.write(bytes)
+ finally:
+ f.close()
+
+ def text(self, encoding=None, errors='strict'):
+ r""" Open this file, read it in, return the content as a string.
+
+ This uses 'U' mode in Python 2.3 and later, so '\r\n' and '\r'
+ are automatically translated to '\n'.
+
+ Optional arguments:
+
+ encoding - The Unicode encoding (or character set) of
+ the file. If present, the content of the file is
+ decoded and returned as a unicode object; otherwise
+ it is returned as an 8-bit str.
+ errors - How to handle Unicode errors; see help(str.decode)
+ for the options. Default is 'strict'.
+ """
+ if encoding is None:
+ # 8-bit
+ f = self.open(_textmode)
+ try:
+ return f.read()
+ finally:
+ f.close()
+ else:
+ # Unicode
+ f = codecs.open(self, 'r', encoding, errors)
+ # (Note - Can't use 'U' mode here, since codecs.open
+ # doesn't support 'U' mode, even in Python 2.3.)
+ try:
+ t = f.read()
+ finally:
+ f.close()
+ return (t.replace(u'\r\n', u'\n')
+ .replace(u'\r\x85', u'\n')
+ .replace(u'\r', u'\n')
+ .replace(u'\x85', u'\n')
+ .replace(u'\u2028', u'\n'))
+
+ def write_text(self, text, encoding=None, errors='strict', linesep=os.linesep, append=False):
+ r""" Write the given text to this file.
+
+ The default behavior is to overwrite any existing file;
+ to append instead, use the 'append=True' keyword argument.
+
+ There are two differences between path.write_text() and
+ path.write_bytes(): newline handling and Unicode handling.
+ See below.
+
+ Parameters:
+
+ - text - str/unicode - The text to be written.
+
+ - encoding - str - The Unicode encoding that will be used.
+ This is ignored if 'text' isn't a Unicode string.
+
+ - errors - str - How to handle Unicode encoding errors.
+ Default is 'strict'. See help(unicode.encode) for the
+ options. This is ignored if 'text' isn't a Unicode
+ string.
+
+ - linesep - keyword argument - str/unicode - The sequence of
+ characters to be used to mark end-of-line. The default is
+ os.linesep. You can also specify None; this means to
+ leave all newlines as they are in 'text'.
+
+ - append - keyword argument - bool - Specifies what to do if
+ the file already exists (True: append to the end of it;
+ False: overwrite it.) The default is False.
+
+
+ --- Newline handling.
+
+ write_text() converts all standard end-of-line sequences
+ ('\n', '\r', and '\r\n') to your platform's default end-of-line
+ sequence (see os.linesep; on Windows, for example, the
+ end-of-line marker is '\r\n').
+
+ If you don't like your platform's default, you can override it
+ using the 'linesep=' keyword argument. If you specifically want
+ write_text() to preserve the newlines as-is, use 'linesep=None'.
+
+ This applies to Unicode text the same as to 8-bit text, except
+ there are three additional standard Unicode end-of-line sequences:
+ u'\x85', u'\r\x85', and u'\u2028'.
+
+ (This is slightly different from when you open a file for
+ writing with fopen(filename, "w") in C or open(filename, 'w')
+ in Python.)
+
+
+ --- Unicode
+
+ If 'text' isn't Unicode, then apart from newline handling, the
+ bytes are written verbatim to the file. The 'encoding' and
+ 'errors' arguments are not used and must be omitted.
+
+ If 'text' is Unicode, it is first converted to bytes using the
+ specified 'encoding' (or the default encoding if 'encoding'
+ isn't specified). The 'errors' argument applies only to this
+ conversion.
+
+ """
+ if isinstance(text, unicode):
+ if linesep is not None:
+ # Convert all standard end-of-line sequences to
+ # ordinary newline characters.
+ text = (text.replace(u'\r\n', u'\n')
+ .replace(u'\r\x85', u'\n')
+ .replace(u'\r', u'\n')
+ .replace(u'\x85', u'\n')
+ .replace(u'\u2028', u'\n'))
+ text = text.replace(u'\n', linesep)
+ if encoding is None:
+ encoding = sys.getdefaultencoding()
+ bytes = text.encode(encoding, errors)
+ else:
+ # It is an error to specify an encoding if 'text' is
+ # an 8-bit string.
+ assert encoding is None
+
+ if linesep is not None:
+ text = (text.replace('\r\n', '\n')
+ .replace('\r', '\n'))
+ bytes = text.replace('\n', linesep)
+
+ self.write_bytes(bytes, append)
+
+ def lines(self, encoding=None, errors='strict', retain=True):
+ r""" Open this file, read all lines, return them in a list.
+
+ Optional arguments:
+ encoding - The Unicode encoding (or character set) of
+ the file. The default is None, meaning the content
+ of the file is read as 8-bit characters and returned
+ as a list of (non-Unicode) str objects.
+ errors - How to handle Unicode errors; see help(str.decode)
+ for the options. Default is 'strict'
+ retain - If true, retain newline characters; but all newline
+ character combinations ('\r', '\n', '\r\n') are
+ translated to '\n'. If false, newline characters are
+ stripped off. Default is True.
+
+ This uses 'U' mode in Python 2.3 and later.
+ """
+ if encoding is None and retain:
+ f = self.open(_textmode)
+ try:
+ return f.readlines()
+ finally:
+ f.close()
+ else:
+ return self.text(encoding, errors).splitlines(retain)
+
+ def write_lines(self, lines, encoding=None, errors='strict',
+ linesep=os.linesep, append=False):
+ r""" Write the given lines of text to this file.
+
+ By default this overwrites any existing file at this path.
+
+ This puts a platform-specific newline sequence on every line.
+ See 'linesep' below.
+
+ lines - A list of strings.
+
+ encoding - A Unicode encoding to use. This applies only if
+ 'lines' contains any Unicode strings.
+
+ errors - How to handle errors in Unicode encoding. This
+ also applies only to Unicode strings.
+
+ linesep - The desired line-ending. This line-ending is
+ applied to every line. If a line already has any
+ standard line ending ('\r', '\n', '\r\n', u'\x85',
+ u'\r\x85', u'\u2028'), that will be stripped off and
+ this will be used instead. The default is os.linesep,
+ which is platform-dependent ('\r\n' on Windows, '\n' on
+ Unix, etc.) Specify None to write the lines as-is,
+ like file.writelines().
+
+ Use the keyword argument append=True to append lines to the
+ file. The default is to overwrite the file. Warning:
+ When you use this with Unicode data, if the encoding of the
+ existing data in the file is different from the encoding
+ you specify with the encoding= parameter, the result is
+ mixed-encoding data, which can really confuse someone trying
+ to read the file later.
+ """
+ if append:
+ mode = 'ab'
+ else:
+ mode = 'wb'
+ f = self.open(mode)
+ try:
+ for line in lines:
+ isUnicode = isinstance(line, unicode)
+ if linesep is not None:
+ # Strip off any existing line-end and add the
+ # specified linesep string.
+ if isUnicode:
+ if line[-2:] in (u'\r\n', u'\x0d\x85'):
+ line = line[:-2]
+ elif line[-1:] in (u'\r', u'\n',
+ u'\x85', u'\u2028'):
+ line = line[:-1]
+ else:
+ if line[-2:] == '\r\n':
+ line = line[:-2]
+ elif line[-1:] in ('\r', '\n'):
+ line = line[:-1]
+ line += linesep
+ if isUnicode:
+ if encoding is None:
+ encoding = sys.getdefaultencoding()
+ line = line.encode(encoding, errors)
+ f.write(line)
+ finally:
+ f.close()
+
+ def read_md5(self):
+ """ Calculate the md5 hash for this file.
+
+ This reads through the entire file.
+ """
+ return self.read_hash('md5')
+
+ def _hash(self, hash_name):
+ f = self.open('rb')
+ try:
+ m = hashlib.new(hash_name)
+ while True:
+ d = f.read(8192)
+ if not d:
+ break
+ m.update(d)
+ return m
+ finally:
+ f.close()
+
+ def read_hash(self, hash_name):
+ """ Calculate given hash for this file.
+
+ List of supported hashes can be obtained from hashlib package. This
+ reads the entire file.
+ """
+ return self._hash(hash_name).digest()
+
+ def read_hexhash(self, hash_name):
+ """ Calculate given hash for this file, returning hexdigest.
+
+ List of supported hashes can be obtained from hashlib package. This
+ reads the entire file.
+ """
+ return self._hash(hash_name).hexdigest()
+
+ # --- Methods for querying the filesystem.
+ # N.B. On some platforms, the os.path functions may be implemented in C
+ # (e.g. isdir on Windows, Python 3.2.2), and compiled functions don't get
+ # bound. Playing it safe and wrapping them all in method calls.
+
+ def isabs(self): return os.path.isabs(self)
+ def exists(self): return os.path.exists(self)
+ def isdir(self): return os.path.isdir(self)
+ def isfile(self): return os.path.isfile(self)
+ def islink(self): return os.path.islink(self)
+ def ismount(self): return os.path.ismount(self)
+
+ if hasattr(os.path, 'samefile'):
+ def samefile(self): return os.path.samefile(self)
+
+ def getatime(self): return os.path.getatime(self)
+ atime = property(
+ getatime, None, None,
+ """ Last access time of the file. """)
+
+ def getmtime(self): return os.path.getmtime(self)
+ mtime = property(
+ getmtime, None, None,
+ """ Last-modified time of the file. """)
+
+ if hasattr(os.path, 'getctime'):
+ def getctime(self): return os.path.getctime(self)
+ ctime = property(
+ getctime, None, None,
+ """ Creation time of the file. """)
+
+ def getsize(self): return os.path.getsize(self)
+ size = property(
+ getsize, None, None,
+ """ Size of the file, in bytes. """)
+
+ if hasattr(os, 'access