kopia lustrzana https://github.com/torrinworx/Blend_My_NFTs
Merge pull request #94 from torrinworx/Material_Randomizer_Metapanda
Further integration and creation of the Material_Generator.pypull/110/head
commit
3e0908bfb3
102
__init__.py
102
__init__.py
|
@ -8,7 +8,6 @@ bl_info = {
|
|||
"category": "Development",
|
||||
}
|
||||
|
||||
|
||||
# ======== Import handling ======== #
|
||||
|
||||
import bpy
|
||||
|
@ -34,15 +33,16 @@ from main import \
|
|||
HeadlessUtil, \
|
||||
loading_animation, \
|
||||
Logic, \
|
||||
Material_Generator, \
|
||||
Metadata, \
|
||||
Rarity, \
|
||||
Refactorer
|
||||
|
||||
from UILists import \
|
||||
Custom_Metadata_UIList, \
|
||||
Logic_UIList
|
||||
|
||||
if "bpy" in locals():
|
||||
|
||||
modules = {
|
||||
"Batch_Sorter": Batch_Sorter,
|
||||
"Checks": Checks,
|
||||
|
@ -52,6 +52,7 @@ if "bpy" in locals():
|
|||
"HeadlessUtil": HeadlessUtil,
|
||||
"loading_animation": loading_animation,
|
||||
"Logic": Logic,
|
||||
"Material_Generator": Material_Generator,
|
||||
"Metadata": Metadata,
|
||||
"Rarity": Rarity,
|
||||
"Refactorer": Refactorer,
|
||||
|
@ -69,6 +70,7 @@ if "bpy" in locals():
|
|||
combinations: int = 0
|
||||
recommended_limit: int = 0
|
||||
|
||||
|
||||
@persistent
|
||||
def Refresh_UI(dummy1, dummy2):
|
||||
"""
|
||||
|
@ -96,6 +98,7 @@ def Refresh_UI(dummy1, dummy2):
|
|||
|
||||
redraw_panel(refresh_panel_classes)
|
||||
|
||||
|
||||
bpy.app.handlers.depsgraph_update_post.append(Refresh_UI)
|
||||
|
||||
|
||||
|
@ -115,10 +118,12 @@ def make_directories(save_path):
|
|||
os.makedirs(nftBatch_save_path)
|
||||
return Blend_My_NFTs_Output, batch_json_save_path, nftBatch_save_path
|
||||
|
||||
|
||||
def runAsHeadless():
|
||||
"""
|
||||
For use when running from the command line.
|
||||
"""
|
||||
|
||||
def dumpSettings(settings):
|
||||
output = (
|
||||
f"nftName={settings.nftName}\n"
|
||||
|
@ -142,6 +147,8 @@ def runAsHeadless():
|
|||
f"solana_description={settings.solana_description}\n"
|
||||
f"enableCustomFields={str(settings.enableCustomFields)}\n"
|
||||
f"customfieldsFile={settings.customfieldsFile}\n"
|
||||
f"enableMaterials={str(settings.customfieldsFile)}\n"
|
||||
f"materialsFile={settings.materialsFile}\n"
|
||||
)
|
||||
print(output)
|
||||
|
||||
|
@ -179,6 +186,8 @@ def runAsHeadless():
|
|||
settings.solanaDescription = pairs[18][1]
|
||||
settings.enableCustomFields = pairs[19][1] == 'True'
|
||||
settings.customfieldsFile = pairs[20][1]
|
||||
settings.enableMaterials = pairs[21][1] == 'True'
|
||||
settings.materialsFile = pairs[22][1]
|
||||
|
||||
if args.save_path:
|
||||
settings.save_path = args.save_path
|
||||
|
@ -199,10 +208,13 @@ def runAsHeadless():
|
|||
enableRarity = settings.enableRarity
|
||||
enableLogic = settings.enableLogic
|
||||
|
||||
enableMaterials = settings.enableMaterials
|
||||
materialsFile = settings.materialsFile
|
||||
|
||||
Blend_My_NFTs_Output, batch_json_save_path, nftBatch_save_path = make_directories(save_path)
|
||||
|
||||
DNA_Generator.send_To_Record_JSON(maxNFTs, nftsPerBatch, save_path, enableRarity, enableLogic, logicFile,
|
||||
Blend_My_NFTs_Output)
|
||||
enableMaterials, materialsFile, Blend_My_NFTs_Output)
|
||||
Batch_Sorter.makeBatches(nftName, maxNFTs, nftsPerBatch, save_path, batch_json_save_path)
|
||||
|
||||
elif args.operation == 'generate-nfts':
|
||||
|
@ -255,7 +267,6 @@ def runAsHeadless():
|
|||
|
||||
# ======== User input Property Group ======== #
|
||||
class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
|
||||
|
||||
# Create NFT Data Panel:
|
||||
|
||||
nftName: bpy.props.StringProperty(name="NFT Name")
|
||||
|
@ -283,6 +294,15 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
|
|||
subtype="FILE_PATH"
|
||||
)
|
||||
|
||||
enableMaterials: bpy.props.BoolProperty(name="Enable Materials")
|
||||
materialsFile: bpy.props.StringProperty(
|
||||
name="Materials File",
|
||||
description="Path where Materials.json is located.",
|
||||
default="",
|
||||
maxlen=1024,
|
||||
subtype="FILE_PATH"
|
||||
)
|
||||
|
||||
# Generate NFTs Panel:
|
||||
imageBool: bpy.props.BoolProperty(name="Image")
|
||||
imageEnum: bpy.props.EnumProperty(
|
||||
|
@ -312,17 +332,20 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
|
|||
description="Select 3D Model file format",
|
||||
items=[
|
||||
('GLB', '.glb', 'Export NFT as .glb'),
|
||||
('GLTF_SEPARATE', '.gltf + .bin + textures', 'Export NFT as .gltf with separated textures in .bin + textures.'),
|
||||
('GLTF_SEPARATE', '.gltf + .bin + textures',
|
||||
'Export NFT as .gltf with separated textures in .bin + textures.'),
|
||||
('GLTF_EMBEDDED', '.gltf', 'Export NFT as embedded .gltf file that contains textures.'),
|
||||
('FBX', '.fbx', 'Export NFT as .fbx'),
|
||||
('OBJ', '.obj', 'Export NFT as .obj'),
|
||||
('X3D', '.x3d', 'Export NFT as .x3d'),
|
||||
('STL', '.stl', 'Export NFT as .stl'),
|
||||
('VOX', '.vox (Experimental)', 'Export NFT as .vox, requires the voxwriter add on: https://github.com/Spyduck/voxwriter')
|
||||
('VOX', '.vox (Experimental)',
|
||||
'Export NFT as .vox, requires the voxwriter add on: https://github.com/Spyduck/voxwriter')
|
||||
]
|
||||
)
|
||||
|
||||
batchToGenerate: bpy.props.IntProperty(name="Batch To Generate", default=1, min=1) # max=(collectionSize / nftsPerBatch)
|
||||
batchToGenerate: bpy.props.IntProperty(name="Batch To Generate", default=1,
|
||||
min=1)
|
||||
|
||||
# Refactor Batches & Create Metadata Panel:
|
||||
cardanoMetaDataBool: bpy.props.BoolProperty(name="Cardano Cip")
|
||||
|
@ -361,19 +384,19 @@ class createData(bpy.types.Operator):
|
|||
name="Reverse Order")
|
||||
|
||||
def execute(self, context):
|
||||
|
||||
nftName = bpy.context.scene.input_tool.nftName
|
||||
collectionSize = bpy.context.scene.input_tool.collectionSize
|
||||
nftsPerBatch = bpy.context.scene.input_tool.nftsPerBatch
|
||||
save_path = bpy.path.abspath(bpy.context.scene.input_tool.save_path)
|
||||
logicFile = bpy.path.abspath(bpy.context.scene.input_tool.logicFile) # Logic_Dict will replace this, remove the open(logicFile)
|
||||
|
||||
enableRarity = bpy.context.scene.input_tool.enableRarity
|
||||
|
||||
enableLogic = bpy.context.scene.input_tool.enableLogic
|
||||
enable_Logic_Json = bpy.context.scene.input_tool.enable_Logic_Json
|
||||
logicFile = bpy.path.abspath(bpy.context.scene.input_tool.logicFile)
|
||||
|
||||
Logic_Dict = {}
|
||||
|
||||
enableMaterials = bpy.context.scene.input_tool.enableMaterials
|
||||
materialsFile = bpy.path.abspath(bpy.context.scene.input_tool.materialsFile)
|
||||
|
||||
# Handling Custom Fields UIList input:
|
||||
if enableLogic:
|
||||
|
@ -381,9 +404,10 @@ class createData(bpy.types.Operator):
|
|||
logicFile = json.load(open(logicFile))
|
||||
|
||||
Blend_My_NFTs_Output, batch_json_save_path, nftBatch_save_path = make_directories(save_path)
|
||||
DNA_Generator.send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, enableLogic,
|
||||
logicFile, Blend_My_NFTs_Output)
|
||||
DNA_Generator.send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, enableLogic, logicFile,
|
||||
enableMaterials, materialsFile, Blend_My_NFTs_Output)
|
||||
Batch_Sorter.makeBatches(nftName, collectionSize, nftsPerBatch, save_path, batch_json_save_path)
|
||||
|
||||
if enable_Logic_Json and not logicFile:
|
||||
self.report({'ERROR'}, f"No Logic.json file path set. Please set the file path to your Logic.json file.")
|
||||
|
||||
|
@ -405,9 +429,8 @@ class createData(bpy.types.Operator):
|
|||
}
|
||||
num += 1
|
||||
Blend_My_NFTs_Output, batch_json_save_path, nftBatch_save_path = make_directories(save_path)
|
||||
DNA_Generator.send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity,
|
||||
enableLogic,
|
||||
logicFile, Blend_My_NFTs_Output)
|
||||
DNA_Generator.send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, enableLogic, logicFile,
|
||||
enableMaterials, materialsFile, Blend_My_NFTs_Output)
|
||||
Batch_Sorter.makeBatches(nftName, collectionSize, nftsPerBatch, save_path, batch_json_save_path)
|
||||
else:
|
||||
logicFile = {}
|
||||
|
@ -423,19 +446,19 @@ class createData(bpy.types.Operator):
|
|||
}
|
||||
num += 1
|
||||
Blend_My_NFTs_Output, batch_json_save_path, nftBatch_save_path = make_directories(save_path)
|
||||
DNA_Generator.send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity,
|
||||
enableLogic,
|
||||
logicFile, Blend_My_NFTs_Output)
|
||||
DNA_Generator.send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, enableLogic, logicFile,
|
||||
enableMaterials, materialsFile, Blend_My_NFTs_Output)
|
||||
Batch_Sorter.makeBatches(nftName, collectionSize, nftsPerBatch, save_path, batch_json_save_path)
|
||||
|
||||
if not enableLogic:
|
||||
Blend_My_NFTs_Output, batch_json_save_path, nftBatch_save_path = make_directories(save_path)
|
||||
DNA_Generator.send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, enableLogic,
|
||||
logicFile, Blend_My_NFTs_Output)
|
||||
DNA_Generator.send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, enableLogic, logicFile,
|
||||
enableMaterials, materialsFile, Blend_My_NFTs_Output)
|
||||
Batch_Sorter.makeBatches(nftName, collectionSize, nftsPerBatch, save_path, batch_json_save_path)
|
||||
self.report({'INFO'}, f"NFT Data created!")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class exportNFTs(bpy.types.Operator):
|
||||
bl_idname = 'exporter.nfts'
|
||||
bl_label = 'Export NFTs'
|
||||
|
@ -459,21 +482,27 @@ class exportNFTs(bpy.types.Operator):
|
|||
enableModelsBlender = bpy.context.scene.input_tool.modelBool
|
||||
modelFileFormat = bpy.context.scene.input_tool.modelEnum
|
||||
|
||||
enableMaterials = bpy.context.scene.input_tool.enableMaterials
|
||||
materialsFile = bpy.path.abspath(bpy.context.scene.input_tool.materialsFile)
|
||||
|
||||
# fail state variables, set to no fail due to resume_failed_batch() Operator in BMNFTS_PT_GenerateNFTs Panel
|
||||
fail_state = False
|
||||
failed_batch = None
|
||||
failed_dna = None
|
||||
failed_dna_index = None
|
||||
|
||||
Exporter.render_and_save_NFTs(nftName, collectionSize, batchToGenerate, batch_json_save_path, nftBatch_save_path, enableImages,
|
||||
Exporter.render_and_save_NFTs(nftName, collectionSize, batchToGenerate, batch_json_save_path,
|
||||
nftBatch_save_path, enableImages,
|
||||
imageFileFormat, enableAnimations, animationFileFormat, enableModelsBlender,
|
||||
modelFileFormat, fail_state, failed_batch, failed_dna, failed_dna_index
|
||||
modelFileFormat, fail_state, failed_batch, failed_dna, failed_dna_index,
|
||||
enableMaterials, materialsFile
|
||||
)
|
||||
|
||||
self.report({'INFO'}, f"All NFTs generated for batch {batchToGenerate}!")
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class resume_failed_batch(bpy.types.Operator):
|
||||
bl_idname = 'exporter.resume_nfts'
|
||||
bl_label = 'Resume Failed Batch'
|
||||
|
@ -500,7 +529,8 @@ class resume_failed_batch(bpy.types.Operator):
|
|||
enableModelsBlender = batch["Generation Save"][-1]["Render_Settings"]["enableModelsBlender"]
|
||||
modelFileFormat = batch["Generation Save"][-1]["Render_Settings"]["modelFileFormat"]
|
||||
|
||||
Exporter.render_and_save_NFTs(nftName, collectionSize, failed_batch, batch_json_save_path, nftBatch_save_path, enableImages,
|
||||
Exporter.render_and_save_NFTs(nftName, collectionSize, failed_batch, batch_json_save_path, nftBatch_save_path,
|
||||
enableImages,
|
||||
imageFileFormat, enableAnimations, animationFileFormat, enableModelsBlender,
|
||||
modelFileFormat, fail_state, failed_batch, failed_dna, failed_dna_index
|
||||
)
|
||||
|
@ -509,6 +539,7 @@ class resume_failed_batch(bpy.types.Operator):
|
|||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class refactor_Batches(bpy.types.Operator):
|
||||
"""Refactor your collection? This action cannot be undone."""
|
||||
bl_idname = 'refactor.batches'
|
||||
|
@ -563,6 +594,7 @@ class refactor_Batches(bpy.types.Operator):
|
|||
def invoke(self, context, event):
|
||||
return context.window_manager.invoke_confirm(self, event)
|
||||
|
||||
|
||||
class export_settings(bpy.types.Operator):
|
||||
"""Export your settings into a configuration file."""
|
||||
bl_idname = 'export.settings'
|
||||
|
@ -621,6 +653,10 @@ class export_settings(bpy.types.Operator):
|
|||
"#Enable Custom Fields\n"
|
||||
f"enableCustomFields={str(settings.enableCustomFields)}\n"
|
||||
f"customfieldsFile={settings.customfieldsFile}\n"
|
||||
"\n"
|
||||
"#Enable Materials\n"
|
||||
f"enableMaterials={str(settings.enableMaterials)}\n"
|
||||
f"materialsFile={settings.materialsFile}\n"
|
||||
)
|
||||
|
||||
print(output, file=config)
|
||||
|
@ -696,9 +732,17 @@ class BMNFTS_PT_CreateData(bpy.types.Panel):
|
|||
row = layout.row()
|
||||
row.prop(input_tool_scene, "logicFile")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(input_tool_scene, "enableMaterials")
|
||||
|
||||
if bpy.context.scene.input_tool.enableMaterials:
|
||||
row = layout.row()
|
||||
row.prop(input_tool_scene, "materialsFile")
|
||||
|
||||
row = layout.row()
|
||||
self.layout.operator("create.data", icon='DISCLOSURE_TRI_RIGHT', text="Create Data")
|
||||
|
||||
|
||||
class BMNFTS_PT_GenerateNFTs(bpy.types.Panel):
|
||||
bl_label = "Generate NFTs"
|
||||
bl_idname = "BMNFTS_PT_GenerateNFTs"
|
||||
|
@ -751,6 +795,7 @@ class BMNFTS_PT_GenerateNFTs(bpy.types.Panel):
|
|||
row = layout.row()
|
||||
self.layout.operator("exporter.nfts", icon='RENDER_RESULT', text="Generate NFTs")
|
||||
|
||||
|
||||
class BMNFTS_PT_Refactor(bpy.types.Panel):
|
||||
bl_label = "Refactor Batches & Create Metadata"
|
||||
bl_idname = "BMNFTS_PT_Refactor"
|
||||
|
@ -825,6 +870,7 @@ class BMNFTS_PT_Refactor(bpy.types.Panel):
|
|||
row = layout.row()
|
||||
self.layout.operator("refactor.batches", icon='FOLDER_REDIRECT', text="Refactor Batches & Create Metadata")
|
||||
|
||||
|
||||
class BMNFTS_PT_Other(bpy.types.Panel):
|
||||
bl_label = "Other"
|
||||
bl_idname = "BMNFTS_PT_Other"
|
||||
|
@ -853,6 +899,11 @@ class BMNFTS_PT_Other(bpy.types.Panel):
|
|||
row = layout.row()
|
||||
layout.label(text=f"**Set a Save Path in Create NFT Data to Export Settings")
|
||||
|
||||
row = layout.row()
|
||||
|
||||
row = layout.row()
|
||||
layout.label(text=f"Looking for help?")
|
||||
|
||||
row = layout.row()
|
||||
row.operator("wm.url_open", text="Blend_My_NFTs Documentation",
|
||||
icon='URL').url = "https://github.com/torrinworx/Blend_My_NFTs"
|
||||
|
@ -860,7 +911,6 @@ class BMNFTS_PT_Other(bpy.types.Panel):
|
|||
row = layout.row()
|
||||
row.operator("wm.url_open", text="YouTube Tutorials",
|
||||
icon='URL').url = "https://www.youtube.com/watch?v=ygKJYz4BjRs&list=PLuVvzaanutXcYtWmPVKu2bx83EYNxLRsX"
|
||||
|
||||
row = layout.row()
|
||||
row.operator("wm.url_open", text="Join Our Discord Community!",
|
||||
icon='URL').url = "https://discord.gg/UpZt5Un57t"
|
||||
|
@ -885,6 +935,7 @@ classes = (
|
|||
BMNFTS_PT_Other,
|
||||
) + Custom_Metadata_UIList.classes_Custom_Metadata_UIList + Logic_UIList.classes_Logic_UIList
|
||||
|
||||
|
||||
def register():
|
||||
for cls in classes:
|
||||
bpy.utils.register_class(cls)
|
||||
|
@ -897,7 +948,6 @@ def register():
|
|||
bpy.types.Scene.logic_fields = CollectionProperty(type=Logic_UIList.CUSTOM_logic_objectCollection)
|
||||
bpy.types.Scene.logic_fields_index = IntProperty()
|
||||
|
||||
|
||||
def unregister():
|
||||
for cls in reversed(classes):
|
||||
bpy.utils.unregister_class(cls)
|
||||
|
|
|
@ -10,7 +10,7 @@ import json
|
|||
import random
|
||||
from functools import partial
|
||||
from .loading_animation import Loader
|
||||
from . import Rarity, Logic, Checks
|
||||
from . import Rarity, Logic, Checks, Material_Generator
|
||||
from .Constants import bcolors, removeList, remove_file_by_extension
|
||||
|
||||
|
||||
|
@ -126,7 +126,7 @@ def get_hierarchy():
|
|||
|
||||
return hierarchy
|
||||
|
||||
def generateNFT_DNA(collectionSize, logicFile, enableRarity, enableLogic):
|
||||
def generateNFT_DNA(collectionSize, enableRarity, enableLogic, logicFile, enableMaterials, materialsFile):
|
||||
"""
|
||||
Returns batchDataDictionary containing the number of NFT combinations, hierarchy, and the DNAList.
|
||||
"""
|
||||
|
@ -172,8 +172,14 @@ def generateNFT_DNA(collectionSize, logicFile, enableRarity, enableLogic):
|
|||
|
||||
if enableLogic:
|
||||
singleDNA = Logic.logicafyDNAsingle(hierarchy, singleDNA, logicFile)
|
||||
# print(f"Logic DNA: {singleDNA}")
|
||||
# print("============\n")
|
||||
print(f"Original DNA: {singleDNA}")
|
||||
print("============\n")
|
||||
|
||||
if enableMaterials:
|
||||
singleDNA = Material_Generator.apply_materials(hierarchy, singleDNA, materialsFile)
|
||||
print(f"Materials DNA: {singleDNA}")
|
||||
print("============\n")
|
||||
|
||||
return singleDNA
|
||||
|
||||
def create_DNAList():
|
||||
|
@ -202,7 +208,8 @@ def generateNFT_DNA(collectionSize, logicFile, enableRarity, enableLogic):
|
|||
|
||||
return DataDictionary
|
||||
|
||||
def send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, enableLogic, logicFile, Blend_My_NFTs_Output):
|
||||
def send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, enableLogic, logicFile, enableMaterials,
|
||||
materialsFile, Blend_My_NFTs_Output):
|
||||
"""
|
||||
Creates NFTRecord.json file and sends "batchDataDictionary" 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
|
||||
|
@ -232,7 +239,8 @@ def send_To_Record_JSON(collectionSize, nftsPerBatch, save_path, enableRarity, e
|
|||
|
||||
def create_nft_data():
|
||||
try:
|
||||
DataDictionary = generateNFT_DNA(collectionSize, logicFile, enableRarity, enableLogic)
|
||||
DataDictionary = generateNFT_DNA(collectionSize, enableRarity, enableLogic, logicFile, enableMaterials,
|
||||
materialsFile)
|
||||
NFTRecord_save_path = os.path.join(Blend_My_NFTs_Output, "NFTRecord.json")
|
||||
|
||||
# Checks:
|
||||
|
|
|
@ -18,7 +18,9 @@ def save_batch(batch, file_name):
|
|||
with open(os.path.join(file_name), 'w') as outfile:
|
||||
outfile.write(saved_batch + '\n')
|
||||
|
||||
def save_generation_state(batchToGenerate, batch_json_save_path, nftBatch_save_path, enableImages, imageFileFormat, enableAnimations,
|
||||
|
||||
def save_generation_state(batchToGenerate, batch_json_save_path, nftBatch_save_path, enableImages, imageFileFormat,
|
||||
enableAnimations,
|
||||
animationFileFormat, enableModelsBlender, modelFileFormat):
|
||||
"""Saves date and time of generation start, and generation types; Images, Animations, 3D Models, and the file types for each."""
|
||||
file_name = os.path.join(batch_json_save_path, "Batch{}.json".format(batchToGenerate))
|
||||
|
@ -51,14 +53,14 @@ def save_generation_state(batchToGenerate, batch_json_save_path, nftBatch_save_p
|
|||
|
||||
save_batch(batch, file_name)
|
||||
|
||||
def save_completed(single_dna, a, x, batch_json_save_path, batchToGenerate):
|
||||
|
||||
def save_completed(full_single_dna, a, x, batch_json_save_path, batchToGenerate):
|
||||
"""Saves progress of rendering to batch.json file."""
|
||||
|
||||
file_name = os.path.join(batch_json_save_path, "Batch{}.json".format(batchToGenerate))
|
||||
batch = json.load(open(file_name))
|
||||
|
||||
index = batch["BatchDNAList"].index(a)
|
||||
batch["BatchDNAList"][index][single_dna]["Complete"] = True
|
||||
batch["BatchDNAList"][index][full_single_dna]["Complete"] = True
|
||||
batch["Generation Save"][-1]["DNA Generated"] = x
|
||||
|
||||
save_batch(batch, file_name)
|
||||
|
@ -79,17 +81,19 @@ def getBatchData(batchToGenerate, batch_json_save_path):
|
|||
|
||||
return NFTs_in_Batch, hierarchy, BatchDNAList
|
||||
|
||||
def render_and_save_NFTs(nftName, maxNFTs, batchToGenerate, batch_json_save_path, nftBatch_save_path, enableImages,
|
||||
|
||||
def render_and_save_NFTs(nftName, collectionSize, batchToGenerate, batch_json_save_path,
|
||||
nftBatch_save_path, enableImages,
|
||||
imageFileFormat, enableAnimations, animationFileFormat, enableModelsBlender,
|
||||
modelFileFormat, fail_state, failed_batch, failed_dna, failed_dna_index
|
||||
):
|
||||
modelFileFormat, fail_state, failed_batch, failed_dna, failed_dna_index,
|
||||
enableMaterials, materialsFile):
|
||||
"""
|
||||
Renders the NFT DNA in a Batch#.json, where # is renderBatch in config.py. Turns off the viewport camera and
|
||||
the render camera for all items in hierarchy.
|
||||
"""
|
||||
|
||||
NFTs_in_Batch, hierarchy, BatchDNAList = getBatchData(batchToGenerate, batch_json_save_path)
|
||||
|
||||
materialsFile = json.load(open(materialsFile))
|
||||
time_start_1 = time.time()
|
||||
|
||||
if fail_state:
|
||||
|
@ -104,7 +108,9 @@ def render_and_save_NFTs(nftName, maxNFTs, batchToGenerate, batch_json_save_path
|
|||
x = 1
|
||||
|
||||
for a in BatchDNAList:
|
||||
single_dna = list(a.keys())[0]
|
||||
full_single_dna = list(a.keys())[0]
|
||||
single_dna, material_dna = full_single_dna.split(':')
|
||||
|
||||
for i in hierarchy:
|
||||
for j in hierarchy[i]:
|
||||
bpy.data.collections[j].hide_render = True
|
||||
|
@ -129,19 +135,67 @@ def render_and_save_NFTs(nftName, maxNFTs, batchToGenerate, batch_json_save_path
|
|||
dnaDictionary.update({x: k})
|
||||
return dnaDictionary
|
||||
|
||||
def match_materialDNA_to_Material(single_dna, material_dna):
|
||||
"""
|
||||
Matches the Material DNA to it's selected Materials unless a 0 is present meaning no material for that variant was selected.
|
||||
"""
|
||||
listAttributes = list(hierarchy.keys())
|
||||
listDnaDecunstructed = single_dna.split('-')
|
||||
listMaterialDNADeconstructed = material_dna.split('-')
|
||||
|
||||
full_dna_dict = {}
|
||||
|
||||
for attribute, variant, material in zip(listAttributes, listDnaDecunstructed, listMaterialDNADeconstructed):
|
||||
|
||||
for var in hierarchy[attribute]:
|
||||
if hierarchy[attribute][var]['number'] == variant:
|
||||
variant = var
|
||||
|
||||
if material != '0':
|
||||
for variant_m in materialsFile:
|
||||
if variant == variant_m:
|
||||
for mat in materialsFile[variant_m]["Material List"]:
|
||||
if mat.split('_')[1] == material:
|
||||
material = mat
|
||||
|
||||
full_dna_dict[variant] = material
|
||||
|
||||
return full_dna_dict
|
||||
|
||||
dnaDictionary = match_DNA_to_Variant(single_dna)
|
||||
name = nftName + "_" + str(x)
|
||||
|
||||
print(f"\n{bcolors.OK}|---Generating NFT {x}/{NFTs_in_Batch} ---|{bcolors.RESET}")
|
||||
print(f"DNA attribute list:\n{dnaDictionary}\nDNA Code:{single_dna}")
|
||||
|
||||
if enableMaterials:
|
||||
materialdnaDictionary = match_materialDNA_to_Material(single_dna, material_dna)
|
||||
|
||||
for var_mat in list(materialdnaDictionary.keys()):
|
||||
if materialdnaDictionary[var_mat] != '0':
|
||||
if not materialsFile[var_mat]['Variant Objects']:
|
||||
"""
|
||||
If objects to apply material to not specified, apply to all objects in Variant collection.
|
||||
"""
|
||||
|
||||
for obj in bpy.data.collections[var_mat].all_objects:
|
||||
selected_object = bpy.data.objects.get(obj.name)
|
||||
selected_object.active_material = bpy.data.materials[materialdnaDictionary[var_mat]]
|
||||
|
||||
if materialsFile[var_mat]['Variant Objects']:
|
||||
"""
|
||||
If objects to apply material to are specified, apply material only to objects specified withing the Variant collection.
|
||||
"""
|
||||
for obj in materialsFile[var_mat]['Variant Objects']:
|
||||
selected_object = bpy.data.objects.get(obj)
|
||||
selected_object.active_material = bpy.data.materials[materialdnaDictionary[var_mat]]
|
||||
|
||||
for c in dnaDictionary:
|
||||
collection = dnaDictionary[c]
|
||||
if collection != '0':
|
||||
bpy.data.collections[collection].hide_render = False
|
||||
bpy.data.collections[collection].hide_viewport = False
|
||||
|
||||
|
||||
time_start_2 = time.time()
|
||||
|
||||
batchFolder = os.path.join(nftBatch_save_path, "Batch" + str(batchToGenerate))
|
||||
|
@ -292,7 +346,7 @@ def render_and_save_NFTs(nftName, maxNFTs, batchToGenerate, batch_json_save_path
|
|||
|
||||
print(f"Completed {name} render in {time.time() - time_start_2}s")
|
||||
|
||||
save_completed(single_dna, a, x, batch_json_save_path, batchToGenerate)
|
||||
save_completed(full_single_dna, a, x, batch_json_save_path, batchToGenerate)
|
||||
|
||||
x += 1
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
# Purpose:
|
||||
# The purpose of this file is to apply the materials a user sets in a given .json file to the Variant collection objects
|
||||
# also specified in the .json file. The Materialized DNA is then returned in the following format: 1-1-1:1-1-1
|
||||
# Where the numbers right of the ":" are the material numbers applied to the respective Variants to the left of the ":"
|
||||
|
||||
import bpy
|
||||
|
||||
import json
|
||||
import random
|
||||
|
||||
|
||||
def select_material(materialList):
|
||||
"""Selects a material from a passed material list. """
|
||||
|
||||
number_List_Of_i = []
|
||||
rarity_List_Of_i = []
|
||||
ifZeroBool = None
|
||||
|
||||
for material in materialList:
|
||||
|
||||
material_order_num = material.split("_")[1]
|
||||
number_List_Of_i.append(material_order_num)
|
||||
|
||||
material_rarity_percent = material.split("_")[1]
|
||||
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
|
||||
|
||||
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)
|
||||
|
||||
return selected_material[0]
|
||||
|
||||
def get_variant_att_index(variant, hierarchy):
|
||||
variant_attribute = None
|
||||
|
||||
for attribute in hierarchy:
|
||||
for variant_h in hierarchy[attribute]:
|
||||
if variant_h == variant:
|
||||
variant_attribute = attribute
|
||||
|
||||
attribute_index = list(hierarchy.keys()).index(variant_attribute)
|
||||
variant_order_num = variant.split("_")[1]
|
||||
return attribute_index, variant_order_num
|
||||
|
||||
def match_DNA_to_Variant(hierarchy, singleDNA):
|
||||
"""
|
||||
Matches each DNA number separated by "-" to its attribute, then its variant.
|
||||
"""
|
||||
|
||||
listAttributes = list(hierarchy.keys())
|
||||
listDnaDecunstructed = singleDNA.split('-')
|
||||
dnaDictionary = {}
|
||||
|
||||
for i, j in zip(listAttributes, listDnaDecunstructed):
|
||||
dnaDictionary[i] = j
|
||||
|
||||
for x in dnaDictionary:
|
||||
for k in hierarchy[x]:
|
||||
kNum = hierarchy[x][k]["number"]
|
||||
if kNum == dnaDictionary[x]:
|
||||
dnaDictionary.update({x: k})
|
||||
return dnaDictionary
|
||||
|
||||
def apply_materials(hierarchy, singleDNA, materialsFile):
|
||||
"""
|
||||
DNA with applied material example: "1-1:1-1" <Normal DNA>:<Selected Material for each Variant>
|
||||
|
||||
The Material DNA will select the material for the Variant order number in the NFT DNA based on the Variant Material
|
||||
list in the Variant_Material.json file.
|
||||
"""
|
||||
|
||||
singleDNADict = match_DNA_to_Variant(hierarchy, singleDNA)
|
||||
materialsFile = json.load(open(materialsFile))
|
||||
deconstructed_MaterialDNA = {}
|
||||
|
||||
for a in singleDNADict:
|
||||
complete = False
|
||||
for b in materialsFile:
|
||||
if singleDNADict[a] == b:
|
||||
mat = select_material(materialsFile[b]['Material List'])
|
||||
deconstructed_MaterialDNA[a] = mat
|
||||
complete = True
|
||||
if not complete:
|
||||
deconstructed_MaterialDNA[a] = "0"
|
||||
|
||||
material_DNA = ""
|
||||
for a in deconstructed_MaterialDNA:
|
||||
num = "-" + str(deconstructed_MaterialDNA[a])
|
||||
material_DNA += num
|
||||
material_DNA = ''.join(material_DNA.split('-', 1))
|
||||
|
||||
return f"{singleDNA}:{material_DNA}"
|
Ładowanie…
Reference in New Issue