Learning to script DAZ Studio...
Greetings,
I'm trying to learn to script DAZ Studio, and there seemed to be no function references for various objects. Maybe I missed them, but I really did try to find them in the documentation section. So I decided to try and find what functions I could, and reverse engineer them as much as possible. Historically I've found that functions are usually very descriptive, even without docs, and with a little guesswork and trial and error, you can make sense of how to use them.
So I'm creating this thread to track my explorations, not terribly dissimilar to a art forum render thread. Hopefully I will update it as I go with interesting stuff I learn/find.
And thus I present my first useful piece of code in DAZ Script. (It's actually pretty generic JavaScript, but it's a start. Also I'm over semi-colon-ing, but that seems to be the style.)
Dump all methods and members of an object; especially useful on the Scene object.
function dumpBehavior(obj) {
var properties = new RegExp("([a-zA-Z0-9]+(\\(.*?\\))?),", "g");
print(Object.getOwnPropertyNames(obj).sort().toString().replace(properties, "$1\n"));
}
dumpBehavior(Scene);
This gave me:
DefaultMethod
DzIncludeAllFlag
DzIncludeCamerasFlag
DzIncludeLightsFlag
DzIncludeNonShadowersFlag
DzIncludeNonVisibleFlag
DzObjectsOnly
MergeFile
OpenNew
aboutToRemoveNode(DzNode*)
aboutToRender(DzRenderer*)
addDataItem(DzSceneData*)
addNode(DzNode*)
addWSModifier(DzWSModifier*)
addWSModifier(DzWSModifier*,int)
animRangeChanged(DzTimeRange)
assetModified()
assetWasSaved()
beginTimeEdit()
cameraAdded(DzCamera*)
cameraListChanged()
cameraRemoved(DzCamera*)
cameraSelectionListChanged()
className()
clear()
clearDebugPoints()
currentTimeChanged(DzTime,DzTime)
deleteLater()
destroyed()
destroyed(QObject*)
drawnDataChanged()
findCamera(QString)
findCameraByLabel(QString)
findDataItem(QString)
findLight(QString)
findLightByLabel(QString)
findNode(QString)
findNodeByLabel(QString)
findNodeIndex(const DzNode*)
findSkeleton(QString)
findSkeletonByLabel(QString)
findSkeletonIndex(const DzSkeleton*)
finishTimeEdit()
getAnimRange()
getAssetLoadPath()
getAssetLoadPath(bool*)
getAudio()
getAudioStartFrame()
getBackdrop()
getBoundingBox()
getBoundingBox(int)
getCamera(int)
getCameraList()
getDataItem(int)
getFilename()
getFilename(bool*)
getFrame()
getHighlightNode()
getLight(int)
getLightList()
getName()
getNode(int)
getNodeList()
getNumCameras()
getNumDataItems()
getNumLights()
getNumNodes()
getNumSelectedCameras()
getNumSelectedLights()
getNumSelectedNodes()
getNumSelectedSkeletons()
getNumSelectedTimeRanges()
getNumSkeletons()
getNumStorablesInScene()
getNumWSModifiers()
getPlayRange()
getPreviewLights()
getPrimarySelection()
getSelectedCamera(int)
getSelectedCameraList()
getSelectedLight(int)
getSelectedLightList()
getSelectedNode(int)
getSelectedNodeList()
getSelectedSkeleton(int)
getSelectedSkeletonList()
getSkeleton(int)
getSkeletonList()
getSortedLightList()
getTime()
getTimeStep()
getUniqueTopLevelLabel(QString)
getUniqueTopLevelLabel(QString,DzNode*)
getWSModifier(int)
getWSModifierList()
highlightNodeChanged(DzNode*)
inherits(QString)
invalidate()
invalidateLightSorting()
isClearing()
isDAZLoading()
isLoading()
isLoopingEnabled()
isPlaying()
iskindof(QString)
lightAdded(DzLight*)
lightListChanged()
lightRemoved(DzLight*)
lightSelectionListChanged()
loadScene(QString,DzOpenMethod)
loopPlayback(bool)
loopPlaybackChanged(bool)
makePersistent()
markChanged()
materialListChanged()
materialSelectionChanged()
name
nameChanged(QString)
needsSave()
nodeAdded(DzNode*)
nodeListChanged()
nodeRemoved(DzNode*)
nodeSelectionListChanged()
objectName
pause()
play()
play(bool)
playRangeChanged(DzTimeRange)
playbackFinished()
playbackStarted()
primarySelectionChanged(DzNode*)
removeAllCameras()
removeAllLights()
removeDataItem(DzSceneData*)
removeNode(DzNode*)
removeSelected()
removeWSModifier(DzWSModifier*)
renderFinished(DzRenderer*)
saveScene()
saveScene(QString)
saveThumbnail(QString)
sceneClearStarting()
sceneCleared()
sceneFilenameChanged(QString)
sceneLoadStarting()
sceneLoaded()
sceneSaveStarting(QString)
sceneSaved(QString)
sceneTopologyChanged()
selectAllNodes(bool)
selectAllSkeletons(bool)
selectAllTime(bool)
setAnimRange(DzTimeRange)
setAssetLoadPath(QString)
setAudio(DzAudioClip*)
setAudio(DzAudioClip*,int)
setBackdrop(DzBackdrop*)
setDebugPoints(int,QColor,const DzPnt3*,int)
setDebugPoints(int,QColor,const DzPnt3*,int,DzMatrix3)
setFrame(int)
setHighlightNode(DzNode*)
setPlayRange(DzTimeRange)
setPreviewLights(bool)
setPrimarySelection(DzNode*)
setTime(DzTime)
setTimeStep(DzTime)
skeletonAdded(DzSkeleton*)
skeletonListChanged()
skeletonRemoved(DzSkeleton*)
skeletonSelectionListChanged()
stepTime()
stepTime(int)
stepTime(int,bool)
stripLabelNumber(QString)
timeChanged(DzTime)
timeChanging(DzTime)
timeSelectionChanged()
timeStepChanged(DzTime)
update()
wsModifierAdded(DzWSModifier*)
wsModifierRemoved(DzWSModifier*)
wsModifierStackChanged()
...which gives me a good starting point to investigate.Is there a top-level object 'above' scene, like something which owns the currently selected camera, etc...?
-- Morgan
Comments
Greetings,
Yes.
You can get to it via:
Some example code, to cycle through available user cameras:
That's all for tonight, I think. Although I did discover how to 'hear' when a camera change is made, so let's list that here also:
Now that's really all.
-- Morgan
The DS3 docs are still available from the script reference section in the Documentation centre, since the DS3 docs aren't. They cover a lot, though there have been significant changes to accommodate TriAx figures - I would strongly urge using object.inherits( classname ) rather than object.className() == string to avoid many issues.
Greetings,
Thanks! That was helpful... I now know how to set the aspect ratio programmatically. Can you tell me how to get a script in the Script IDE to remain...running?Specifically, I have this code:
with the eventual intent of extracting the aspect ratio from the camera name, or some other camera property. However, I can't get it to remain running. Is there a trick to getting a signal/slot installed and retained from the Script IDE, or is it something where I just have to put it in a startup script or something and restart every time I change it?That script works, but only during the time it's running, as soon as the Script IDE stops running it, it doesn't trap the camera change anymore.
What am I missing?
-- Morgan
It should be possible to have a script triggered by an event, but I know it was problematic at one point (there's probably a thread on it in the old forum's Developer Discussion). It's not something I've ever tried, so I can't offer any advice.
Greetings,
Thanks for the approximate pointer! I found this article by rbtwhiz by using the keywords you mentioned and judicious googling... The entire script now looks like this:
If you include '(16x9)', '(16,9)', '(4x3)', '(8x11)', etc., in the name of your camera, it will set the aspect ratio to that when you switch to that camera. (So, for example, I have 'Whole Scene (16x9)' as a camera and 'Closeup (3x4)' as another...) It supports both (##x##) and (##,##) formats.
Thanks very much for the help!
-- Morgan
Now I need to bookmark this thread so I can find it when I want that info :)
Greetings,
I made a small tweak, it wasn't properly propagating the aspect ratio to the pixels themselves, so I fixed that. It operates on the theory that the GCD between the pixel sizes is the old multiplier times the ratios, so it preserves that multiplier to whatever aspect ratio you set. This avoids unchecked resolution inflation as you change cameras.
So if you've started with 4x3 and 1024x68, you have a 256 multiplier. This means that if you switch to 16x9 it will go to 4096x2304, but if you switch back to 4x3 it'll be 1024x768 again. I couldn't think of a better algorithm to preserve your expected size, offhand. I could, I suppose, preserve the larger dimension, but then it's possible to change from 4x3 to 3x4 over and over and get resolution inflation each cycle. :)
The best answer would be to preserve the resolution somehow associated with the previous camera... No idea how to do that yet. :)
-- Morgan
You can create numeric properties on the camera... Then use the value changed signal from the properties to trigger a callback that sets the other properties and triggers updates to render settings.
-Rob
thank you morgan, richard & rob for all this information.
regarding using the DS3 documentation, is this the correct link?
http://docs.daz3d.com/lib/exe/fetch.php/public/software/dazstudio/3/ds3_daz_script_development_kit_3.0.1.144_docs.zip
if so, then i am on the right track, but it would help me if someone could tell whether a couple of things are possible or impossible:
1) i am trying to automate certain actions and need to find the function references in particular for 'Restore Figure Shape' - is this function exposed in the script API? in the list that i get from running morgan's object function list code (for which many thanks), i don't see anything connected with 'Restore'. i would be very grateful to know what the function name is. if it is not available, is that avenue closed?
2) i would like to be able to assign keyboard shortcuts to items not listed in Window > Workspace > Customize - again, 'Restore Figure Shape' would be one of them - sometimes i just need to do the action a couple of times, and don't necessarily want to run a full script to automate the task.
3) ultimately i am trying to automate the process of stepping forward a keyframe, applying Restore Figure Shape, and repeating this till the end of the clip.
thanks,
julian
ps. i am (re-)learning javascript at the same time as learning Daz Script, so more detailed explanation is highly appreciated.
update: it looks like my link was correct (to the sdk.zip), and using what i found here and that document i have created two working scripts that seem to do the job. thus, if anyone faces the following problem, my solution may be helpful:
i bought the Daz Millennium Cat (DMC), then the Cat Animation Pack (CAP) from Renderosity. the animation pack is quite good, but it is built for Poser, and you just keep MC the same shape, then CAP will work perfectly without any adjustment. if however, you want to change the shape of the cat, as we did (and make the cat very fat), then when you apply CAP to your differently shaped cat, it will revert to the original shape of MC, which is not what i wanted.
in order to get CAP to work with a morphed DMC, i found that the following worked:
create the following scripts
'memorizeFigure.dsa' script: [you can name this what you like]
var oMgr = MainWindow.getActionMgr();
var memorizeFigureAction = oMgr.findAction("DzMemorizeFigureAction");
if( memorizeFigureAction ){ memorizeFigureAction.trigger(); }
'applyMorph.dsa' script: [you can also name this what you like]
var oMgr = MainWindow.getActionMgr();
var nextKeyAction = oMgr.findAction("DzSkipToNextKeyAction");
var restoreAction = oMgr.findAction("DzRestoreSelectedItemsAction");
/* set the i limit to be larger than your keyframes - i really ought to get the number of keyframes and use that as a limit, but haven't done this yet */
for ( var i=0; i < 200; i++ ) {
restoreAction.trigger();
nextKeyAction.trigger();
}
instructions:
1) open Daz IDE
2) i suggest docking the IDE in the left-hand pane where you can always see it and it will appear as a sensible size
3) load the two scripts, memorizeFigure.dsa & applyMorph.dsa into the IDE
4) load a DMC with any body changes you like
5) run memorizeFigure.dsa script - this memorizes your different cat shape
6) double-click poser animation morph to apply selected morph to 'different' cat show - the cat now reverts to the original DMC shape
7) check keyframes don't have a huge gap of 25 frames - sometimes they do, sometimes they don’t - no idea why at present
8) run applyMorph.dsa script
9) press play to run 'different-shaped' cat animation
i hope this helps someone - if you have a lot of these 'morph-animations' to do it could save you many tedious hours. i hope so, because as a newbie it took me some long toil to put it together, simple though it is!