kopia lustrzana https://github.com/torrinworx/Blend_My_NFTs
Changes to Materials and Logic
- Added AutoSave before generation functionality to Other panel - Removed strip_empty_exclude function - Modified Exporter to work with new Material Randomizer layout - Added Enable Materials option in logicafyDNAsingle function in preparation for Material Randomizer Logic - Materials are no longer formatted like Variants, the Material List is now a dictionary where the keys are the names of the Materials and the values are the Rarity percentages. Each Variant in the Materials.json file can have a different list with different rarity values that are selected for only that variant. Material file format: ``` { "Variant Name": { "Material List": { "Material Name 1": 90, "Material Name 2": 5, "Material Name 3": 1, "Material Name 4": 4 }, "Variant Objects": [] } } ```pull/135/head
rodzic
17cbf3a32f
commit
3cb2a69c81
14
__init__.py
14
__init__.py
|
@ -376,6 +376,8 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
|
|||
)
|
||||
|
||||
# Other Panel:
|
||||
enableAutoSave: bpy.props.BoolProperty(name="Auto Save Before Generation")
|
||||
|
||||
|
||||
# API Panel properties:
|
||||
apiKey: bpy.props.StringProperty(name="API Key", subtype='PASSWORD')
|
||||
|
@ -478,6 +480,11 @@ class exportNFTs(bpy.types.Operator):
|
|||
name="Reverse Order")
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
enableAutoSave = bpy.context.scene.input_tool.enableAutoSave
|
||||
if enableAutoSave:
|
||||
bpy.ops.wm.save_mainfile()
|
||||
|
||||
class input:
|
||||
nftName = bpy.context.scene.input_tool.nftName
|
||||
save_path = bpy.path.abspath(bpy.context.scene.input_tool.save_path)
|
||||
|
@ -923,10 +930,17 @@ class BMNFTS_PT_Other(bpy.types.Panel):
|
|||
input_tool_scene = scene.input_tool
|
||||
|
||||
"""
|
||||
Other:
|
||||
A place to store miscellaneous settings, features, and external links that the user may find useful but doesn't
|
||||
want to get in the way of their work flow.
|
||||
Export Settings:
|
||||
This panel gives the user the option to export all settings from the Blend_My_NFTs addon into a config file. Settings
|
||||
will be read from the config file when running heedlessly.
|
||||
"""
|
||||
|
||||
row = layout.row()
|
||||
row.prop(input_tool_scene, "enableAutoSave")
|
||||
|
||||
layout.label(text=f"Running Blend_My_NFTs Headless:")
|
||||
|
||||
save_path = bpy.path.abspath(bpy.context.scene.input_tool.save_path)
|
||||
|
|
|
@ -123,47 +123,18 @@ def get_hierarchy():
|
|||
|
||||
return hierarchy
|
||||
|
||||
def strip_empty_exclude(hierarchy):
|
||||
"""
|
||||
Strips Empty Exclude variants from the hierarchy.
|
||||
"""
|
||||
excluded_var_dict = {}
|
||||
|
||||
for a in hierarchy:
|
||||
empty_variant = ""
|
||||
empty_var_count = 0
|
||||
variant_list = list(hierarchy[a].keys())
|
||||
# empty_var_count and raise() prevents this for from causing breaking stuff:
|
||||
|
||||
for b in variant_list:
|
||||
if b.split("_")[1] == "0":
|
||||
empty_variant = b
|
||||
empty_var_count += 1
|
||||
if empty_var_count > 1:
|
||||
raise Exception(
|
||||
f"\n{bcolors.ERROR}Blend_My_NFTs Error:\n"
|
||||
f"The Attribute collection '{a}' has more than one Empty variant.\n"
|
||||
f"Attributes can only have a maximum of 1 Empty variant, please review the documentation here:\n{bcolors.RESET}"
|
||||
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
|
||||
)
|
||||
|
||||
if len(empty_variant.split("_")) == 4 and empty_variant.split("_")[3] == "Exclude":
|
||||
excluded_var_dict[a] = empty_variant
|
||||
del hierarchy[a][empty_variant]
|
||||
|
||||
return hierarchy, excluded_var_dict
|
||||
|
||||
def generateNFT_DNA(collectionSize, enableRarity, enableLogic, logicFile, enableMaterials, materialsFile):
|
||||
"""
|
||||
Returns batchDataDictionary containing the number of NFT combinations, hierarchy, and the DNAList.
|
||||
"""
|
||||
|
||||
hierarchy, excluded_var_dict = strip_empty_exclude(get_hierarchy())
|
||||
hierarchy = get_hierarchy()
|
||||
|
||||
# DNA random, Rarity and Logic methods:
|
||||
DataDictionary = {}
|
||||
|
||||
def createDNArandom():
|
||||
def createDNArandom(hierarchy):
|
||||
"""Creates a single DNA randomly without Rarity or Logic."""
|
||||
dnaStr = ""
|
||||
dnaStrList = []
|
||||
|
@ -195,20 +166,22 @@ def generateNFT_DNA(collectionSize, enableRarity, enableLogic, logicFile, enable
|
|||
singleDNA = ""
|
||||
# Comments for debugging random, rarity, logic, and materials.
|
||||
if not enableRarity:
|
||||
singleDNA = createDNArandom()
|
||||
singleDNA = createDNArandom(hierarchy)
|
||||
# print("============")
|
||||
# print(f"Original DNA: {singleDNA}")
|
||||
if enableRarity:
|
||||
singleDNA = Rarity.createDNArarity(hierarchy)
|
||||
# print(f"Rarity DNA: {singleDNA}")
|
||||
|
||||
if enableMaterials:
|
||||
singleDNA = Material_Generator.apply_materials(hierarchy, singleDNA, materialsFile, enableRarity)
|
||||
# print(f"Materials DNA: {singleDNA}")
|
||||
|
||||
if enableLogic:
|
||||
singleDNA = Logic.logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, excluded_var_dict)
|
||||
singleDNA = Logic.logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, enableMaterials)
|
||||
# print(f"Logic DNA: {singleDNA}")
|
||||
|
||||
if enableMaterials:
|
||||
singleDNA = Material_Generator.apply_materials(hierarchy, singleDNA, materialsFile)
|
||||
# print(f"Materials DNA: {singleDNA}")
|
||||
|
||||
# print("============\n")
|
||||
|
||||
return singleDNA
|
||||
|
@ -246,7 +219,6 @@ def generateNFT_DNA(collectionSize, enableRarity, enableLogic, logicFile, enable
|
|||
|
||||
# Data stored in batchDataDictionary:
|
||||
DataDictionary["numNFTsGenerated"] = len(DNAList)
|
||||
DataDictionary["excludedVariants"] = excluded_var_dict
|
||||
DataDictionary["hierarchy"] = hierarchy
|
||||
DataDictionary["DNAList"] = DNAList
|
||||
|
||||
|
|
|
@ -177,12 +177,14 @@ def render_and_save_NFTs(input):
|
|||
if hierarchy[attribute][var]['number'] == variant:
|
||||
variant = var
|
||||
|
||||
if material != '0':
|
||||
if material != '0': # If material is not empty
|
||||
for variant_m in materialsFile:
|
||||
if variant == variant_m:
|
||||
for mat in materialsFile[variant_m]["Material List"]:
|
||||
if mat.split('_')[1] == material:
|
||||
material = mat
|
||||
# Getting Materials name from Materials index in the Materials List
|
||||
materials_list = list(materialsFile[variant_m]["Material List"].keys())
|
||||
|
||||
material = materials_list[int(material) - 1] # Subtract 1 because '0' means empty mat
|
||||
break
|
||||
|
||||
full_dna_dict[variant] = material
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ def reconstructDNA(deconstructedDNA):
|
|||
return ''.join(reconstructed_DNA.split('-', 1))
|
||||
|
||||
|
||||
def apply_rules_to_dna(hierarchy, deconstructed_DNA, if_dict, then_dict, enableRarity, excluded_var_dict):
|
||||
def apply_rules_to_dna(hierarchy, deconstructed_DNA, if_dict, then_dict, enableRarity):
|
||||
|
||||
# Check if Variants in if_dict are in deconstructed_DNA, if so return if_list_selected = True:
|
||||
if_list_selected = False
|
||||
|
@ -221,7 +221,7 @@ def create_dicts(hierarchy, rule_list_items):
|
|||
return dict(items_returned)
|
||||
|
||||
|
||||
def logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, excluded_var_dict):
|
||||
def logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, enableMaterials):
|
||||
|
||||
deconstructed_DNA = singleDNA.split("-")
|
||||
didReconstruct = True
|
||||
|
@ -236,7 +236,6 @@ def logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, excluded_va
|
|||
# Items from 'THEN' key for a given rule
|
||||
then_dict = create_dicts(hierarchy, logicFile[rule]["THEN"])
|
||||
|
||||
# save_result(then_dict)
|
||||
violates_rule, if_bool, then_bool, full_att_bool = get_rule_break_type(hierarchy, deconstructed_DNA,
|
||||
if_dict, then_dict)
|
||||
if deconstructed_DNA[3] != "1":
|
||||
|
@ -249,7 +248,7 @@ def logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, excluded_va
|
|||
print(f"======={deconstructed_DNA} VIOLATES RULE======")
|
||||
|
||||
deconstructed_DNA = apply_rules_to_dna(
|
||||
hierarchy, deconstructed_DNA, if_dict, then_dict, enableRarity, excluded_var_dict
|
||||
hierarchy, deconstructed_DNA, if_dict, then_dict, enableRarity
|
||||
)
|
||||
|
||||
newDNA = reconstructDNA(deconstructed_DNA)
|
||||
|
|
|
@ -9,34 +9,42 @@ import json
|
|||
import random
|
||||
|
||||
|
||||
def select_material(materialList):
|
||||
def select_material(materialList, enableRarity):
|
||||
"""Selects a material from a passed material list. """
|
||||
|
||||
number_List_Of_i = []
|
||||
material_List_Of_i = [] # List of Material names instead of order numbers
|
||||
rarity_List_Of_i = []
|
||||
ifZeroBool = None
|
||||
|
||||
for material in materialList:
|
||||
# Material Order Number comes from index in the Material List in materials.json for a given Variant.
|
||||
# material_order_num = list(materialList.keys()).index(material)
|
||||
|
||||
material_order_num = material.split("_")[1]
|
||||
number_List_Of_i.append(material_order_num)
|
||||
material_List_Of_i.append(material)
|
||||
|
||||
material_rarity_percent = material.split("_")[1]
|
||||
material_rarity_percent = materialList[material]
|
||||
rarity_List_Of_i.append(float(material_rarity_percent))
|
||||
|
||||
for x in rarity_List_Of_i:
|
||||
if x == 0:
|
||||
ifZeroBool = True
|
||||
break
|
||||
elif x != 0:
|
||||
ifZeroBool = False
|
||||
print(f"MATERIAL_LIST_OF_I:{material_List_Of_i}")
|
||||
print(f"RARITY_LIST_OF_I:{rarity_List_Of_i}")
|
||||
|
||||
if ifZeroBool:
|
||||
selected_material = random.choices(number_List_Of_i, k=1)
|
||||
elif not ifZeroBool:
|
||||
selected_material = random.choices(number_List_Of_i, weights=rarity_List_Of_i, k=1)
|
||||
if enableRarity:
|
||||
ifZeroBool = None
|
||||
|
||||
return selected_material[0]
|
||||
for x in rarity_List_Of_i:
|
||||
if x == 0:
|
||||
ifZeroBool = True
|
||||
break
|
||||
elif x != 0:
|
||||
ifZeroBool = False
|
||||
|
||||
if ifZeroBool:
|
||||
selected_material = random.choices(material_List_Of_i, k=1)
|
||||
elif not ifZeroBool:
|
||||
|
||||
selected_material = random.choices(material_List_Of_i, weights=rarity_List_Of_i, k=1)
|
||||
|
||||
else:
|
||||
selected_material = random.choices(material_List_Of_i, k=1)
|
||||
|
||||
return selected_material[0], materialList
|
||||
|
||||
def get_variant_att_index(variant, hierarchy):
|
||||
variant_attribute = None
|
||||
|
@ -69,7 +77,7 @@ def match_DNA_to_Variant(hierarchy, singleDNA):
|
|||
dnaDictionary.update({x: k})
|
||||
return dnaDictionary
|
||||
|
||||
def apply_materials(hierarchy, singleDNA, materialsFile):
|
||||
def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity):
|
||||
"""
|
||||
DNA with applied material example: "1-1:1-1" <Normal DNA>:<Selected Material for each Variant>
|
||||
|
||||
|
@ -85,8 +93,9 @@ def apply_materials(hierarchy, singleDNA, materialsFile):
|
|||
complete = False
|
||||
for b in materialsFile:
|
||||
if singleDNADict[a] == b:
|
||||
mat = select_material(materialsFile[b]['Material List'])
|
||||
deconstructed_MaterialDNA[a] = mat
|
||||
material_name, materialList, = select_material(materialsFile[b]['Material List'], enableRarity)
|
||||
material_order_num = list(materialList.keys()).index(material_name) # Gets the Order Number of the Material
|
||||
deconstructed_MaterialDNA[a] = str(material_order_num + 1)
|
||||
complete = True
|
||||
if not complete:
|
||||
deconstructed_MaterialDNA[a] = "0"
|
||||
|
|
Ładowanie…
Reference in New Issue