Morph "eCTRLEyesClosed" cannot be set from script

Issue #848 resolved
Butaixianran created an issue

I’m trying to set morph’s value from script, but morph “eCTRLMouthOpen“ just doesn’t work

import bpy
obj = bpy.context.object

# This works
obj["eCTRLMouthOpen"] = 1.0
# This not
obj["eCTRLEyesClosed"] = 1.0

bpy.ops.daz.update_all()

It can be set from panel as “Eyes Closed“, and I checked the morph name from Daz Studio, “eCTRLEyesClosed“ is the right name.

I think, the real morph name behind “Eyes Closed“ in the panel, must be different from “eCTRLEyesClosed“.

Is there a way to find out “Eyes Closed“'s real morph name in this addon?

Comments (16)

  1. Alessandro Padovani

    As I know it for expressions you have to use ids, not names. That is, label is for the interface, name is for the file, id is for the expressions. The id is defined in the duf file and may differ from the name. Unless Thomas changed something.

  2. Thomas Larsson repo owner

    The name in Blender is ECTRLEyesClosed, which you can see if you hover over the slider with the mouse (Python tooltips must be enabled). eCTRLEyesClosed and ECTRLEyesClosed are aliases, which are displayed with lines that start with “=” in the terminal window when the morphs are loaded.

    But this is not good, because there is no straightforward way to know what the real property name is. There should be a function that sets the property value, taking aliases into account. Perhaps the operator that loads morphs should return a table with the real morph names and the file they are defined in.

  3. Alessandro Padovani

    Thomas, that’s the id in the duf file so it’s fine in my opinion. If a programmer wants to use expressions in a script file then he have to check the ids in daz studio. The common user is not concerned by this and only wants the daz labels in the interface so to get the same names as daz.

    If you use names instead of ids inside the expressions there will be conflicts because daz studio uses ids, not names.

  4. Butaixianran reporter

    Well, use the id from .duf file is a good way. The only thing a developer need, is write this down into the online document. So developers can know about this.

    I think a lot of people don’t know the morph name like “eCtrlxxx“ is actually not the id, and there is another id in the .duf file. That’s insane, since the name is already different from label.

    And if you like to add this into online document, pls also write down that, we need to enable python tooltip to see that very important tooltip.

    I’ll close this issue.

    Thanks

  5. Alessandro Padovani

    A lot of people don’t know about this but it is also not required for the common user. A programmer should know if he wants to make scripts for daz figures he also has to know how they work. That’s what the daz PAs do. Then I agree a note in the docs is always useful of course.

    edit. p.s. As for aliases it’s the same they are defined in the daz properties as it’s visible in the picture above. So the programmer can know just by checking in daz.

  6. Thomas Larsson repo owner

    In the last commit I define an API function set_slider(ob, prop, value), which sets the value of the property, and also of the alias if there is one. I added the following code to the test suite to illustrate the use.

    import_daz.set_slider(rig, "eCTRLEyesClosedL", 0.3)
    import_daz.set_slider(rig, "ECTRLEyesClosedR", 0.7)
    import_daz.update_drivers(rig)

    This also illustrates that you can force update with a function rather than an operator. I had forgotten about that.

    Updated docs for the API: https://diffeomorphic.blogspot.com/p/daz-importer-functions-version-16.html

  7. Thomas Larsson repo owner
    • changed status to open

    Reopened this because I want to add some mechanism to return the IDs when the morphs are loaded. A script may not know beforehand which morphs will be loaded and what their IDs are.

  8. Alessandro Padovani

    In my opinion this adds unnecessary complexity on the blender side since a programmer can already check this in daz. Plus the addon doesn’t know about all the aliases because it doesn’t scan the whole daz database so this will be incomplete information anyway. Unless I miss something that’s entirely possible because I suck at rigging and programming.

  9. Thomas Larsson repo owner

    Sorry, I’m using the wrong terminology. A morph has both an id, a name, and a label, and both the id and the name can be used to refer to the morph, whereas the label is displayed on the slider. All three are defined in the same file, so there is no need to open anything else.

    The api function get_return_value now returns a dict which specifies the id of the morph defined in a given file. It should be called immediately after the operator. The sample file shows how to use it.

    units = import_daz.get_return_value()
    print("Units loaded:")
    for path,prop in units.items():
    . print(" %s: %s" % (path, prop))

    We can then recover the property id from the paths like this. The path must be in lower case and use / as separators.

    path = unitsfolder + "eCTRLEyesClosed.dsf"
    prop = units[path.lower()]
    import_daz.set_slider(rig, prop, 0.1)

    Not super elegant, but it works, at least for files that only define one morph per file.

  10. Alessandro Padovani

    The name is not good to refer the morph in expressions there’s nothing that guarantees the name to be unique. That’s what ids are for. Again unless I miss something that’s what I understand.

  11. Thomas Larsson repo owner

    The code that loads poses checks both the id and the name, so at some point I must have encountered pose presets that refer to the name rather than the id. Although I don’t have any example right now.

    Getting the morph id from the file path should be useful. One could write a script that loops over all files in a directory and loads the morphs. If one wants to do something with the morphs afterwards, it is good to know which morph was actually defined in each file.

  12. Butaixianran reporter

    It is not that simple as “a programmer can already check this in daz“, since they don’t know the morph name from Daz is not the id.

    I have written Daz script for years and I still don’t know there is another id hide in the morph’s .duf file, until yesterday.

    I think the most important thing is write this down, with bold, something like this:

    “Notice: the morph name from Daz Studio’s morph setting panel, is not the morph id. There is another id in the morph’s .duf file. And we use the id in this addon“

    Otherwise, even a developer can get the morph names by this “get_morphs“ API, they will wonder why those morph names are different from the one in Daz.

    As long as a developer know about this name and id difference, it will be fine just use the id.

  13. Thomas Larsson repo owner

    The idea with the new set_slider function is that you can use either the name or the id. And actually it is not the full id, but rather the id relative to the asset's file path. To uniquely refer to the asset, DS uses the syntax filepath#relative id. You can see how it works if you open the file “/data/DAZ 3D/Genesis 8/Female/Morphs/DAZ 3D/Base Pose Head/eCTRLEyesClosed.dsf” in a text editor.

    But using the return value to get the property from the filepath should be safest approach, albeit somewhat clumsy. A script doesn’t have to know what’s in a file, but it always knows its path.

  14. Log in to comment