I would like to apply a material for all the objects in the occurences with this script:
import json
# Définir le chemin vers ton fichier JSON d'entrée
json_path = r"\\ozone\materiaux.json" # Remplace par le chemin correct
with open(json_path, "r") as file:
materials_data = json.load(file)
# Récupérer toutes les occurrences dans la scène
occurrences = pxz.scene.getAllOccurrences()
# Récupérer tous les matériaux existants dans la scène
all_materials = pxz.material.getAllMaterials()
material_dict = {pxz.material.getMaterialName(mat): mat for mat in all_materials}
# Assigner les matériaux aux occurrences
for occ in occurrences:
occ_name = pxz.scene.getOccurrenceName(occ)
# Trouver si l'occurrence a un matériau défini dans le JSON
material_info = next((item for item in materials_data if item["name"] == occ_name), None)
if material_info:
material_name = material_info["material"]
if material_name in material_dict:
material_id = material_dict[material_name]
pxz.material.assignMaterial(occ, material_id)
print(f"✅ Matériau '{material_name}' assigné à '{occ_name}'")
else:
print(f"⚠ Matériau '{material_name}' introuvable pour '{occ_name}'")
else:
print(f"❌ Aucun matériau défini pour '{occ_name}' dans le JSON")
It looks like the Forum layout missunderstood the code example you copy pasted. Can you try to reformat your message using the “Preformatted text” option (cf screenshot). Because it’s quite hard to read it currently.
import json
# Définir le chemin vers ton fichier JSON d'entrée
json_path = r"\\ozone\materiaux.json" # Remplace par le chemin correct
with open(json_path, "r") as file:
materials_data = json.load(file)
# Récupérer toutes les occurrences dans la scène
occurrences = pxz.scene.getAllOccurrences()
# Récupérer tous les matériaux existants dans la scène
all_materials = pxz.material.getAllMaterials()
material_dict = {pxz.material.getMaterialName(mat): mat for mat in all_materials}
# Assigner les matériaux aux occurrences
for occ in occurrences:
occ_name = pxz.scene.getOccurrenceName(occ)
# Trouver si l'occurrence a un matériau défini dans le JSON
material_info = next((item for item in materials_data if item["name"] == occ_name), None)
if material_info:
material_name = material_info["material"]
if material_name in material_dict:
material_id = material_dict[material_name]
pxz.material.assignMaterial(occ, material_id)
print(f"✅ Matériau '{material_name}' assigné à '{occ_name}'")
else:
print(f"⚠ Matériau '{material_name}' introuvable pour '{occ_name}'")
else:
print(f"❌ Aucun matériau défini pour '{occ_name}' dans le JSON")
Thanks.
Can you try to elaborate a bit more on what your are trying to acheive ?
What the “name” key in your JSON is refering to ? And what the “material” key is refering to ?
You want to swap what with what ?
From want i understood:
You want to look for every occurence in your scene that has the name of the Json “name” key, then for them swap their material with the one defined in the Json “material” key ?
Yes! Exactly! For every occurence in my scene that has the name of the Json “name” key, for the objects inside of each occurence swap their material with the one defined in the Json “material” key
I propose to have a look at the sample scripts, for example the Materials_ColorsByDensity.py and the resource Selim_B posted in another thread , see: How to Handle Materials
There you can see that you need to call
createMaterial
see PixyzSDK: material.createMaterial(name, pattern, addToMaterialLibrary=True) → material.Material
At best, your JSON file would contain all the information necessary for the material pattern already. Then you could also use this: CreateMaterialFromDefinition
Now that you have your material (occurrence id), then you only have to set it the same way as in the example script.
core.setProperty(occ, “Material”, str(mat))
where “Material” is the name of the material and occ is your part occurrence. (See script) or use the function
Be aware that there are some details regarding materials and how they are assigned and displayed in Pixyz Studio/SDK when it comes to multi-material PartOccurrences.
Many thanks @DMG_GLein for providing helpfull threads.
@Erc02 I rewrote your code based on the goal we discussed. I provided a static materials_data structure, based on your specification. But feel free to load it from your json file.
I added a check to ensure the material you want to replace with, exist in the pxz scene.
from pxz import *
materialSwappingData =[
{
"name": "myOccurrenceName1",
"material": "myCustomMat1"
},
{
"name": "myOccurrenceName2",
"material": "myCustomMat2"
}
]
for matSwapData in materialSwappingData:
# We retrieve the material id assosiated with the wanted material name (case-sensitive)
materialsIds = material.findMaterialsByProperty("Name", matSwapData["material"], True)
# Ensure we found one material with the specified name
if len(materialsIds) == 0 :
print("No materials found for name " + matSwapData["material"] + ", step will be skipped")
continue
# We retrieve all the occurrences from your scene with the specified name (case-sensitive)
occurrencesFound = scene.findOccurrencesByProperty("Name", matSwapData["name"], [scene.getRoot()], True)
# For each of them, we swap their materials
for occurrence in occurrencesFound:
# In our case, we do not pass regex into findMaterialsByProperty so we assume the first mat in the list is the correct one
scene.setOccurrenceMaterial(occurrence, materialsIds[0])
# If you also want to override your occurrence subParts materials, let's do it here.
# First we need to know how many of them are attached to this occurrence
numberOfSubPartMaterials = len(scene.listSubpartMaterials(occurrence))
# Now we override each of them
for subpartIndex in range(0, numberOfSubPartMaterials):
scene.setSubpartMaterial(occurrence, subpartIndex, materialsIds[0])
# Ensure the materials on the subParts are also applied on the patches
scene.transferSubpartMaterialsOnPatches(occurrence)
I hope it will be clear and will make sense for your use case. Feel free to ask if you need more precision.