Is It Possible To Access The Internal Name From A PP2 In DS4 Via DAZ Script? [How About The OBJ Name
I've recently updated the Poser version of my Smart+ Prop/PropGoto+ freebies - http://www.daz3d.com/forums/discussion/39376/
Part of the update was to use the internal name of the prop to identify Smart+ props like this:
Extract from file 'Smart+ Prop DS.pp2':
version
{
number 6
}
prop SmPlHaRoTestRod
{
geomCustom
...
}
prop SmPlHaRoTestRod
{
name TestRod
...
The "SmPlHaRo" prefix added to the internal name indicates it's a Smart+ prop targeted to the hand, requiring a rod-type grip.
This works fine in Poser 6, 8, and 9 (all the versions I can test with).
I'm working on the equivalent DAZ Studio update now (I'm using the old DAZ Script DSA format since I need to support DS3 still). So I'm using oProp.getLabel() to get the external name and oProp.name() to get the internal name.
DS3 works fine with the above (oProp.getLabel()="TestRod" and oProp.name="SmPlHaRoTestRod" as expected)
But DS4 seems to ignore the internal name and create its own, based on the CR2 name ((oProp.getLabel()="TestRod" but oProp.name="Smart+ Prop DS_18"), and the name looks like the subfolder names that DS creates in its C:\Users\\Documents\DAZ 3D\Studio\My Library\data\ folder which would make sense (I can't find the DS4 equivalent folder)
So the question is simple:
Is there any way to get the Poser prop internal name (as defined in the PP2)from DAZ Script in DS4?
Comments
I don't believe so. The change of naming system, to one based on the OBJ name and vertex count, seems to have some in sometime during DS4 - I ran into this in connection with some scripts I'd written for a PA recently.
I had to do DS version-checking in one of my scripts (do one thing if it's DS3, another if it's DS4.5+, and it's DS4.0 come to a grinding halt).
No big problem - I'll just go for the 'ask the user' option:
Note to self: if DS4 loads a prop from a Poser PP2 then the name accessed via oProp.name() depends on where the geometry is...
- If the PP2 used an external geometry file, then it's the OBJ filename
- Otherwise (i.e. geometry embedded in PP2) it's the PP2 filename.
So using external geometry and adding my prefix to the OBJ filename seems the easiest workaround for now.
A year later, I'm finding a need to access the filename of the OBJ from which the geometry of a prop actor was loaded (assuming the PP2 used external geometry)
In PoserPython it should just be 'actor.GeomFileName()'
What would you use in DAZ Script ? I know there's DzGeometry and DzGeomSourceFileData, but I can't find any methods under DzNode that could lead me towards this.
Also, can DAZ Script differentiate between
(a) geometry that's been loaded from an OBJ via a PP2
(b) geometry that was embedded in the PP2
(c) (for DS4) geometry that was loaded from a DUF
I just had a look. DzGeomSourceFileData is derived from DzElementData, and DzElement has methods for getting the number of DzElementData items attached so I thought it would just be necessary to go through the list. However, importing an OBJ neither the object nor the object's shape have any DzElementData items, and the DzNode has only one which is for puppeteer by its class name. Not helpful, but it may perhaps suggest a more fruitful line to you.
Ah yes... in the DAZ Script 2 HTML documentation I keep forgetting to click 'List of all members', and that I need to clamber up and down and around in the class hierachy tree. And your mention of 'shape' rings a bell.
Here's my first bit of tree-clambering....
DzNode ---up---> DzElement ---down---> DzShape ---memberfunction---> getGeometry() ---returnvalue---> DzGeometry ---inheritedmethod---> getFullFilename()
...soooo, if I can find a DzShape that's associated with the DzNode that I'm looking at...
(hmmm... DzFacetShape suddenly springs to mind - iirc between DS4 and DS4.5 there was a change from DzShape to DzFacetShape...)
I remember DzShape/DzFacetShape in some script I played with in relation to one of my other threads in this forum, maybe some example code that Rob directed me to? I vaguely recall that there was a DzSomethingElse inbetween the DzNode and DzShape/DzFacetShape. I also recall that I used the code but ended up needing a DS version check, and doing something different for DS3 and DS4.5+ (I couldn't get it to work with DS4.0 at all)
Guess my next step is try and track down that thread/code.
Tracked down the code I was thinking of (but so far not the thread) - it was related to creating a square groundplane in script for my DS3/4 worldball (WorldBall Setup DS3,4.dsa), and DzObject was the 'DzSomethingElse'. Here are extracts from both DS3 and DS4 versions:
DS3 version
DS4 version:
So for DS3 I think the route from the DzNode to the DzShape is this...
DzObject DzNode::getObject ()
DzShape DzObject::getCurrentShape ()
For DS4 I think it's going to be the same ? I think the DzPresentation bit is irrelevant if I'm just trying to get from the DzNode to the DzShape ?
So the DS3 code is probably going to be based on something like this ?
and the DS4 code is probably going to be based on something like this ?
Obviously some checking for null/undefined return values will be needed as well.
Can anyone spot any potential problems (I don't have any documentation for the DS4 FacetShape, so I may have got that bit wrong)?
I'm making progress - it's not the oGeom.getFullFilename() that I want (that seems to be null), but oGeom.name - with a prop loaded into DS3 from a PP2 with an external OBJ, the following always fails the 'if (sObjFilename)' test - sObjFilename is printed as an empty string, but oGeom.name gives me exactly what I was after.
Also tried exactly the same code in DS4 and that gives me the same results.
So if DS3/4 load a prop from a PP2 with an external OBJ then I can get at the OBJ filename with oGeom.name.
If the PP2 has an embedded geometry oGeom.name appears to be the PP2 filename (need to do another test to confirm - edit:confirmed)
If DS4 loads from a DUF... not sure yet what oGeom.name will give me, but I'm guessing it'll be the "name" field from the "geometries[]" section of the DUF (e.g. the screenshot on this post) - edit: more-or-less confirmed from a couple of simple tests
You can get the geometry from the node - DzNode.getGeometry()
I've tried what seems like every combination of the above and it seems to me that those fields are mostly empty.
Did you ever figure it out ?
I got this far... which only got me part of the path, not the full file name.
I should mention I was using a prop loaded from a DUF file.
That code above just gives me :
sObjFilename=C:/Program Files/DAZ 3D/DAZStudio4
I'm rather rusty on this but I recall that I got this working with DUFs - however, and I think this is important, they were DUFs that were originally created by importing a PP2 with an external geometry OBJ into DAZ Studio.
I think the screenshot pointed to by the link at the bottom of my 9th post above might help explain... (well it would if the new forum software hadn't screwed up all old-style links to specific posts ... this is the working link ). If you look in a DUF you can see the name and label fields of each node and its associated geometry. The values will depend on how the DUF was originally created, although I don't recall the exact differences off hand:
1) DUF created by importing a Poser PP2/CR2 with an external geometry in an OBJ file (DS4 automatically creates the DUF on import)
2) DUF created by importing a Poser PP2/CR2 with internal geometry, i.e. NO OBJ file (DS4 automatically creates the DUF on import)
3) DUF created purely in DAZ Studio, e.g. using "Create Primitive" and saving that as a DUF.
Cheers, Pete
Thanks for coming back to this.
When I open a DUF file I don't get text, but I think I see what you are saying... for those fields to appear they need to be in the DUF file ?
All I need to do is select an object(s) and get the DUF filename. It sounds simple but I've spent hours on this and got nowhere !
I'll soldier on I guess.
Correct, assuming that I understand correctly... and that's always debatable... :D
I liked the old DAZ Script file extensions DSA, DSC* and DSE - A for ASCII, C* for Compressed*, and E for Encrypted - you knew where you were with those. DUF doesn't give you that, so I'd guess the DUF files you're looking at are compressed or encrypted. If they're just compressed you should be able to open them with 7-zip or similar, and extract the plain text files to check those name/label entries.
Of course if the DUF files are encrypted then you're out of luck.
Note: If you're saving your own DUF files then there's a checkbox when you do the saving so you can select to write either ASCII or compressed DUF files.
*That should be DSB with B for Binary for compressed files as Richard pointed out below. DSC was a figment of my camera's imagination ;o)
Thanks for that. I am making my own DUF files yes. I did one plain text and there's not an absolute file path in there.
However at the top there is this :
If I could get the id I would be half way there.
Still trying to dig it out, when I load up an object from the selected node and try this :
print(oObj.assetId);
It's undefined. Hmm
The compressed script extension is .dsb, I don't think .dsc is a DS extension.
There's a Batch Convert pane that will also handle compressing/uncompressing without losing extensions or duplicating files as happens using 7Zip.
Thanks Richard.
I'm beginning to think this area is not fully working.
SImplifying that code to this :
Gives :
C:/Program Files/DAZ 3D/DAZStudio4
And filename() is empty.
Looks like oObj.getCurrentShape().getGeometry().getFilename() is returning a null string - I tried a slightly amended version of your code
var prop = Scene.getPrimarySelection();
var oObj = prop.getObject();
var sPropName = oObj.getCurrentShape().getGeometry().getFilename()
print ("sPropName = ",sPropName)
var oThisFile = new DzFileInfo (sPropName);
print (oThisFile.absFileName());
print (oThisFile.fileName());
and got this
Loading script: .../TEST.dsa
DEBUG: sPropName =
DEBUG: H:/Poser/!TEMP
DEBUG:
Script executed successfully: .../TEST.dsa
(Note: I loaded and selected a Poser prop that I know uses an external OBJ for this. oObj.getCurrentShape().getGeometry().getFilename() clearly isn't returning what we expect, so our expectations are probably incorrect! ;o) Off to look at it a bit more...)
The new DAZ Studio 4.x documentation Object Index doesn't yet have anything about DzGeometry, so I'm using the old DAZ Script 2 documentation from DS3 (the 2.96MB 'DAZ Script API.zip) for reference. DzGeometry inherits getFilename() from DzStorable, so let's also try using that with our oGeom.
var prop = Scene.getPrimarySelection();
var oObj = prop.getObject();
print("oObj.name = ",oObj.name)
if (oObj){
oShape = oObj.getCurrentShape()
if (oShape){
oGeom = oShape.getGeometry()
if (oGeom){
print ("oGeom.name =",oGeom.name);
print ("oGeom.getFilename() =",oGeom.getFilename());
oFileInfo = new DzFileInfo( oGeom.getFilename() );
if (oFileInfo){
print ("oFileInfo.absFileName()="+oFileInfo.absFileName());
} else print ("No sObjFilename = "+sObjFilename+"oGeom.name="+oGeom.name);
} else print ("No oGeom");
} else print ("No oShape");
} else print ("No oObj");
In addition lets initially use a Poser prop TESTPP2.pp2 with an external OBJ file TESTOBJ.obj. I've specifically used different text for the PP2 filename, OBJ filename, Poser internal name and Poser external name. Here's the relevant bit of TESTPP2.pp2 with the Poser internal/external names:
{
...
prop PropA
{
storageOffset 0 0.3487 0
objFileGeom 0 0 :Runtime:libraries:Props:Temporary:TESTOBJ.obj
}
prop PropA
{
name PropName
...
}
I load this prop into DS4.8, select it and then run the script. This is what I get:
Loaded file: TESTPP2.pp2
Loading script: .../TestScript.dsa
DEBUG: oObj.name = TESTOBJ_3108
DEBUG: oGeom.name = TESTOBJ
DEBUG: oGeom.getFilename() =
DEBUG: oFileInfo.absFileName()=E:/DAZ/Studio4(64)
Script executed successfully: .../TestScript.dsa
So it looks like oGeom.name is the filename (without path or extension) of the OBJ file provided the prop was loaded from a PP2 with an external OBJ.
Currently I can't find the associated /data/auto-adapted folder to check the DUF etc that were created when I imported the Poser prop. I'll post the relevant bits of that in this post when I find it. (Edit: Hmmm... can't find it in any of my content/data/auto-adapted. So I tried saving manually as a Prop Asset. Noticed that there's a "Write geometry definitions" checkbox*, ticked by default. Saved it as TESTDUF.duf using all default settings, then loaded the DUF, selected the prop and ran the script...
Loaded file: TESTDUF.duf
Loading script: ...y/TestScript.dsa
DEBUG: oObj.name = TESTOBJ_3108
DEBUG: oGeom.name = TESTOBJ
DEBUG: oGeom.getFilename() =
DEBUG: oFileInfo.absFileName()=.../DAZ/Studio4(64)
Script executed successfully: .../TestScript.dsa
No surprise there, exactly the same as loading it from the PP2. When I saved TESTDUF.duf it also created TESTOBJ_3108.dsf which now contains the geometry ("geometry_library" type: "polygon_mesh")
(Edit: contrary to a comment I saw somewhere, can't recall where, neither the DUF nor the DSF contain any reference back to the original PP2 or OBJ)
(*Note: if you uncheck the "Write geometry definitions" checkbox it simply seems to write the geometry data to the DUF instead oif the DSF)
DAZ Studio native props from the DAZ store seem to use the same DUF+DSF structure. The FRED.duf contains something like this
"nodes" : [
{
"id" : "FRED_1234",
"url" : "/data/WHATEVERPATH/FRED_1234.dsf#FRED_1234",
"name" : "FRED_1234",
"label" : "FRED",
...
"geometries" : [
{
"id" : "FRED",
"url" : "/data/WHATEVERPATH/FRED_1234.dsf#FRED",
and the associated FRED_1234.dsf which contains the geometry data has this near the top:
"geometry_library" : [
{
"id" : "FRED",
"name" : "FRED",
"type" : "polygon_mesh",
and the script gives
Loaded file: FRED.duf
Loading script: .../TestScript.dsa
DEBUG: oObj.name = FRED_1234
DEBUG: oGeom.name = FRED
DEBUG: oGeom.getFilename() =
DEBUG: oFileInfo.absFileName()=.../DAZ/Studio4(64)
Script executed successfully: .../TestScript.dsa
Interesting.
So there does not seem a way to construct the full path, which I find odd.
Which specific file are you trying to find the full path of ? As far as I can tell at the moment a basic DAZ Studio native (i.e. DUF) file consists of just three files:
/Figures/FRED.duf
/data/Name/Product/FRED/FRED_1234.dsf
/data/Name/Product/FRED/UV Sets/Name/Base/default.dsf
And the geometry is embedded in either FRED.duf or FRED_1234.dsf depending on whether or not you ticked the "Write geometry definitions" checkbox when creating the DUF.
There's probably a way to get the full path you're after from DAZ Script, but I'd guess we haven't hit on the right object.method() combo ! :)
Well what I would like to do is click on any item in the scene list and get it's full path.
What you click on will be a DzNode, which isn't yet documented in the DS4.x stuff.
And you want to find the equivalent of the /Figures/FRED.duf from which that node was loaded.
Thinking off the top of my head I guess you first need to climb up the node tree its root node (e.g. if you clicked on a figure's left hand you'd want to climb up to the Body node, but if you clicked on an item carried in the figures left hand you wouldn't). If we're lucky there'll be some DzNode methods (possibly inherited from DzStorable?) that we can use to find the DUF filename...
I'll have a dig around later. To see what was in objects I was printing them to the IDE window with this that was posted on the forum :
function dump(obj) {
var properties = new RegExp("([a-zA-Z0-9]+(\\(.*?\\))?),", "g");
print(Object.getOwnPropertyNames(obj).sort().toString().replace(properties, "$1\n"));
}
So maybe I can find something in DzNode.
Nothing obvious in the DS3 DzNode documentation so it'll probably be a case of scrambling around in the object hierarchy. And that's something I'm useless at !
See if this helps.
Hmmm... large sections of uncommented code, apparently irrelevant to the discussion*, posted with no explanation always sets the alarm bells ringing.
Can you expand on your "See if this helps." and explain why and how it might ? :)
*Edit: My mistake - as I said I'm not good with OO - I simply didn't understand what the code was doing. With 50/50 hindsight I should simply have asked "Can you expand on your 'See if this helps'? What does this script actually do?"
Including the first sentence was uncalled for, and the '...apparently irrelevant to the discussion...' was pure stupidity on my part! My sincere apologies jag11.
Edit2: I need to look no further than the last few lines of code in jag11's script above to see how stupid my comment was ! I.e.
I'm sorry.
I wrongfully assumed several things, I assummed:
Apologies if you took offence - none was intended. I sometypes type without engaging my brain!
As I said earlier I'm not good with object oriented code, and when I looked through the code I couldn't follow what it was doing, and couldn't see how it helped with the question mrmorph was asking.
If I was wrong (as it seems I was) I apologize unreservedly. I've also added an edit to the post above.
And it's definitely not a party of two - the more the merrier !
Especially people who actually understand OO !