यह एक स्क्रिप्ट के लिए है जिसे मैं ब्लेंडर में चला रहा हूं, लेकिन सवाल इसके पायथन हिस्से से संबंधित है। यह ब्लेंडर के लिए विशिष्ट नहीं है।

स्क्रिप्ट मूल रूप से इस उत्तर की है, और यह किसी दी गई सामग्री (कुंजी) को उसके नए समकक्ष ( मूल्य)।

यहाँ कोड है:

import bpy

objects = bpy.context.selected_objects

mat_dict =  {
  "SOLID-WHITE": "Sld_WHITE",
  "SOLID-BLACK": "Sld_BLACK",
  "SOLID-BLUE": "Sld_BLUE"
}

for obj in objects:
    for slot in obj.material_slots:
        slot.material = bpy.data.materials[mat_dict[slot.material.name]]

रोड़ा है, डुप्लिकेट को कैसे संभालना है जब दृश्य में "सॉलिड-व्हाइट" सामग्री के साथ न केवल ऑब्जेक्ट हो सकते हैं, बल्कि "सॉलिड-व्हाइट.001", "सॉलिड-व्हाइट.002", और इसी तरह।

मैं पाइथन में वाइल्डकार्ड के बारे में एक प्रश्न के लिए this answer देख रहा था और ऐसा लगता है कि fnmatch अच्छी तरह से अनुकूल हो सकता है इस कार्य के लिए।

मैंने कोड की अंतिम पंक्ति में fnmatch काम करने की कोशिश की है। मैंने इसके साथ शब्दकोश कुंजियों को लपेटने का भी प्रयास किया है (बहुत गीला, मुझे पता है)। इनमें से किसी भी दृष्टिकोण ने काम नहीं किया है।

मैं प्रत्येक शब्दकोश कुंजी पर वाइल्डकार्ड मिलान कैसे चला सकता हूं?

तो उदाहरण के लिए, क्या किसी ऑब्जेक्ट में "सॉलिड-व्हाइट" या "सॉलिड-व्हाइट" -डॉट-कुछ-नंबर है, फिर भी इसे "Sld_WHITE" से बदल दिया जाएगा?

0
Mentalist 28 अक्टूबर 2020, 23:26

2 जवाब

सबसे बढ़िया उत्तर

मुझे ब्लेंडर के बारे में कोई जानकारी नहीं है इसलिए मुझे यकीन नहीं है कि मुझे समस्या ठीक हो रही है, लेकिन निम्नलिखित के बारे में कैसे?

mat_dict =  {
  "SOLID-WHITE": "Sld_WHITE",
  "SOLID-BLACK": "Sld_BLACK",
  "SOLID-BLUE": "Sld_BLUE"
}

def get_new_material(old_material):
    for k, v in mat_dict.items():
        # .split(".")[0] extracts the part to the left of the dot (if there is one)
        if old_material.split(".")[0] == k:
            return v
    return old_material

for obj in objects:
    for slot in obj.material_slots:
        new_material = get_new_material(slot.material.name)
        slot.material = bpy.data.materials[new_material]

.split(".")[0] के बजाय आप या re.match रेगेक्स को अपने शब्दकोश में कुंजियों के रूप में संग्रहीत करके उपयोग कर सकते हैं। जैसा कि आपने टिप्पणी में देखा, startswith बहुत अधिक मेल खा सकता है, और fnmatch के मामले में भी ऐसा ही होगा।

कार्रवाई में उपरोक्त फ़ंक्शन के उदाहरण:

In [3]: get_new_material("SOLID-WHITE.001")
Out[3]: 'Sld_WHITE'

In [4]: get_new_material("SOLID-WHITE")
Out[4]: 'Sld_WHITE'

In [5]: get_new_material("SOLID-BLACK")
Out[5]: 'Sld_BLACK'

In [6]: get_new_material("test")
Out[6]: 'test'
1
Czaporka 29 अक्टूबर 2020, 11:12

आप दो तरीकों से इस तक पहुंच सकते हैं। आप एक ऐसा स्मार्ट डिक्शनरी बना सकते हैं जो अस्पष्ट नामों से मेल खाता हो। या आप उस कुंजी को बदल सकते हैं जिसका उपयोग रंग देखने के लिए किया जाता है।

यहाँ fnmatch का उपयोग करने वाले पहले दृष्टिकोण का एक उदाहरण दिया गया है। यह दृष्टिकोण लुकअप समय की जटिलता को O(1) से O(n) में बदल देता है जब रंग में कोई संख्या होती है। यह दृष्टिकोण __missing__ विधि के साथ UserDict का विस्तार करता है . शब्दकोश में कुंजी नहीं मिलने पर __missing__ विधि को कॉल किया जाता है। यह fnmatch का उपयोग करके दी गई कुंजी के साथ प्रत्येक कुंजी की तुलना करता है।

from collections import UserDict
import fnmatch
import bpy

objects = bpy.context.selected_objects

class Colors(UserDict):
    def __missing__(self, key):
        for color in self.keys():
            if fnmatch.fnmatch(key, color + "*"):
                return self[color]
        raise KeyError(f"could not match {key}")

mat_dict = Colors({
  "SOLID-WHITE": "Sld_WHITE",
  "SOLID-BLACK": "Sld_BLACK",
  "SOLID-BLUE": "Sld_BLUE"
})

for obj in objects:
    for slot in obj.material_slots:
        slot.material = bpy.data.materials[mat_dict[slot.material.name]]

रेगेक्स का उपयोग करके दूसरे दृष्टिकोण का एक उदाहरण यहां दिया गया है।

import re
import bpy

objects = bpy.context.selected_objects

mat_dict =  {
  "SOLID-WHITE": "Sld_WHITE",
  "SOLID-BLACK": "Sld_BLACK",
  "SOLID-BLUE": "Sld_BLUE"
}

pattern = re.compile(r"([A-Z\-]+)(?:\.\d+)?")
# matches any number of capital letters and dashes
# can be followed by a dot followed by any number of digits
# this pattern can match the following strings
# ["AAAAA", "----", "AA-AA.00005"]


for obj in objects:
    for slot in obj.material_slots:
        match = pattern.fullmatch(slot.material.name)
        if match:
            slot.material = bpy.data.materials[mat_dict[match.group(1)]]
        else:
            slot.material = bpy.data.materials[mat_dict[slot.material.name]]
1
steviestickman 29 अक्टूबर 2020, 00:47