kopia lustrzana https://github.com/torrinworx/Blend_My_NFTs
Initial commit
rodzic
7bb741a185
commit
6495b12654
|
@ -199,7 +199,7 @@ def generateNFT_DNA(collectionSize, enableRarity, enableLogic, logicFile, enable
|
|||
# print(f"Rarity DNA: {singleDNA}")
|
||||
|
||||
if enableLogic:
|
||||
singleDNA = Logic.logicafyDNAsingle(hierarchy, singleDNA, logicFile)
|
||||
singleDNA = Logic.logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity)
|
||||
# print(f"Original DNA: {singleDNA}")
|
||||
# print("============\n")
|
||||
|
||||
|
@ -328,7 +328,7 @@ def send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, e
|
|||
print(f"{bcolors.OK}Rarity is ON. Weights listed in .blend scene will be taken into account.\n{bcolors.RESET}")
|
||||
|
||||
if enableLogic:
|
||||
print(f"{bcolors.OK}Logic is ON. Rules listed in {logicFile} will be taken into account.\n{bcolors.RESET}")
|
||||
print(f"{bcolors.OK}Logic is ON. {len(list(logicFile.keys()))} rules from your Logic.json file will be applied.\n{bcolors.RESET}")
|
||||
|
||||
time_start = time.time()
|
||||
|
||||
|
|
|
@ -413,13 +413,13 @@ def render_and_save_NFTs(input):
|
|||
if not os.path.exists(solanaMetadataPath):
|
||||
os.makedirs(solanaMetadataPath)
|
||||
createSolanaMetaData(name, Order_Num, full_single_dna, dnaDictionary, metadataMaterialDict, input.custom_Fields,
|
||||
input.enableCustomFields, input.cardano_description, solanaMetadataPath)
|
||||
input.enableCustomFields, input.solana_description, solanaMetadataPath)
|
||||
|
||||
if input.erc721MetaData:
|
||||
if not os.path.exists(erc721MetadataPath):
|
||||
os.makedirs(erc721MetadataPath)
|
||||
createErc721MetaData(name, Order_Num, full_single_dna, dnaDictionary, metadataMaterialDict, input.custom_Fields,
|
||||
input.enableCustomFields, input.cardano_description, erc721MetadataPath)
|
||||
input.enableCustomFields, input.erc721_description, erc721MetadataPath)
|
||||
|
||||
if not os.path.exists(BMNFT_metaData_Folder):
|
||||
os.makedirs(BMNFT_metaData_Folder)
|
||||
|
|
183
main/Logic.py
183
main/Logic.py
|
@ -2,10 +2,11 @@
|
|||
# The purpose of this file is to add logic and rules to the DNA that are sent to the NFTRecord.json file in DNA_Generator.py
|
||||
|
||||
import bpy
|
||||
import json
|
||||
import random
|
||||
import collections
|
||||
|
||||
from .Constants import bcolors, removeList, remove_file_by_extension
|
||||
|
||||
|
||||
# Helper Functions
|
||||
def isAttorVar(hierarchy, items_List):
|
||||
|
@ -26,11 +27,13 @@ def isAttorVar(hierarchy, items_List):
|
|||
|
||||
return dict(items_returned)
|
||||
|
||||
|
||||
def getAttIndex(hierarchy, attribute):
|
||||
attList = list(hierarchy.keys())
|
||||
index = attList.index(attribute)
|
||||
return index
|
||||
|
||||
|
||||
def getVarNum(variant):
|
||||
if variant == "Empty":
|
||||
num = '0'
|
||||
|
@ -38,6 +41,7 @@ def getVarNum(variant):
|
|||
num = variant.split("_")[1]
|
||||
return num
|
||||
|
||||
|
||||
def items_to_num(items_List):
|
||||
num_List = {}
|
||||
for i in items_List:
|
||||
|
@ -49,47 +53,70 @@ def items_to_num(items_List):
|
|||
num_List[i] = variant_num_list
|
||||
return num_List
|
||||
|
||||
def rar_selectVar(hierarchy, items_List, deconstructed_DNA):
|
||||
for attribute in items_List:
|
||||
|
||||
a_attribute_index = getAttIndex(hierarchy, attribute)
|
||||
def select_from_then_list(hierarchy, deconstructed_DNA, then_num_list, enableRarity):
|
||||
for a in then_num_list:
|
||||
|
||||
selected_variants = items_List[attribute]
|
||||
hierarchy_selected_variants = list(hierarchy[attribute])
|
||||
a_attribute_index = getAttIndex(hierarchy, a)
|
||||
|
||||
selected_variants = then_num_list[a]
|
||||
hierarchy_selected_variants = list(hierarchy[a])
|
||||
|
||||
# Left over variants are removed for when the user only specifies individual variants instead of whole attributes
|
||||
left_over_variants = [x for x in hierarchy_selected_variants if x not in selected_variants]
|
||||
|
||||
# If 'a' is a full attribute:
|
||||
if not left_over_variants:
|
||||
deconstructed_DNA[int(a_attribute_index)] = "0"
|
||||
|
||||
# If 'a' is only part of an attribute (the user specified variant(s) from the attribute that don't add to the full
|
||||
# attribute):
|
||||
else:
|
||||
number_List_Of_i = []
|
||||
rarity_List_Of_i = []
|
||||
ifZeroBool = None
|
||||
variantNum = None
|
||||
|
||||
for a in left_over_variants:
|
||||
number = a.split("_")[1]
|
||||
rarity = a.split("_")[2]
|
||||
for b in left_over_variants:
|
||||
number = b.split("_")[1]
|
||||
rarity = b.split("_")[2]
|
||||
|
||||
number_List_Of_i.append(int(number))
|
||||
rarity_List_Of_i.append(float(rarity))
|
||||
|
||||
for x in rarity_List_Of_i:
|
||||
if x == 0:
|
||||
for b in rarity_List_Of_i:
|
||||
if b == 0:
|
||||
ifZeroBool = True
|
||||
elif x != 0:
|
||||
elif b != 0:
|
||||
ifZeroBool = False
|
||||
|
||||
if ifZeroBool:
|
||||
variantNum = random.choices(number_List_Of_i, k=1)
|
||||
|
||||
if not ifZeroBool:
|
||||
variantNum = random.choices(number_List_Of_i, weights=rarity_List_Of_i, k=1)
|
||||
|
||||
if enableRarity:
|
||||
try:
|
||||
if ifZeroBool:
|
||||
variantNum = random.choices(number_List_Of_i, k=1)
|
||||
elif not ifZeroBool:
|
||||
variantNum = random.choices(number_List_Of_i, weights=rarity_List_Of_i, k=1)
|
||||
except IndexError:
|
||||
raise IndexError(
|
||||
f"\n{bcolors.ERROR}Blend_My_NFTs Error:\n"
|
||||
f"An issue was found within the Attribute collection '{a}'. For more information on Blend_My_NFTs compatible scenes, "
|
||||
f"see:\n{bcolors.RESET}"
|
||||
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
|
||||
)
|
||||
else:
|
||||
try:
|
||||
variantNum = random.choices(number_List_Of_i, k=1)
|
||||
except IndexError:
|
||||
raise IndexError(
|
||||
f"\n{bcolors.ERROR}Blend_My_NFTs Error:\n"
|
||||
f"An issue was found within the Attribute collection '{a}'. For more information on Blend_My_NFTs compatible scenes, "
|
||||
f"see:\n{bcolors.RESET}"
|
||||
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
|
||||
)
|
||||
deconstructed_DNA[int(a_attribute_index)] = str(variantNum[0])
|
||||
|
||||
return deconstructed_DNA
|
||||
|
||||
|
||||
def reconstructDNA(deconstructedDNA):
|
||||
reconstructed_DNA = ""
|
||||
for a in deconstructedDNA:
|
||||
|
@ -97,117 +124,57 @@ def reconstructDNA(deconstructedDNA):
|
|||
reconstructed_DNA += num
|
||||
return (''.join(reconstructed_DNA.split('-', 1)))
|
||||
|
||||
def strip_empty_variant(num_list):
|
||||
"""Strips empty variants if full attribute collection. Used for processing below."""
|
||||
for i in num_list:
|
||||
var_list = num_list[i]
|
||||
|
||||
def check_if_dna_violates_rules(hierarchy, deconstructed_DNA, if_num_list, then_num_list):
|
||||
"""Returns True if singleDNA violates Rules stated in a Logic.json file."""
|
||||
violates_rule = None
|
||||
|
||||
# Strips empty variants if full attribute collection
|
||||
for i in if_num_list:
|
||||
var_list = if_num_list[i]
|
||||
if "0" in var_list:
|
||||
var_list.remove("0")
|
||||
num_list[i] = var_list
|
||||
return num_list
|
||||
if_num_list[i] = var_list
|
||||
|
||||
# Rule Checks:
|
||||
def never_with_Rule_Check(hierarchy, deconstructed_DNA, num_List1, num_List2):
|
||||
"""Returns True if singleDNA violates Never with Rule stated in Logic.json."""
|
||||
violates_rule = None
|
||||
for a in if_num_list:
|
||||
for b in then_num_list:
|
||||
# The attributes slot value from the DNA given 'a' from if_num_list and 'b' from then_num_list:
|
||||
attribute_slot_value_IF = str(deconstructed_DNA[getAttIndex(hierarchy, a)])
|
||||
attribute_slot_value_THEN = str(deconstructed_DNA[getAttIndex(hierarchy, b)])
|
||||
|
||||
num_List1 = strip_empty_variant(num_List1)
|
||||
num_List2 = strip_empty_variant(num_List2)
|
||||
|
||||
for a in num_List1:
|
||||
for b in num_List2:
|
||||
if str(deconstructed_DNA[getAttIndex(hierarchy, a)]) in num_List1[a] and \
|
||||
str(deconstructed_DNA[getAttIndex(hierarchy, b)]) in num_List2[b]:
|
||||
if attribute_slot_value_IF in if_num_list[a] and attribute_slot_value_THEN in then_num_list[b]:
|
||||
violates_rule = True
|
||||
return violates_rule
|
||||
else:
|
||||
violates_rule = False
|
||||
return violates_rule
|
||||
|
||||
def only_with_Rule_Check(hierarchy, deconstructed_DNA, num_List1, num_List2):
|
||||
"""Returns True if singleDNA violates Only with Rule stated in Logic.json."""
|
||||
violates_rule = None
|
||||
|
||||
for a in num_List1:
|
||||
for b in num_List2:
|
||||
if str(deconstructed_DNA[getAttIndex(hierarchy, a)]) in num_List1[a] and \
|
||||
str(deconstructed_DNA[getAttIndex(hierarchy, b)]) not in num_List2[b]:
|
||||
violates_rule = True
|
||||
return violates_rule
|
||||
|
||||
else:
|
||||
violates_rule = False
|
||||
return violates_rule
|
||||
|
||||
def always_with_Rule_Check(hierarchy, deconstructed_DNA, num_List1, num_List2):
|
||||
"""Returns True if singleDNA violates Always with Rule stated in Logic.json."""
|
||||
violates_rule = None
|
||||
|
||||
for a in num_List2:
|
||||
if str(deconstructed_DNA[getAttIndex(hierarchy, a)]) not in num_List2[a]:
|
||||
violates_rule = True
|
||||
return violates_rule
|
||||
else:
|
||||
violates_rule = False
|
||||
return violates_rule
|
||||
|
||||
|
||||
# Main Function
|
||||
def logicafyDNAsingle(hierarchy, singleDNA, logicFile):
|
||||
def logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity):
|
||||
|
||||
deconstructed_DNA = singleDNA.split("-")
|
||||
|
||||
didReconstruct = True
|
||||
originalDNA = str(singleDNA)
|
||||
|
||||
while didReconstruct:
|
||||
didReconstruct = False
|
||||
for rule in logicFile:
|
||||
items_List1 = isAttorVar(hierarchy, logicFile[rule]["Items-1"])
|
||||
items_List2 = isAttorVar(hierarchy, logicFile[rule]["Items-2"])
|
||||
num_List1 = items_to_num(items_List1)
|
||||
num_List2 = items_to_num(items_List2)
|
||||
# Items from 'IF' key for a given rule
|
||||
if_list = isAttorVar(hierarchy, logicFile[rule]["IF"])
|
||||
if_num_list = items_to_num(if_list)
|
||||
|
||||
if logicFile[rule]["Rule-Type"] == "Never With":
|
||||
if never_with_Rule_Check(hierarchy, deconstructed_DNA, num_List1, num_List2):
|
||||
# Items from 'THEN' key for a given rule
|
||||
then_list = isAttorVar(hierarchy, logicFile[rule]["THEN"])
|
||||
then_num_list = items_to_num(then_list)
|
||||
|
||||
rand_bool = bool(random.getrandbits(1))
|
||||
if check_if_dna_violates_rules(hierarchy, deconstructed_DNA, if_num_list, then_num_list):
|
||||
deconstructed_DNA = select_from_then_list(hierarchy, deconstructed_DNA, then_num_list, enableRarity)
|
||||
|
||||
if rand_bool:
|
||||
deconstructed_DNA = rar_selectVar(hierarchy, items_List2, deconstructed_DNA)
|
||||
|
||||
if not rand_bool:
|
||||
deconstructed_DNA = rar_selectVar(hierarchy, items_List1, deconstructed_DNA)
|
||||
|
||||
newDNA = reconstructDNA(deconstructed_DNA)
|
||||
if newDNA != originalDNA:
|
||||
originalDNA = str(newDNA)
|
||||
didReconstruct = True
|
||||
break
|
||||
|
||||
if logicFile[rule]["Rule-Type"] == "Only With":
|
||||
if only_with_Rule_Check(hierarchy, deconstructed_DNA, num_List1, num_List2):
|
||||
for b in num_List1:
|
||||
if "0" in num_List1[b]: # If complete attribute
|
||||
deconstructed_DNA[getAttIndex(hierarchy, b)] = "0"
|
||||
|
||||
if "0" not in num_List1[b]: # Not complete attribute, select from other variants with rarity:
|
||||
deconstructed_DNA = rar_selectVar(hierarchy, items_List1, deconstructed_DNA)
|
||||
|
||||
newDNA = reconstructDNA(deconstructed_DNA)
|
||||
if newDNA != originalDNA:
|
||||
originalDNA = str(newDNA)
|
||||
didReconstruct = True
|
||||
break
|
||||
|
||||
if logicFile[rule]["Rule-Type"] == "Always With":
|
||||
if always_with_Rule_Check(hierarchy, deconstructed_DNA, num_List1, num_List2):
|
||||
deconstructed_DNA = rar_selectVar(hierarchy, items_List1, deconstructed_DNA)
|
||||
|
||||
newDNA = reconstructDNA(deconstructed_DNA)
|
||||
if newDNA != originalDNA:
|
||||
originalDNA = str(newDNA)
|
||||
didReconstruct = True
|
||||
break
|
||||
newDNA = reconstructDNA(deconstructed_DNA)
|
||||
if newDNA != originalDNA:
|
||||
originalDNA = str(newDNA)
|
||||
didReconstruct = True
|
||||
break
|
||||
|
||||
return str(reconstructDNA(deconstructed_DNA))
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
import bpy
|
||||
import random
|
||||
|
||||
from .Constants import bcolors, removeList, remove_file_by_extension
|
||||
|
||||
|
||||
def createDNArarity(hierarchy):
|
||||
"""
|
||||
Sorts through DataDictionary and appropriately weights each variant based on their rarity percentage set in Blender
|
||||
|
@ -32,10 +35,18 @@ def createDNArarity(hierarchy):
|
|||
elif x != 0:
|
||||
ifZeroBool = False
|
||||
|
||||
if ifZeroBool:
|
||||
variantByNum = random.choices(number_List_Of_i, k=1)
|
||||
elif not ifZeroBool:
|
||||
variantByNum = random.choices(number_List_Of_i, weights=rarity_List_Of_i, k=1)
|
||||
try:
|
||||
if ifZeroBool:
|
||||
variantByNum = random.choices(number_List_Of_i, k=1)
|
||||
elif not ifZeroBool:
|
||||
variantByNum = random.choices(number_List_Of_i, weights=rarity_List_Of_i, k=1)
|
||||
except IndexError:
|
||||
raise IndexError(
|
||||
f"\n{bcolors.ERROR}Blend_My_NFTs Error:\n"
|
||||
f"An issue was found within the Attribute collection '{i}'. For more information on Blend_My_NFTs compatible scenes, "
|
||||
f"see:\n{bcolors.RESET}"
|
||||
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
|
||||
)
|
||||
|
||||
singleDNA += "-" + str(variantByNum[0])
|
||||
singleDNA = ''.join(singleDNA.split('-', 1))
|
||||
|
|
Ładowanie…
Reference in New Issue