pep8 formatting DNA_Generator.py

pull/142/head
Torrin Leonard 2022-08-24 11:10:22 -04:00
rodzic 3a35a66e75
commit 3715b30afa
2 zmienionych plików z 168 dodań i 134 usunięć

Wyświetl plik

@ -1,219 +1,246 @@
# Purpose: # Purpose:
# This file generates NFT DNA based on a .blend file scene structure and exports NFTRecord.json. # This file generates NFT DNA based on a .blend file scene structure and exports NFTRecord.json.
import bpy
import os import os
import time import time
import json import json
import random import random
import traceback
from functools import partial from functools import partial
from . import Logic, Material_Generator, Helpers from . import Logic, Material_Generator, Helpers
from .Helpers import TextColors
def generateNFT_DNA(collectionSize, enableRarity, enableLogic, logicFile, enableMaterials, materialsFile, enable_debug): def generate_nft_dna(
collection_size,
enable_rarity,
enable_logic,
logic_file,
enable_materials,
materials_file,
enable_debug
):
""" """
Returns batchDataDictionary containing the number of NFT combinations, hierarchy, and the DNAList. Returns batchDataDictionary containing the number of NFT combinations, hierarchy, and the dna_list.
""" """
hierarchy = Helpers.get_hierarchy() hierarchy = Helpers.get_hierarchy()
# DNA random, Rarity and Logic methods: # DNA random, Rarity and Logic methods:
DataDictionary = {} data_dictionary = {}
def createDNArandom(hierarchy): def create_dna_random(hierarchy):
"""Creates a single DNA randomly without Rarity or Logic.""" """Creates a single DNA randomly without Rarity or Logic."""
dnaStr = "" dna_str = ""
dnaStrList = [] dna_str_list = []
listOptionVariant = [] list_option_variant = []
for i in hierarchy: for i in hierarchy:
numChild = len(hierarchy[i]) num_child = len(hierarchy[i])
possibleNums = list(range(1, numChild + 1)) possible_nums = list(range(1, num_child + 1))
listOptionVariant.append(possibleNums) list_option_variant.append(possible_nums)
for i in listOptionVariant: for i in list_option_variant:
randomVariantNum = random.choices(i, k=1) random_variant_num = random.choices(i, k=1)
str1 = ''.join(str(e) for e in randomVariantNum) str1 = ''.join(str(e) for e in random_variant_num)
dnaStrList.append(str1) dna_str_list.append(str1)
for i in dnaStrList: for i in dna_str_list:
num = "-" + str(i) num = "-" + str(i)
dnaStr += num dna_str += num
dna = ''.join(dnaStr.split('-', 1)) dna = ''.join(dna_str.split('-', 1))
return str(dna) return str(dna)
def createDNArarity(hierarchy): def create_dna_rarity(hierarchy):
""" """
Sorts through DataDictionary and appropriately weights each variant based on their rarity percentage set in Blender Sorts through data_dictionary and appropriately weights each variant based on their rarity percentage set in Blender
("rarity" in DNA_Generator). Then ("rarity" in DNA_Generator). Then
""" """
singleDNA = "" single_dna = ""
for i in hierarchy: for i in hierarchy:
number_List_Of_i = [] number_list_of_i = []
rarity_List_Of_i = [] rarity_list_of_i = []
ifZeroBool = None if_zero_bool = None
for k in hierarchy[i]: for k in hierarchy[i]:
number = hierarchy[i][k]["number"] number = hierarchy[i][k]["number"]
number_List_Of_i.append(number) number_list_of_i.append(number)
rarity = hierarchy[i][k]["rarity"] rarity = hierarchy[i][k]["rarity"]
rarity_List_Of_i.append(float(rarity)) rarity_list_of_i.append(float(rarity))
for x in rarity_List_Of_i: for x in rarity_list_of_i:
if x == 0: if x == 0:
ifZeroBool = True if_zero_bool = True
elif x != 0: elif x != 0:
ifZeroBool = False if_zero_bool = False
try: try:
if ifZeroBool: if if_zero_bool:
variantByNum = random.choices(number_List_Of_i, k=1) variant_by_num = random.choices(number_list_of_i, k=1)
elif not ifZeroBool: elif not if_zero_bool:
variantByNum = random.choices(number_List_Of_i, weights=rarity_List_Of_i, k=1) variant_by_num = random.choices(number_list_of_i, weights=rarity_list_of_i, k=1)
except IndexError: except IndexError:
raise IndexError( raise IndexError(
f"\n{Helpers.TextColors.ERROR}Blend_My_NFTs Error:\n" f"\n{TextColors.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"An issue was found within the Attribute collection '{i}'. For more information on Blend_My_NFTs "
f"see:\n{Helpers.TextColors.RESET}" f"compatible scenes, see:\n{TextColors.RESET}"
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n" f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
) )
singleDNA += "-" + str(variantByNum[0]) single_dna += "-" + str(variant_by_num[0])
singleDNA = ''.join(singleDNA.split('-', 1)) single_dna = ''.join(single_dna.split('-', 1))
return singleDNA return single_dna
def singleCompleteDNA(): def singleCompleteDNA():
""" """
This function applies Rarity and Logic to a single DNA created by createDNASingle() if Rarity or Logic specified This function applies Rarity and Logic to a single DNA created by createDNASingle() if Rarity or Logic specified
""" """
singleDNA = "" single_dna = ""
if not enableRarity: if not enable_rarity:
singleDNA = createDNArandom(hierarchy) single_dna = create_dna_random(hierarchy)
# print("============") # print("============")
# print(f"Original DNA: {singleDNA}") # print(f"Original DNA: {single_dna}")
if enableRarity: if enable_rarity:
singleDNA = createDNArarity(hierarchy) single_dna = create_dna_rarity(hierarchy)
# print(f"Rarity DNA: {singleDNA}") # print(f"Rarity DNA: {single_dna}")
if enableLogic: if enable_logic:
singleDNA = Logic.logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, enableMaterials) single_dna = Logic.logicafyDNAsingle(hierarchy, single_dna, logic_file, enable_rarity, enable_materials)
# print(f"Logic DNA: {singleDNA}") # print(f"Logic DNA: {single_dna}")
if enableMaterials: if enable_materials:
singleDNA = Material_Generator.apply_materials(hierarchy, singleDNA, materialsFile, enableRarity) single_dna = Material_Generator.apply_materials(hierarchy, single_dna, materials_file, enable_rarity)
# print(f"Materials DNA: {singleDNA}") # print(f"Materials DNA: {single_dna}")
# print("============\n") # print("============\n")
return singleDNA return single_dna
def create_DNAList(): def create_dna_list():
"""Creates DNAList. Loops through createDNARandom() and applies Rarity, and Logic while checking if all DNA are unique""" """
DNASetReturn = set() Creates dna_list. Loops through createDNARandom() and applies Rarity, and Logic while checking if all DNA
are unique.
"""
dna_set_return = set()
for i in range(collectionSize): for i in range(collection_size):
dnaPushToList = partial(singleCompleteDNA) dna_push_to_list = partial(singleCompleteDNA)
DNASetReturn |= {''.join([dnaPushToList()]) for _ in range(collectionSize - len(DNASetReturn))} dna_set_return |= {''.join([dna_push_to_list()]) for _ in range(collection_size - len(dna_set_return))}
DNAListUnformatted = list(DNASetReturn) dna_list_non_formatted = list(dna_set_return)
DNAListFormatted = [] dna_list_formatted = []
DNA_Counter = 1 dna_counter = 1
for i in DNAListUnformatted: for i in dna_list_non_formatted:
DNAListFormatted.append({ dna_list_formatted.append({
i: { i: {
"Complete": False, "complete": False,
"Order_Num": DNA_Counter "order_num": dna_counter
} }
}) })
DNA_Counter += 1 dna_counter += 1
return DNAListFormatted return dna_list_formatted
DNAList = create_DNAList() dna_list = create_dna_list()
# Messages: # Messages:
Helpers.raise_warning_collection_size(DNAList, collectionSize) Helpers.raise_warning_collection_size(dna_list, collection_size)
# Data stored in batchDataDictionary: # Data stored in batchDataDictionary:
DataDictionary["numNFTsGenerated"] = len(DNAList) data_dictionary["num_nfts_generated"] = len(dna_list)
DataDictionary["hierarchy"] = hierarchy data_dictionary["hierarchy"] = hierarchy
DataDictionary["DNAList"] = DNAList data_dictionary["dna_list"] = dna_list
return DataDictionary return data_dictionary
def makeBatches(collectionSize, nftsPerBatch, save_path, batch_json_save_path): def make_batches(
collection_size,
nfts_per_batch,
save_path,
batch_json_save_path
):
""" """
Sorts through all the batches and outputs a given number of batches depending on collectionSize and nftsPerBatch. Sorts through all the batches and outputs a given number of batches depending on collectionSize and nftsPerBatch.
These files are then saved as Batch#.json files to batch_json_save_path These files are then saved as Batch#.json files to batch_json_save_path
""" """
# Clears the Batch Data folder of Batches: # Clears the Batch Data folder of Batches:
batchList = os.listdir(batch_json_save_path) batch_list = os.listdir(batch_json_save_path)
if batchList: if batch_list:
for i in batchList: for i in batch_list:
batch = os.path.join(batch_json_save_path, i) batch = os.path.join(batch_json_save_path, i)
if os.path.exists(batch): if os.path.exists(batch):
os.remove( os.remove(
os.path.join(batch_json_save_path, i) os.path.join(batch_json_save_path, i)
) )
Blend_My_NFTs_Output = os.path.join(save_path, "Blend_My_NFTs Output", "NFT_Data") blend_my_nf_ts_output = os.path.join(save_path, "Blend_My_NFTs Output", "NFT_Data")
NFTRecord_save_path = os.path.join(Blend_My_NFTs_Output, "NFTRecord.json") nft_record_save_path = os.path.join(blend_my_nf_ts_output, "NFTRecord.json")
DataDictionary = json.load(open(NFTRecord_save_path)) data_dictionary = json.load(open(nft_record_save_path))
numNFTsGenerated = DataDictionary["numNFTsGenerated"] num_nfts_generated = data_dictionary["num_nfts_generated"]
hierarchy = DataDictionary["hierarchy"] hierarchy = data_dictionary["hierarchy"]
DNAList = DataDictionary["DNAList"] dna_list = data_dictionary["dna_list"]
numBatches = collectionSize // nftsPerBatch num_batches = collection_size // nfts_per_batch
remainder_dna = collectionSize % nftsPerBatch remainder_dna = collection_size % nfts_per_batch
if remainder_dna > 0: if remainder_dna > 0:
numBatches += 1 num_batches += 1
print(f"To generate batches of {nftsPerBatch} DNA sequences per batch, with a total of {numNFTsGenerated}" print(f"To generate batches of {nfts_per_batch} DNA sequences per batch, with a total of {num_nfts_generated}"
f" possible NFT DNA sequences, the number of batches generated will be {numBatches}") f" possible NFT DNA sequences, the number of batches generated will be {num_batches}")
batches_dna_list = [] batches_dna_list = []
for i in range(numBatches): for i in range(num_batches):
BatchDNAList = [] if i != range(num_batches)[-1]:
if i != range(numBatches)[-1]: batch_dna_list = list(dna_list[0:nfts_per_batch])
BatchDNAList = list(DNAList[0:nftsPerBatch]) batches_dna_list.append(batch_dna_list)
batches_dna_list.append(BatchDNAList)
DNAList = [x for x in DNAList if x not in BatchDNAList] dna_list = [x for x in dna_list if x not in batch_dna_list]
else: else:
BatchDNAList = DNAList batch_dna_list = dna_list
batchDictionary = { batch_dictionary = {
"NFTs_in_Batch": int(len(BatchDNAList)), "nfts_in_batch": int(len(batch_dna_list)),
"hierarchy": hierarchy, "hierarchy": hierarchy,
"BatchDNAList": BatchDNAList "batch_dna_list": batch_dna_list
} }
batchDictionary = json.dumps(batchDictionary, indent=1, ensure_ascii=True) batch_dictionary = json.dumps(batch_dictionary, indent=1, ensure_ascii=True)
with open(os.path.join(batch_json_save_path, f"Batch{i + 1}.json"), "w") as outfile: with open(os.path.join(batch_json_save_path, f"Batch{i + 1}.json"), "w") as outfile:
outfile.write(batchDictionary) outfile.write(batch_dictionary)
def send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, enableLogic, logicFile, enableMaterials, def send_to_record(
materialsFile, Blend_My_NFTs_Output, batch_json_save_path, enable_debug): collection_size,
nfts_per_batch,
save_path,
enable_rarity,
enable_logic,
logic_file,
enable_materials,
materials_file,
blend_my_nfts_output,
batch_json_save_path,
enable_debug
):
""" """
Creates NFTRecord.json file and sends "batchDataDictionary" to it. NFTRecord.json is a permanent record of all DNA Creates NFTRecord.json file and sends "batch_data_dictionary" to it. NFTRecord.json is a permanent record of all DNA
you've generated with all attribute variants. If you add new variants or attributes to your .blend file, other scripts you've generated with all attribute variants. If you add new variants or attributes to your .blend file, other scripts
need to reference this .json file to generate new DNA and make note of the new attributes and variants to prevent need to reference this .json file to generate new DNA and make note of the new attributes and variants to prevent
repeate DNA. repeat DNA.
""" """
# Checking Scene is compatible with BMNFTs: # Checking Scene is compatible with BMNFTs:
@ -221,66 +248,73 @@ def send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, e
# Messages: # Messages:
print( print(
f"\n{Helpers.TextColors.OK}======== Creating NFT Data ========{Helpers.TextColors.RESET}" f"\n{TextColors.OK}======== Creating NFT Data ========{TextColors.RESET}"
f"\nGenerating {collectionSize} NFT DNA" f"\nGenerating {collection_size} NFT DNA"
) )
if not enableRarity and not enableLogic: if not enable_rarity and not enable_logic:
print( print(
f"{Helpers.TextColors.OK}NFT DNA will be determined randomly, no special properties or parameters are " f"{TextColors.OK}NFT DNA will be determined randomly, no special properties or parameters are "
f"applied.\n{Helpers.TextColors.RESET}") f"applied.\n{TextColors.RESET}")
if enableRarity: if enable_rarity:
print( print(
f"{Helpers.TextColors.OK}Rarity is ON. Weights listed in .blend scene will be taken into account." f"{TextColors.OK}Rarity is ON. Weights listed in .blend scene will be taken into account."
f"{Helpers.TextColors.RESET}" f"{TextColors.RESET}"
) )
if enableLogic: if enable_logic:
print( print(
f"{Helpers.TextColors.OK}Logic is ON. {len(list(logicFile.keys()))} rules detected and applied." f"{TextColors.OK}Logic is ON. {len(list(logic_file.keys()))} rules detected and applied."
f"{Helpers.TextColors.RESET}" f"{TextColors.RESET}"
) )
time_start = time.time() time_start = time.time()
def create_nft_data(): def create_nft_data():
try: try:
DataDictionary = generateNFT_DNA(collectionSize, enableRarity, enableLogic, logicFile, enableMaterials, data_dictionary = generate_nft_dna(
materialsFile, enable_debug) collection_size,
NFTRecord_save_path = os.path.join(Blend_My_NFTs_Output, "NFTRecord.json") enable_rarity,
enable_logic,
logic_file,
enable_materials,
materials_file,
enable_debug,
)
nft_record_save_path = os.path.join(blend_my_nfts_output, "NFTRecord.json")
# Checks: # Checks:
Helpers.raise_warning_max_nfts(nfts_per_batch, collection_size)
Helpers.raise_warning_max_nfts(nftsPerBatch, collectionSize) Helpers.check_duplicates(data_dictionary["dna_list"])
Helpers.check_duplicates(DataDictionary["DNAList"])
Helpers.raise_error_zero_combinations() Helpers.raise_error_zero_combinations()
if enableRarity: if enable_rarity:
Helpers.check_rarity(DataDictionary["hierarchy"], DataDictionary["DNAList"], Helpers.check_rarity(data_dictionary["hierarchy"], data_dictionary["dna_list"],
os.path.join(save_path, "Blend_My_NFTs Output/NFT_Data")) os.path.join(save_path, "Blend_My_NFTs Output/NFT_Data"))
except FileNotFoundError: except FileNotFoundError:
raise FileNotFoundError( raise FileNotFoundError(
f"\n{Helpers.TextColors.ERROR}Blend_My_NFTs Error:\n" f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n"
f"Data not saved to NFTRecord.json. Please review your Blender scene and ensure it follows " f"Data not saved to NFTRecord.json. Please review your Blender scene and ensure it follows "
f"the naming conventions and scene structure. For more information, " f"the naming conventions and scene structure. For more information, see:\n{TextColors.RESET}"
f"see:\n{Helpers.TextColors.RESET}"
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n" f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
) )
finally: finally:
loading.stop() loading.stop()
try: try:
ledger = json.dumps(DataDictionary, indent=1, ensure_ascii=True) ledger = json.dumps(data_dictionary, indent=1, ensure_ascii=True)
with open(NFTRecord_save_path, 'w') as outfile: with open(nft_record_save_path, 'w') as outfile:
outfile.write(ledger + '\n') outfile.write(ledger + '\n')
print( print(
f"\n{Helpers.TextColors.OK}Blend_My_NFTs Success:\n" f"\n{TextColors.OK}Blend_My_NFTs Success:\n"
f"{len(DataDictionary['DNAList'])} NFT DNA saved to {NFTRecord_save_path}. NFT DNA Successfully created.\n{Helpers.TextColors.RESET}") f"{len(data_dictionary['DNAList'])} NFT DNA saved to {nft_record_save_path}. NFT DNA Successfully "
f"created.\n{TextColors.RESET}")
except: except Exception:
traceback.print_exc()
raise ( raise (
f"\n{Helpers.TextColors.ERROR}Blend_My_NFTs Error:\n" f"\n{Helpers.TextColors.ERROR}Blend_My_NFTs Error:\n"
f"Data not saved to NFTRecord.json. Please review your Blender scene and ensure it follows " f"Data not saved to NFTRecord.json. Please review your Blender scene and ensure it follows "
@ -292,7 +326,7 @@ def send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, e
# Loading Animation: # Loading Animation:
loading = Helpers.Loader(f'Creating NFT DNA...', '').start() loading = Helpers.Loader(f'Creating NFT DNA...', '').start()
create_nft_data() create_nft_data()
makeBatches(collectionSize, nftsPerBatch, save_path, batch_json_save_path) make_batches(collection_size, nfts_per_batch, save_path, batch_json_save_path)
loading.stop() loading.stop()
time_end = time.time() time_end = time.time()

Wyświetl plik

@ -44,7 +44,7 @@ def send_To_Record_JSON(input, reverse_order=False):
num += 1 num += 1
DNA_Generator.send_To_Record_JSON(input.collectionSize, DNA_Generator.send_to_record(input.collectionSize,
input.nftsPerBatch, input.nftsPerBatch,
input.save_path, input.save_path,
input.enableRarity, input.enableRarity,