DzProperty::currentValueChanged() not working?
Hi.
I need to be notified when a material changed in Studio. For example, when the user applies a skin to V4 or Genesis. In this post: http://www.daz3d.com/forums/discussion/36541/ it was suggested to use DzProperty::currentValueChanged(), which I am doing now.
The code that I use is something like this:
ReDSMaterialListIterator i(matList);
while( i.hasNext() ) {
DzMaterial* mat = i.next();
// Scan the list of properties and monitor their changes
auto i = mat->propertyListIterator();
while( i.hasNext() ) {
auto prop = i.next();
// Get notifications when the material changes
connect(prop, SIGNAL(currentValueChanged()), this, SLOT(watchMaterial()));
}
}
Matlist is simply a QList collected by a previous step.
This works for some materials and it doesn't for others. More precisely, while the list of properties monitored for something like V4's 1_SkinFace is:
DS mat monitored: 1_SkinFace
Diffuse Color
Diffuse Strength
Glossiness
Specular Color
Specular Strength
Multiply Specular Through Opacity
Ambient Color
Ambient Strength
Opacity Strength
Bump Strength
Negative Bump
Positive Bump
Displacement Strength
Minimum Displacement
Maximum Displacement
Normal Map
Reflection Color
Reflection Strength
Refraction Color
Refraction Strength
Index of Refraction
Horizontal Tiles
Horizontal Offset
Vertical Tiles
Vertical Offset
Lighting Model
UV Set
Smooth On
Smooth Angle
Render Priority
Propagate Priority
Follow Blend
For some skins the slot receives notifications only for a property named "UV Set" for 1_SkinFace. The signal for Diffuse and other properties modified by the skin, a pz2 file, is never received. This is with a products called "Ireland" by Vyktohria. Same experience with SAV Maraki for Dawn. The skins are applied to V4 or Dawn. I can see the difference in the Surfaces tab.
Is there some missing step that needs to be performed to receive notification for all properties in the loop?
Thanks in advance.
Comments
After some more testing I noticed that hand-changing the material in the Surfaces tab triggers the slot correctly.
Applying a material preset calls the watchMaterial() slot for all materials but the vast majority of the calls are for a "UV Set" property. The slot tries to find the owner of the property but it fails for most properties in this way:
Apparently, the mat->shapeListIterator() returns an empty list, because no updates are queued in the materialRefreshTable container.
I hope this gives you an idea of what's happening. It seems that it's very hard for a plugin to monitor material changes consistently. If you have an alternative method that will be greatly appreciated.
Thank you.
More testing. When using V4 with PZ2 files every material preset works as expected.
I have to rectify my previous observation. As initially reported, the Ireland skin fails to set all materials. It triggers the update for:
- 5_Lacrimal
- 4_Teeth
- 6_Eyelash
- 4_InnerMouth
- 5_Sclera
- 5_Pupil
- 4_Gums
- 1_Eyebrow
- 7_EyeSurface
- 5_Iris
- 4_Tongue
- 5_Cornea
- 7_Tear
So, it seems that, in this case, most non-skin materials are triggers but all the skin-related mats don't. The preset is also a pz2.
Hope this helps.
A material preset can modify properties as you see, but a preset can also replace materials entirely.
So, you will want to listen for some combination of the following signals on DzShape:
void materialAdded( DzMaterial *mat );
void materialRemoved( DzMaterial *mat );
void materialListChanged();
I'll try that. Thank you.
So, you are saying that, even though the material itself will be the same, say 1_SkinFace, the preset might actually cause the shader to be deleted and then replaced with a shader that has the same name and properties but that it's created from scratch. Am I understanding this correctly?
I'll try that. Thank you.
So, you are saying that, even though the material itself will be the same, say 1_SkinFace, the preset might actually cause the shader to be deleted and then replaced with a shader that has the same name and properties but that it's created from scratch. Am I understanding this correctly?
The name of the material group will still be 1_SkinFace. The name is determined by the geometry, in the case for V4 the name is in the obj file. The material itself, denoted by DzMaterial* can be entirely different after a material preset is applied. If the current material in the 1_SkinFace group is a DzDefaultMaterial and the preset wants DzShaderMaterial, then the current material that corresponds to 1_SkinFace will be removed and then replaced with a different material. In which case you would want to disconnect from the removed material and connect up to the new material.
Thank you for the information.
Unfortunately it seems that there are cases that are not so cut and dry.
For example, the "Ireland" skin for V4 works OK when applying the full skin to V4. Reality gets the notifications.
I added slots for: materialChanged(), materialRemoved(DzMaterial*), materialAdded(DzMaterial*), and materialListChanged() of each shape in the figure.
When applying some pz2 files for makeup or lips no slot is called.
Is there a way of monitoring what signals are called by Studio during a certain operation? Any way of installing a global signal monitor?
Thanks in advance.
I forgot to mention that I also monitor the currentValueChanged() signal of every property of the materials and don't get any notification in the case described above.
One last detail. The pz2 file has an associated dsa file that is executed by Studio as expected.
I have resolved it.
The DZShape::materialListChanged() in fact notifies that the materials have been changed and old materials possibly deleted. Although I had a slot assigned to the materialRemoved(DzMaterial*) method, it was never called. Instead, the materialListChanged() signal is what needs to be monitored. Once I receive that signal it means that the program has to connect to the new materials. In that way everything works as expected and very quickly too.
Cheers.