Pep8 formatting and renaming key variables

pull/142/head
Torrin Leonard 2022-08-24 13:04:20 -04:00
rodzic 7c389e15df
commit 57ec4b1ac1
12 zmienionych plików z 628 dodań i 556 usunięć

Wyświetl plik

@ -11,6 +11,7 @@ from bpy.types import (Operator,
PropertyGroup,
UIList)
# ======== Operators ======== #
class CUSTOM_OT_custom_metadata_fields_actions(Operator):
"""Move items up and down, add and remove"""
@ -103,6 +104,7 @@ class CUSTOM_UL_custom_metadata_fields_items(UIList):
def invoke(self, context, event):
pass
# ======== Property Collection ======== #
class CUSTOM_custom_metadata_fields_objectCollection(PropertyGroup):
# name: StringProperty() -> Instantiated by default

Wyświetl plik

@ -11,6 +11,7 @@ from bpy.types import (Operator,
PropertyGroup,
UIList)
# ======== Operators ======== #
class CUSTOM_OT_logic_actions(Operator):
"""Move items up and down, add and remove"""

Wyświetl plik

@ -1,18 +1,19 @@
bl_info = {
"name": "Blend_My_NFTs",
"author": "Torrin Leonard, This Cozy Studio Inc",
"version": (4, 5, 0),
"author": "Torrin Leonard, This Cozy Studio Inc.",
"version": (4, 5, 1),
"blender": (3, 2, 2),
"location": "View3D",
"description": "A free and opensource Blender add-on that enables you to create thousands of unique images, animations, and 3D models.",
"description": "A free and opensource Blender add-on that enables you to create thousands of unique images, "
"animations, and 3D models.",
"support": "COMMUNITY",
"doc_url": "https://github.com/torrinworx/Blend_My_NFTs",
"tracker_url": "https://github.com/torrinworx/Blend_My_NFTs/issues/new",
"category": "Development",
}
BMNFTS_VERSION = "v4.5.0"
LAST_UPDATED = "12:34AM, Aug 11th, 2022"
BMNFTS_VERSION = "v4.5.1"
LAST_UPDATED = "01:02PM, Aug 24th, 2022"
# ======== Import handling ======== #
@ -111,64 +112,64 @@ bpy.app.handlers.depsgraph_update_post.append(Refresh_UI)
# ======== Defining BMNFTs Data ======== #
@dataclass
class BMNFTData:
nftName: str
nft_name: str
save_path: str
nftsPerBatch: int
batchToGenerate: int
collectionSize: int
nfts_per_batch: int
batch_to_generate: int
collection_size: int
Blend_My_NFTs_Output: str
blend_my_nfts_output: str
batch_json_save_path: str
nftBatch_save_path: str
nft_batch_save_path: str
enableImages: bool
imageFileFormat: str
enable_images: bool
image_file_format: str
enableAnimations: bool
animationFileFormat: str
enable_animations: bool
animation_file_format: str
enableModelsBlender: bool
modelFileFormat: str
enable_models: bool
model_file_format: str
enableCustomFields: bool
enable_custom_fields: bool
cardanoMetaDataBool: bool
solanaMetaDataBool: bool
erc721MetaData: bool
cardano_metadata_bool: bool
solana_metadata_bool: bool
erc721_metadata: bool
cardano_description: str
solana_description: str
erc721_description: str
enableMaterials: bool
materialsFile: str
enable_materials: bool
materials_file: str
enableLogic: bool
enable_Logic_Json: bool
logicFile: str
enable_logic: bool
enable_logic_json: bool
logic_file: str
enableRarity: bool
enable_rarity: bool
enableAutoShutdown: bool
enable_auto_shutdown: bool
specify_timeBool: bool
specify_time_bool: bool
hours: int
minutes: int
emailNotificationBool: bool
email_notification_bool: bool
sender_from: str
email_password: str
receiver_to: str
enable_debug: bool
custom_Fields: dict = None
custom_fields: dict = None
fail_state: Any = False
failed_batch: Any = None
failed_dna: Any = None
failed_dna_index: Any = None
def __post_init__(self):
self.custom_Fields = {}
self.custom_fields = {}
def getBMNFTData():
@ -176,51 +177,51 @@ def getBMNFTData():
_Blend_My_NFTs_Output, _batch_json_save_path, _nftBatch_save_path = make_directories(_save_path)
data = BMNFTData(
nftName=bpy.context.scene.input_tool.nftName,
nft_name=bpy.context.scene.input_tool.nft_name,
save_path=_save_path,
nftsPerBatch=bpy.context.scene.input_tool.nftsPerBatch,
batchToGenerate=bpy.context.scene.input_tool.batchToGenerate,
collectionSize=bpy.context.scene.input_tool.collectionSize,
nfts_per_batch=bpy.context.scene.input_tool.nfts_per_batch,
batch_to_generate=bpy.context.scene.input_tool.batch_to_generate,
collection_size=bpy.context.scene.input_tool.collection_size,
enableRarity=bpy.context.scene.input_tool.enableRarity,
enable_rarity=bpy.context.scene.input_tool.enable_rarity,
Blend_My_NFTs_Output=_Blend_My_NFTs_Output,
blend_my_nfts_output=_Blend_My_NFTs_Output,
batch_json_save_path=_batch_json_save_path,
nftBatch_save_path=_nftBatch_save_path,
nft_batch_save_path=_nftBatch_save_path,
enableLogic=bpy.context.scene.input_tool.enableLogic,
enable_Logic_Json=bpy.context.scene.input_tool.enable_Logic_Json,
logicFile=bpy.context.scene.input_tool.logicFile,
enable_logic=bpy.context.scene.input_tool.enable_logic,
enable_logic_json=bpy.context.scene.input_tool.enable_logic_json,
logic_file=bpy.context.scene.input_tool.logic_file,
enableImages=bpy.context.scene.input_tool.imageBool,
imageFileFormat=bpy.context.scene.input_tool.imageEnum,
enable_images=bpy.context.scene.input_tool.image_bool,
image_file_format=bpy.context.scene.input_tool.image_enum,
enableAnimations=bpy.context.scene.input_tool.animationBool,
animationFileFormat=bpy.context.scene.input_tool.animationEnum,
enable_animations=bpy.context.scene.input_tool.animation_bool,
animation_file_format=bpy.context.scene.input_tool.animation_enum,
enableModelsBlender=bpy.context.scene.input_tool.modelBool,
modelFileFormat=bpy.context.scene.input_tool.modelEnum,
enable_models=bpy.context.scene.input_tool.model_bool,
model_file_format=bpy.context.scene.input_tool.model_enum,
enableCustomFields=bpy.context.scene.input_tool.enableCustomFields,
enable_custom_fields=bpy.context.scene.input_tool.enable_custom_fields,
cardanoMetaDataBool=bpy.context.scene.input_tool.cardanoMetaDataBool,
solanaMetaDataBool=bpy.context.scene.input_tool.solanaMetaDataBool,
erc721MetaData=bpy.context.scene.input_tool.erc721MetaData,
cardano_metadata_bool=bpy.context.scene.input_tool.cardano_metadata_bool,
solana_metadata_bool=bpy.context.scene.input_tool.solana_metadata_bool,
erc721_metadata=bpy.context.scene.input_tool.erc721_metadata,
cardano_description=bpy.context.scene.input_tool.cardano_description,
solana_description=bpy.context.scene.input_tool.solana_description,
erc721_description=bpy.context.scene.input_tool.erc721_description,
enableMaterials=bpy.context.scene.input_tool.enableMaterials,
materialsFile=bpy.path.abspath(bpy.context.scene.input_tool.materialsFile),
enable_materials=bpy.context.scene.input_tool.enable_materials,
materials_file=bpy.path.abspath(bpy.context.scene.input_tool.materials_file),
enableAutoShutdown=bpy.context.scene.input_tool.enableAutoShutdown,
enable_auto_shutdown=bpy.context.scene.input_tool.enable_auto_shutdown,
specify_timeBool=bpy.context.scene.input_tool.specify_timeBool,
specify_time_bool=bpy.context.scene.input_tool.specify_time_bool,
hours=bpy.context.scene.input_tool.hours,
minutes=bpy.context.scene.input_tool.minutes,
emailNotificationBool=bpy.context.scene.input_tool.emailNotificationBool,
email_notification_bool=bpy.context.scene.input_tool.email_notification_bool,
sender_from=bpy.context.scene.input_tool.sender_from,
email_password=bpy.context.scene.input_tool.email_password,
receiver_to=bpy.context.scene.input_tool.receiver_to,
@ -263,35 +264,35 @@ def runAsHeadless():
print('Using {} devices for rendering!'.format(cprefs.get_num_gpu_devices()))
def dumpSettings(settings):
output = (
f"nftName={settings.nftName}\n"
f"collectionSize={str(settings.collectionSize)}\n"
f"nftsPerBatch={str(settings.nftsPerBatch)}\n"
f"save_path={settings.save_path}\n"
f"enableRarity={(settings.enableRarity)}\n"
f"enableLogic={str(settings.enableLogic)}\n"
f"imageBool={str(settings.imageBool)}\n"
f"imageEnum={settings.imageEnum}\n"
f"animationBool={str(settings.animationBool)}\n"
f"animationEnum={settings.animationEnum}\n"
f"modelBool={str(settings.modelBool)}\n"
f"modelEnum={settings.modelEnum}\n"
f"batch_to_generate={str(settings.batchToGenerate)}\n"
f"cardanoMetaDataBool={str(settings.cardanoMetaDataBool)}\n"
f"cardano_description={settings.cardano_description}\n"
f"erc721MetaData={str(settings.erc721MetaData)}\n"
f"erc721_description={settings.erc721_description}\n"
f"solanaMetaDataBool={str(settings.solanaMetaDataBool)}\n"
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)
# def dumpSettings(settings):
# output = (
# f"nft_name={settings.nft_name}\n"
# f"collection_size={str(settings.collection_size)}\n"
# f"nfts_per_batch={str(settings.nfts_per_batch)}\n"
# f"save_path={settings.save_path}\n"
# f"enable_rarity={(settings.enable_rarity)}\n"
# f"enable_logic={str(settings.enable_logic)}\n"
# f"image_bool={str(settings.image_bool)}\n"
# f"image_enum={settings.image_enum}\n"
# f"animation_bool={str(settings.animation_bool)}\n"
# f"animation_enum={settings.animation_enum}\n"
# f"model_bool={str(settings.model_bool)}\n"
# f"model_enum={settings.model_enum}\n"
# f"batch_to_generate={str(settings.batch_to_generate)}\n"
# f"cardano_metadata_bool={str(settings.cardano_metadata_bool)}\n"
# f"cardano_description={settings.cardano_description}\n"
# f"erc721_metadata={str(settings.erc721_metadata)}\n"
# f"erc721_description={settings.erc721_description}\n"
# f"solana_metadata_bool={str(settings.solana_metadata_bool)}\n"
# f"solana_description={settings.solana_description}\n"
# f"enable_custom_fields={str(settings.enable_custom_fields)}\n"
# f"custom_fields_file={settings.custom_fields_file}\n"
# f"enable_materials={str(settings.custom_fields_file)}\n"
# f"materials_file={settings.materials_file}\n"
# )
# print(output)
args, parser = headless_util.getPythonArgs()
args, parser = headless_util.get_python_args()
settings = bpy.context.scene.input_tool
@ -304,37 +305,37 @@ def runAsHeadless():
# print(pairs)
settings.nftName = pairs[0][1]
settings.collectionSize = int(pairs[1][1])
settings.nftsPerBatch = int(pairs[2][1])
settings.nft_name = pairs[0][1]
settings.collection_size = int(pairs[1][1])
settings.nfts_per_batch = int(pairs[2][1])
settings.save_path = pairs[3][1]
settings.enableRarity = pairs[4][1] == 'True'
settings.enableLogic = pairs[5][1] == 'True'
settings.enable_rarity = pairs[4][1]=='True'
settings.enable_logic = pairs[5][1]=='True'
settings.enableLogicJson = pairs[6][1] == 'True'
settings.logicFile = pairs[7][1]
settings.imageBool = pairs[8][1] == 'True'
settings.imageEnum = pairs[9][1]
settings.animationBool = pairs[10][1] == 'True'
settings.animationEnum = pairs[11][1]
settings.modelBool = pairs[12][1] == 'True'
settings.modelEnum = pairs[13][1]
settings.batchToGenerate = int(pairs[14][1])
settings.cardanoMetaDataBool = pairs[15][1] == 'True'
settings.logic_file = pairs[7][1]
settings.image_bool = pairs[8][1]=='True'
settings.image_enum = pairs[9][1]
settings.animation_bool = pairs[10][1]=='True'
settings.animation_enum = pairs[11][1]
settings.model_bool = pairs[12][1]=='True'
settings.model_enum = pairs[13][1]
settings.batch_to_generate = int(pairs[14][1])
settings.cardano_metadata_bool = pairs[15][1]=='True'
settings.cardano_description = pairs[16][1]
settings.erc721MetaData = pairs[17][1] == 'True'
settings.erc721_metadata = pairs[17][1]=='True'
settings.erc721_description = pairs[18][1]
settings.solanaMetaDataBool = pairs[19][1] == 'True'
settings.solana_metadata_bool = pairs[19][1]=='True'
settings.solanaDescription = pairs[20][1]
settings.enableCustomFields = pairs[21][1] == 'True'
settings.customfieldsFile = pairs[22][1]
settings.enableMaterials = pairs[23][1] == 'True'
settings.materialsFile = pairs[24][1]
settings.enable_custom_fields = pairs[21][1]=='True'
settings.custom_fields_file = pairs[22][1]
settings.enable_materials = pairs[23][1]=='True'
settings.materials_file = pairs[24][1]
if args.save_path:
settings.save_path = args.save_path
if args.batch_number:
settings.batchToGenerate = args.batch_number
settings.batch_to_generate = args.batch_number
input = getBMNFTData()
@ -342,27 +343,27 @@ def runAsHeadless():
input.batch_json_save_path = args.batch_data_path
if args.operation == 'create-dna':
intermediate.send_To_Record_JSON(input)
intermediate.send_to_record(input)
elif args.operation == 'generate-nfts':
intermediate.render_and_save_NFTs(input)
intermediate.render_and_save_nfts(input)
elif args.operation == 'refactor-batches':
refactorer.reformatNFTCollection(input)
refactorer.reformat_nft_collection(input)
# ======== User input Property Group ======== #
class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
# Create NFT Data Panel:
nftName: bpy.props.StringProperty(name="NFT Name")
nft_name: bpy.props.StringProperty(name="NFT Name")
collectionSize: bpy.props.IntProperty(
collection_size: bpy.props.IntProperty(
name="NFT Collection Size",
default=1,
min=1
) # max=(combinations - offset)
nftsPerBatch: bpy.props.IntProperty(
nfts_per_batch: bpy.props.IntProperty(
name="NFTs Per Batch",
default=1,
min=1
@ -376,17 +377,17 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
subtype="DIR_PATH"
)
enableRarity: bpy.props.BoolProperty(
enable_rarity: bpy.props.BoolProperty(
name="Enable Rarity"
)
enableLogic: bpy.props.BoolProperty(
enable_logic: bpy.props.BoolProperty(
name="Enable Logic"
)
enable_Logic_Json: bpy.props.BoolProperty(
enable_logic_json: bpy.props.BoolProperty(
name="Use Logic.json instead"
)
logicFile: bpy.props.StringProperty(
logic_file: bpy.props.StringProperty(
name="Logic File Path",
description="Path where Logic.json is located.",
default="",
@ -394,10 +395,10 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
subtype="FILE_PATH"
)
enableMaterials: bpy.props.BoolProperty(
enable_materials: bpy.props.BoolProperty(
name="Enable Materials"
)
materialsFile: bpy.props.StringProperty(
materials_file: bpy.props.StringProperty(
name="Materials File",
description="Path where Materials.json is located.",
default="",
@ -406,10 +407,10 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
)
# Generate NFTs Panel:
imageBool: bpy.props.BoolProperty(
image_bool: bpy.props.BoolProperty(
name="Image"
)
imageEnum: bpy.props.EnumProperty(
image_enum: bpy.props.EnumProperty(
name="Image File Format",
description="Select Image file format",
items=[
@ -418,10 +419,10 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
]
)
animationBool: bpy.props.BoolProperty(
animation_bool: bpy.props.BoolProperty(
name="Animation"
)
animationEnum: bpy.props.EnumProperty(
animation_enum: bpy.props.EnumProperty(
name="Animation File Format",
description="Select Animation file format",
items=[
@ -434,10 +435,10 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
]
)
modelBool: bpy.props.BoolProperty(
model_bool: bpy.props.BoolProperty(
name="3D Model"
)
modelEnum: bpy.props.EnumProperty(
model_enum: bpy.props.EnumProperty(
name="3D Model File Format",
description="Select 3D Model file format",
items=[
@ -454,38 +455,38 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
]
)
batchToGenerate: bpy.props.IntProperty(
batch_to_generate: bpy.props.IntProperty(
name="Batch To Generate",
default=1,
min=1
)
# Refactor Batches & Create Metadata Panel:
cardanoMetaDataBool: bpy.props.BoolProperty(
cardano_metadata_bool: bpy.props.BoolProperty(
name="Cardano Cip"
)
cardano_description: bpy.props.StringProperty(
name="Cardano description"
)
solanaMetaDataBool: bpy.props.BoolProperty(
solana_metadata_bool: bpy.props.BoolProperty(
name="Solana Metaplex"
)
solana_description: bpy.props.StringProperty(
name="Solana description"
)
erc721MetaData: bpy.props.BoolProperty(
erc721_metadata: bpy.props.BoolProperty(
name="ERC721"
)
erc721_description: bpy.props.StringProperty(
name="ERC721 description"
)
enableCustomFields: bpy.props.BoolProperty(
enable_custom_fields: bpy.props.BoolProperty(
name="Enable Custom Metadata Fields"
)
customfieldsFile: bpy.props.StringProperty(
custom_fields_file: bpy.props.StringProperty(
name="Custom Fields File",
description="Path where Custom_Fields.json is located.",
default="",
@ -496,17 +497,17 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
# TODO: Add 'Other' panel inputs to Headless functionality.
# Other Panel:
enableAutoSave: bpy.props.BoolProperty(
enable_auto_save: bpy.props.BoolProperty(
name="Auto Save Before Generation",
description="Automatically saves your Blender file when 'Generate NFTs & Create Metadata' button is clicked"
)
enableAutoShutdown: bpy.props.BoolProperty(
enable_auto_shutdown: bpy.props.BoolProperty(
name="Auto Shutdown",
description="Automatically shuts down your computer after a Batch is finished Generating"
)
specify_timeBool: bpy.props.BoolProperty(
specify_time_bool: bpy.props.BoolProperty(
name="Shutdown in a Given Amount of Time",
description="Wait a given amount of time after a Batch is generated before Automatic Shutdown"
)
@ -517,7 +518,7 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
default=0, min=0
)
emailNotificationBool: bpy.props.BoolProperty(
email_notification_bool: bpy.props.BoolProperty(
name="Email Notifications",
description="Receive Email Notifications from Blender once a batch is finished generating"
)
@ -541,17 +542,18 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup):
)
# API Panel properties:
apiKey: bpy.props.StringProperty(
api_key: bpy.props.StringProperty(
name="API Key",
subtype='PASSWORD'
) # Test code for future features
# ======== Main Operators ======== #
class createData(bpy.types.Operator):
class Createdata(bpy.types.Operator):
bl_idname = 'create.data'
bl_label = 'Create Data'
bl_description = 'Creates NFT Data. Run after any changes were made to scene. All previous data will be overwritten and cannot be recovered.'
bl_description = 'Creates NFT Data. Run after any changes were made to scene. All previous data will be ' \
'overwritten and cannot be recovered.'
bl_options = {"REGISTER", "UNDO"}
reverse_order: BoolProperty(
@ -562,12 +564,12 @@ class createData(bpy.types.Operator):
# Handling Custom Fields UIList input:
input = getBMNFTData()
if input.enableLogic:
if input.enable_Logic_Json and not input.logicFile:
if input.enable_logic:
if input.enable_logic_json and not input.logic_file:
self.report({'ERROR'},
f"No Logic.json file path set. Please set the file path to your Logic.json file.")
intermediate.send_To_Record_JSON(input)
intermediate.send_to_record(input)
self.report({'INFO'}, f"NFT Data created!")
return {"FINISHED"}
@ -576,7 +578,7 @@ class createData(bpy.types.Operator):
return context.window_manager.invoke_confirm(self, event)
class exportNFTs(bpy.types.Operator):
class ExportNFTs(bpy.types.Operator):
bl_idname = 'exporter.nfts'
bl_label = 'Export NFTs'
bl_description = 'Generate and export a given batch of NFTs.'
@ -590,14 +592,14 @@ class exportNFTs(bpy.types.Operator):
input = getBMNFTData()
# Handling Custom Fields UIList input:
intermediate.render_and_save_NFTs(input)
intermediate.render_and_save_nfts(input)
self.report({'INFO'}, f"All NFTs generated for batch {input.batchToGenerate}!")
self.report({'INFO'}, f"All NFTs generated for batch {input.batch_to_generate}!")
return {"FINISHED"}
class resume_failed_batch(bpy.types.Operator):
class ResumeFailedBatch(bpy.types.Operator):
bl_idname = 'exporter.resume_nfts'
bl_label = 'Resume Failed Batch'
bl_description = 'Failed Batch detected. Generate NFTs where the previous batch failed?'
@ -607,7 +609,7 @@ class resume_failed_batch(bpy.types.Operator):
_save_path = bpy.path.abspath(bpy.context.scene.input_tool.save_path)
_Blend_My_NFTs_Output, _batch_json_save_path, _nftBatch_save_path = make_directories(_save_path)
_batchToGenerate = bpy.context.scene.input_tool.batchToGenerate
_batchToGenerate = bpy.context.scene.input_tool.batch_to_generate
file_name = os.path.join(_batch_json_save_path, "Batch{}.json".format(_batchToGenerate))
batchData = json.load(open(file_name))
@ -617,51 +619,51 @@ class resume_failed_batch(bpy.types.Operator):
render_settings = batchData["Generation Save"][-1]["Render_Settings"]
input = BMNFTData(
nftName=render_settings["nftName"],
nft_name=render_settings["nft_name"],
save_path=_save_path,
nftsPerBatch=render_settings["nftsPerBatch"],
batchToGenerate=render_settings["batch_to_generate"],
collectionSize=render_settings["collectionSize"],
nfts_per_batch=render_settings["nfts_per_batch"],
batch_to_generate=render_settings["batch_to_generate"],
collection_size=render_settings["collection_size"],
Blend_My_NFTs_Output=_Blend_My_NFTs_Output,
blend_my_nfts_output=_Blend_My_NFTs_Output,
batch_json_save_path=_batch_json_save_path,
nftBatch_save_path=render_settings["nftBatch_save_path"],
nft_batch_save_path=render_settings["nft_batch_save_path"],
enableImages=render_settings["enableImages"],
imageFileFormat=render_settings["imageFileFormat"],
enable_images=render_settings["enable_images"],
image_file_format=render_settings["image_file_format"],
enableAnimations=render_settings["enableAnimations"],
animationFileFormat=render_settings["animationFileFormat"],
enable_animations=render_settings["enable_animations"],
animation_file_format=render_settings["animation_file_format"],
enableModelsBlender=render_settings["enableModelsBlender"],
modelFileFormat=render_settings["modelFileFormat"],
enable_models=render_settings["enable_models"],
model_file_format=render_settings["model_file_format"],
enableCustomFields=render_settings["enableCustomFields"],
enable_custom_fields=render_settings["enable_custom_fields"],
cardanoMetaDataBool=render_settings["cardanoMetaDataBool"],
solanaMetaDataBool=render_settings["solanaMetaDataBool"],
erc721MetaData=render_settings["erc721MetaData"],
cardano_metadata_bool=render_settings["cardano_metadata_bool"],
solana_metadata_bool=render_settings["solana_metadata_bool"],
erc721_metadata=render_settings["erc721_metadata"],
cardano_description=render_settings["cardano_description"],
solana_description=render_settings["solana_description"],
erc721_description=render_settings["erc721_description"],
enableMaterials=render_settings["enableMaterials"],
materialsFile=render_settings["materialsFile"],
enable_materials=render_settings["enable_materials"],
materials_file=render_settings["materials_file"],
enableLogic=render_settings["enableLogic"],
enable_Logic_Json=render_settings["enable_Logic_Json"],
logicFile=render_settings["logicFile"],
enable_logic=render_settings["enable_logic"],
enable_logic_json=render_settings["enable_logic_json"],
logic_file=render_settings["logic_file"],
enableRarity=render_settings["enableRarity"],
enable_rarity=render_settings["enable_rarity"],
enableAutoShutdown=render_settings["enableAutoShutdown"],
enable_auto_shutdown=render_settings["enable_auto_shutdown"],
specify_timeBool=render_settings["specify_timeBool"],
specify_time_bool=render_settings["specify_time_bool"],
hours=render_settings["hours"],
minutes=render_settings["minutes"],
emailNotificationBool=render_settings["emailNotificationBool"],
email_notification_bool=render_settings["email_notification_bool"],
sender_from=render_settings["sender_from"],
email_password=render_settings["email_password"],
receiver_to=render_settings["receiver_to"],
@ -672,7 +674,7 @@ class resume_failed_batch(bpy.types.Operator):
failed_dna=_failed_dna,
failed_dna_index=_failed_dna_index,
custom_Fields=render_settings["custom_Fields"],
custom_fields=render_settings["custom_fields"],
)
exporter.render_and_save_nfts(input)
@ -682,7 +684,7 @@ class resume_failed_batch(bpy.types.Operator):
return {"FINISHED"}
class refactor_Batches(bpy.types.Operator):
class RefactorBatches(bpy.types.Operator):
"""Refactor your collection? This action cannot be undone."""
bl_idname = 'refactor.batches'
bl_label = 'Refactor your Batches?'
@ -695,14 +697,14 @@ class refactor_Batches(bpy.types.Operator):
def execute(self, context):
# Passing info to main functions for refactoring:
refactorer.reformatNFTCollection(getBMNFTData())
refactorer.reformat_nft_collection(getBMNFTData())
return {"FINISHED"}
def invoke(self, context, event):
return context.window_manager.invoke_confirm(self, event)
class export_settings(bpy.types.Operator):
class ExportSettings(bpy.types.Operator):
"""Export your settings into a configuration file."""
bl_idname = 'export.settings'
bl_label = 'Export Settings'
@ -721,51 +723,51 @@ class export_settings(bpy.types.Operator):
"#when running Blend_My_NFTs in a headless environment.\n"
"\n"
"#The name of your nft project\n"
f"nftName={settings.nftName}\n"
f"nft_name={settings.nft_name}\n"
"\n"
"#NFT Collection Size\n"
f"collectionSize={settings.collectionSize}\n"
f"collection_size={settings.collection_size}\n"
"\n"
"#The number of NFTs to generate per batch\n"
f"nftsPerBatch={str(settings.nftsPerBatch)}\n"
f"nfts_per_batch={str(settings.nfts_per_batch)}\n"
"\n"
"#Save path for your NFT files\n"
f"save_path={settings.save_path}\n"
"\n"
"#Enable Rarity\n"
f"enableRarity={(settings.enableRarity)}\n"
f"enable_rarity={settings.enable_rarity}\n"
"\n"
"#Enable Logic\n"
f"enableLogic={str(settings.enableLogic)}\n"
f"enableLogicJson={str(settings.enable_Logic_Json)}\n"
f"logicFilePath={settings.logicFile}\n"
f"enable_logic={str(settings.enable_logic)}\n"
f"enableLogicJson={str(settings.enable_logic_json)}\n"
f"logicFilePath={settings.logic_file}\n"
"\n"
"#NFT Media output type(s):\n"
f"imageBool={str(settings.imageBool)}\n"
f"imageEnum={settings.imageEnum}\n"
f"animationBool={str(settings.animationBool)}\n"
f"animationEnum={settings.animationEnum}\n"
f"modelBool={str(settings.modelBool)}\n"
f"modelEnum={settings.modelEnum}\n"
f"image_bool={str(settings.image_bool)}\n"
f"image_enum={settings.image_enum}\n"
f"animation_bool={str(settings.animation_bool)}\n"
f"animation_enum={settings.animation_enum}\n"
f"model_bool={str(settings.model_bool)}\n"
f"model_enum={settings.model_enum}\n"
"\n"
"#Batch to generate\n"
f"batch_to_generate={str(settings.batchToGenerate)}\n"
f"batch_to_generate={str(settings.batch_to_generate)}\n"
"\n"
"#Metadata Format\n"
f"cardanoMetaDataBool={str(settings.cardanoMetaDataBool)}\n"
f"cardano_metadata_bool={str(settings.cardano_metadata_bool)}\n"
f"cardano_description={settings.cardano_description}\n"
f"erc721MetaData={str(settings.erc721MetaData)}\n"
f"erc721_metadata={str(settings.erc721_metadata)}\n"
f"erc721_description={settings.erc721_description}\n"
f"solanaMetaDataBool={str(settings.solanaMetaDataBool)}\n"
f"solana_metadata_bool={str(settings.solana_metadata_bool)}\n"
f"solana_description={settings.solana_description}\n"
"\n"
"#Enable Custom Fields\n"
f"enableCustomFields={str(settings.enableCustomFields)}\n"
f"customfieldsFile={settings.customfieldsFile}\n"
f"enable_custom_fields={str(settings.enable_custom_fields)}\n"
f"custom_fields_file={settings.custom_fields_file}\n"
"\n"
"#Enable Materials\n"
f"enableMaterials={str(settings.enableMaterials)}\n"
f"materialsFile={settings.materialsFile}\n"
f"enable_materials={str(settings.enable_materials)}\n"
f"materials_file={settings.materials_file}\n"
)
print(output, file=config)
@ -789,29 +791,29 @@ class BMNFTS_PT_CreateData(bpy.types.Panel):
input_tool_scene = scene.input_tool
row = layout.row()
row.prop(input_tool_scene, "nftName")
row.prop(input_tool_scene, "nft_name")
row = layout.row()
layout.label(text=f"Maximum Number Of NFTs: {combinations}")
layout.label(text=f"Recommended limit: {recommended_limit}")
row = layout.row()
row.prop(input_tool_scene, "collectionSize")
row.prop(input_tool_scene, "collection_size")
row = layout.row()
row.prop(input_tool_scene, "nftsPerBatch")
row.prop(input_tool_scene, "nfts_per_batch")
row = layout.row()
row.prop(input_tool_scene, "save_path")
row = layout.row()
row.prop(input_tool_scene, "enableRarity")
row.prop(input_tool_scene, "enable_rarity")
row = layout.row()
row.prop(input_tool_scene, "enableLogic")
row.prop(input_tool_scene, "enable_logic")
# Logic_UIList implementation:
if bpy.context.scene.input_tool.enableLogic:
if bpy.context.scene.input_tool.enable_logic:
layout = self.layout
scn = bpy.context.scene
@ -835,18 +837,18 @@ class BMNFTS_PT_CreateData(bpy.types.Panel):
row.label(text=f"*Field Names must be unique.")
row = layout.row()
row.prop(input_tool_scene, "enable_Logic_Json")
row.prop(input_tool_scene, "enable_logic_json")
if bpy.context.scene.input_tool.enable_Logic_Json:
if bpy.context.scene.input_tool.enable_logic_json:
row = layout.row()
row.prop(input_tool_scene, "logicFile")
row.prop(input_tool_scene, "logic_file")
row = layout.row()
row.prop(input_tool_scene, "enableMaterials")
row.prop(input_tool_scene, "enable_materials")
if bpy.context.scene.input_tool.enableMaterials:
if bpy.context.scene.input_tool.enable_materials:
row = layout.row()
row.prop(input_tool_scene, "materialsFile")
row.prop(input_tool_scene, "materials_file")
row = layout.row()
self.layout.operator("create.data", icon='DISCLOSURE_TRI_RIGHT', text="Create Data")
@ -870,26 +872,26 @@ class BMNFTS_PT_GenerateNFTs(bpy.types.Panel):
layout.label(text="NFT Media files:")
row = layout.row()
row.prop(input_tool_scene, "imageBool")
if bpy.context.scene.input_tool.imageBool:
row.prop(input_tool_scene, "imageEnum")
row.prop(input_tool_scene, "image_bool")
if bpy.context.scene.input_tool.image_bool:
row.prop(input_tool_scene, "image_enum")
row = layout.row()
row.prop(input_tool_scene, "animationBool")
if bpy.context.scene.input_tool.animationBool:
row.prop(input_tool_scene, "animationEnum")
row.prop(input_tool_scene, "animation_bool")
if bpy.context.scene.input_tool.animation_bool:
row.prop(input_tool_scene, "animation_enum")
row = layout.row()
row.prop(input_tool_scene, "modelBool")
if bpy.context.scene.input_tool.modelBool:
row.prop(input_tool_scene, "modelEnum")
row.prop(input_tool_scene, "model_bool")
if bpy.context.scene.input_tool.model_bool:
row.prop(input_tool_scene, "model_enum")
row = layout.row()
layout.label(text="Meta Data format:")
row = layout.row()
row.prop(input_tool_scene, "cardanoMetaDataBool")
if bpy.context.scene.input_tool.cardanoMetaDataBool:
row.prop(input_tool_scene, "cardano_metadata_bool")
if bpy.context.scene.input_tool.cardano_metadata_bool:
row = layout.row()
row.prop(input_tool_scene, "cardano_description")
@ -898,8 +900,8 @@ class BMNFTS_PT_GenerateNFTs(bpy.types.Panel):
icon='URL').url = "https://cips.cardano.org/cips/cip25/"
row = layout.row()
row.prop(input_tool_scene, "solanaMetaDataBool")
if bpy.context.scene.input_tool.solanaMetaDataBool:
row.prop(input_tool_scene, "solana_metadata_bool")
if bpy.context.scene.input_tool.solana_metadata_bool:
row = layout.row()
row.prop(input_tool_scene, "solana_description")
@ -908,8 +910,8 @@ class BMNFTS_PT_GenerateNFTs(bpy.types.Panel):
icon='URL').url = "https://docs.metaplex.com/token-metadata/specification"
row = layout.row()
row.prop(input_tool_scene, "erc721MetaData")
if bpy.context.scene.input_tool.erc721MetaData:
row.prop(input_tool_scene, "erc721_metadata")
if bpy.context.scene.input_tool.erc721_metadata:
row = layout.row()
row.prop(input_tool_scene, "erc721_description")
@ -918,10 +920,10 @@ class BMNFTS_PT_GenerateNFTs(bpy.types.Panel):
icon='URL').url = "https://docs.opensea.io/docs/metadata-standards"
row = layout.row()
row.prop(input_tool_scene, "enableCustomFields")
row.prop(input_tool_scene, "enable_custom_fields")
# Custom Metadata Fields UIList:
if bpy.context.scene.input_tool.enableCustomFields:
if bpy.context.scene.input_tool.enable_custom_fields:
layout = self.layout
scn = bpy.context.scene
@ -1010,16 +1012,16 @@ class BMNFTS_PT_Other(bpy.types.Panel):
"""
row = layout.row()
row.prop(input_tool_scene, "enableAutoSave")
row.prop(input_tool_scene, "enable_auto_save")
# Auto Shutdown:
row = layout.row()
row.prop(input_tool_scene, "enableAutoShutdown")
row.prop(input_tool_scene, "enable_auto_shutdown")
row.label(text="*Must Run Blender as Admin")
if bpy.context.scene.input_tool.enableAutoShutdown:
if bpy.context.scene.input_tool.enable_auto_shutdown:
row = layout.row()
row.prop(input_tool_scene, "specify_timeBool")
row.prop(input_tool_scene, "specify_time_bool")
time_row1 = layout.row()
time_row1.label(text=f"Hours")
@ -1029,7 +1031,7 @@ class BMNFTS_PT_Other(bpy.types.Panel):
time_row2.label(text=f"Minutes")
time_row2.prop(input_tool_scene, "minutes", text="")
if not bpy.context.scene.input_tool.specify_timeBool:
if not bpy.context.scene.input_tool.specify_time_bool:
time_row1.enabled = False
time_row2.enabled = False
else:
@ -1038,10 +1040,10 @@ class BMNFTS_PT_Other(bpy.types.Panel):
layout.separator()
row = layout.row()
row.prop(input_tool_scene, "emailNotificationBool")
row.prop(input_tool_scene, "email_notification_bool")
row.label(text="*Windows 10+ only")
if bpy.context.scene.input_tool.emailNotificationBool:
if bpy.context.scene.input_tool.email_notification_bool:
row = layout.row()
row.prop(input_tool_scene, "sender_from")
row = layout.row()
@ -1089,22 +1091,22 @@ class BMNFTS_PT_Other(bpy.types.Panel):
# ======== Blender add-on register/unregister handling ======== #
classes = (
# Property Group Classes:
BMNFTS_PGT_Input_Properties,
# Property Group Classes:
BMNFTS_PGT_Input_Properties,
# Operator Classes:
createData,
exportNFTs,
resume_failed_batch,
refactor_Batches,
export_settings,
# Operator Classes:
Createdata,
ExportNFTs,
ResumeFailedBatch,
RefactorBatches,
ExportSettings,
# Panel Classes:
BMNFTS_PT_CreateData,
BMNFTS_PT_GenerateNFTs,
BMNFTS_PT_Refactor,
BMNFTS_PT_Other,
) + custom_metadata_ui_list.classes_Custom_Metadata_UIList + logic_ui_list.classes_Logic_UIList
# Panel Classes:
BMNFTS_PT_CreateData,
BMNFTS_PT_GenerateNFTs,
BMNFTS_PT_Refactor,
BMNFTS_PT_Other,
) + custom_metadata_ui_list.classes_Custom_Metadata_UIList + logic_ui_list.classes_Logic_UIList
def register():

Wyświetl plik

@ -110,7 +110,7 @@ def generate_nft_dna(
# print(f"Rarity DNA: {single_dna}")
if enable_logic:
single_dna = logic.logicafyDNAsingle(hierarchy, single_dna, logic_file, enable_rarity, enable_materials)
single_dna = logic.logicafy_dna_single(hierarchy, single_dna, logic_file, enable_rarity, enable_materials)
# print(f"Logic DNA: {single_dna}")
if enable_materials:
@ -170,7 +170,7 @@ def make_batches(
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 collection_size and nfts_per_batch.
These files are then saved as Batch#.json files to batch_json_save_path
"""

Wyświetl plik

@ -12,7 +12,7 @@ import datetime
import platform
from .helpers import TextColors, Loader
from .metadata_templates import createCardanoMetadata, createSolanaMetaData, createErc721MetaData
from .metadata_templates import create_cardano_metadata, createSolanaMetaData, create_erc721_meta_data
# Save info
@ -28,7 +28,7 @@ def save_generation_state(input):
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(input.batch_json_save_path, "Batch{}.json".format(input.batchToGenerate))
file_name = os.path.join(input.batch_json_save_path, "Batch{}.json".format(input.batch_to_generate))
batch = json.load(open(file_name))
current_time = datetime.datetime.now().strftime("%H:%M:%S")
@ -46,56 +46,56 @@ def save_generation_state(input):
"DNA Generated": None,
"Generation Start Date and Time": [current_time, current_date, local_timezone],
"Render_Settings": {
"nftName": input.nftName,
"nft_name": input.nft_name,
"save_path": input.save_path,
"nftsPerBatch": input.nftsPerBatch,
"batch_to_generate": input.batchToGenerate,
"collectionSize": input.collectionSize,
"nfts_per_batch": input.nfts_per_batch,
"batch_to_generate": input.batch_to_generate,
"collection_size": input.collection_size,
"Blend_My_NFTs_Output": input.Blend_My_NFTs_Output,
"blend_my_nfts_output": input.blend_my_nfts_output,
"batch_json_save_path": input.batch_json_save_path,
"nftBatch_save_path": input.nftBatch_save_path,
"nft_batch_save_path": input.nft_batch_save_path,
"enableImages": input.enableImages,
"imageFileFormat": input.imageFileFormat,
"enable_images": input.enable_images,
"image_file_format": input.image_file_format,
"enableAnimations": input.enableAnimations,
"animationFileFormat": input.animationFileFormat,
"enable_animations": input.enable_animations,
"animation_file_format": input.animation_file_format,
"enableModelsBlender": input.enableModelsBlender,
"modelFileFormat": input.modelFileFormat,
"enable_models": input.enable_models,
"model_file_format": input.model_file_format,
"enableCustomFields": input.enableCustomFields,
"enable_custom_fields": input.enable_custom_fields,
"cardanoMetaDataBool": input.cardanoMetaDataBool,
"solanaMetaDataBool": input.solanaMetaDataBool,
"erc721MetaData": input.erc721MetaData,
"cardano_metadata_bool": input.cardano_metadata_bool,
"solana_metadata_bool": input.solana_metadata_bool,
"erc721_metadata": input.erc721_metadata,
"cardano_description": input.cardano_description,
"solana_description": input.solana_description,
"erc721_description": input.erc721_description,
"enableMaterials": input.enableMaterials,
"materialsFile": input.materialsFile,
"enable_materials": input.enable_materials,
"materials_file": input.materials_file,
"enableLogic": input.enableLogic,
"enable_Logic_Json": input.enable_Logic_Json,
"logicFile": input.logicFile,
"enable_logic": input.enable_logic,
"enable_logic_json": input.enable_logic_json,
"logic_file": input.logic_file,
"enableRarity": input.enableRarity,
"enable_rarity": input.enable_rarity,
"enableAutoShutdown": input.enableAutoShutdown,
"enable_auto_shutdown": input.enable_auto_shutdown,
"specify_timeBool": input.specify_timeBool,
"specify_time_bool": input.specify_time_bool,
"hours": input.hours,
"minutes": input.minutes,
"emailNotificationBool": input.emailNotificationBool,
"email_notification_bool": input.email_notification_bool,
"sender_from": input.sender_from,
"email_password": input.email_password,
"receiver_to": input.receiver_to,
"custom_Fields": input.custom_Fields,
"custom_fields": input.custom_fields,
},
})
@ -148,23 +148,23 @@ def render_and_save_nfts(input):
# If user is generating the normal way:
else:
print(f"\nGenerating Batch #{input.batchToGenerate}\n")
nfts_in_batch, hierarchy, batch_dna_list = get_batch_data(input.batchToGenerate, input.batch_json_save_path)
print(f"\nGenerating Batch #{input.batch_to_generate}\n")
nfts_in_batch, hierarchy, batch_dna_list = get_batch_data(input.batch_to_generate, input.batch_json_save_path)
save_generation_state(input)
x = 1
if input.enableMaterials:
materials_file = json.load(open(input.materialsFile))
if input.enable_materials:
materials_file = json.load(open(input.materials_file))
for a in batch_dna_list:
full_single_dna = list(a.keys())[0]
order_num = a[full_single_dna]['order_num']
# Material handling:
if input.enableMaterials:
if input.enable_materials:
single_dna, material_dna = full_single_dna.split(':')
if not input.enableMaterials:
if not input.enable_materials:
single_dna = full_single_dna
def match_dna_to_variant(single_dna):
@ -221,7 +221,7 @@ def render_and_save_nfts(input):
metadata_material_dict = {}
if input.enableMaterials:
if input.enable_materials:
material_dna_dictionary = match_material_dna_to_material(single_dna, material_dna, materials_file)
for var_mat in list(material_dna_dictionary.keys()):
@ -263,7 +263,7 @@ def render_and_save_nfts(input):
)
dna_dictionary = match_dna_to_variant(single_dna)
name = input.nftName + "_" + str(order_num)
name = input.nft_name + "_" + str(order_num)
# Change Text Object in Scene to match DNA string:
# Variables that can be used: full_single_dna, name, order_num
@ -273,7 +273,7 @@ def render_and_save_nfts(input):
print(f"\n{TextColors.OK}======== Generating NFT {x}/{nfts_in_batch}: {name} ========{TextColors.RESET}")
print(f"\nVariants selected:")
print(f"{dna_dictionary}")
if input.enableMaterials:
if input.enable_materials:
print(f"\nMaterials selected:")
print(f"{material_dna_dictionary}")
@ -288,7 +288,7 @@ def render_and_save_nfts(input):
time_start_2 = time.time()
# Main paths for batch sub-folders:
batch_folder = os.path.join(input.nftBatch_save_path, "Batch" + str(input.batchToGenerate))
batch_folder = os.path.join(input.nft_batch_save_path, "Batch" + str(input.batch_to_generate))
image_folder = os.path.join(batch_folder, "Images")
animation_folder = os.path.join(batch_folder, "Animations")
@ -313,7 +313,7 @@ def render_and_save_nfts(input):
os.remove(file_path)
# Generation/Rendering:
if input.enableImages:
if input.enable_images:
print(f"{TextColors.OK}-------- Image --------{TextColors.RESET}")
@ -326,7 +326,7 @@ def render_and_save_nfts(input):
os.makedirs(image_folder)
bpy.context.scene.render.filepath = image_path
bpy.context.scene.render.image_settings.file_format = input.imageFileFormat
bpy.context.scene.render.image_settings.file_format = input.image_file_format
bpy.ops.render.render(write_still=True)
# Loading Animation:
@ -341,7 +341,7 @@ def render_and_save_nfts(input):
f"\n{TextColors.RESET}"
)
if input.enableAnimations:
if input.enable_animations:
print(f"{TextColors.OK}-------- Animation --------{TextColors.RESET}")
animation_render_time_start = time.time()
@ -352,7 +352,7 @@ def render_and_save_nfts(input):
if not os.path.exists(animation_folder):
os.makedirs(animation_folder)
if input.animationFileFormat == "MP4":
if input.animation_file_format =="MP4":
bpy.context.scene.render.filepath = animation_path
bpy.context.scene.render.image_settings.file_format = "FFMPEG"
@ -360,25 +360,25 @@ def render_and_save_nfts(input):
bpy.context.scene.render.ffmpeg.codec = 'H264'
bpy.ops.render.render(animation=True)
elif input.animationFileFormat == 'PNG':
elif input.animation_file_format =='PNG':
if not os.path.exists(animation_path):
os.makedirs(animation_path)
bpy.context.scene.render.filepath = os.path.join(animation_path, name)
bpy.context.scene.render.image_settings.file_format = input.animationFileFormat
bpy.context.scene.render.image_settings.file_format = input.animation_file_format
bpy.ops.render.render(animation=True)
elif input.animationFileFormat == 'TIFF':
elif input.animation_file_format =='TIFF':
if not os.path.exists(animation_path):
os.makedirs(animation_path)
bpy.context.scene.render.filepath = os.path.join(animation_path, name)
bpy.context.scene.render.image_settings.file_format = input.animationFileFormat
bpy.context.scene.render.image_settings.file_format = input.animation_file_format
bpy.ops.render.render(animation=True)
else:
bpy.context.scene.render.filepath = animation_path
bpy.context.scene.render.image_settings.file_format = input.animationFileFormat
bpy.context.scene.render.image_settings.file_format = input.animation_file_format
bpy.ops.render.render(animation=True)
# Loading Animation:
@ -393,7 +393,7 @@ def render_and_save_nfts(input):
f"\n{TextColors.RESET}"
)
if input.enableModelsBlender:
if input.enable_models:
print(f"{TextColors.OK}-------- 3D Model --------{TextColors.RESET}")
model_generation_time_start = time.time()
@ -419,7 +419,7 @@ def render_and_save_nfts(input):
# if obj.name in remove_objects:
# obj.select_set(False)
if input.modelFileFormat == 'GLB':
if input.model_file_format =='GLB':
check_failed_exists(f"{model_path}.glb")
bpy.ops.export_scene.gltf(
filepath=f"{model_path}.glb",
@ -428,7 +428,7 @@ def render_and_save_nfts(input):
export_keep_originals=True,
use_selection=True
)
if input.modelFileFormat == 'GLTF_SEPARATE':
if input.model_file_format =='GLTF_SEPARATE':
check_failed_exists(f"{model_path}.gltf")
check_failed_exists(f"{model_path}.bin")
bpy.ops.export_scene.gltf(
@ -438,7 +438,7 @@ def render_and_save_nfts(input):
export_keep_originals=True,
use_selection=True
)
if input.modelFileFormat == 'GLTF_EMBEDDED':
if input.model_file_format =='GLTF_EMBEDDED':
check_failed_exists(f"{model_path}.gltf")
bpy.ops.export_scene.gltf(
filepath=f"{model_path}.gltf",
@ -447,35 +447,35 @@ def render_and_save_nfts(input):
export_keep_originals=True,
use_selection=True
)
elif input.modelFileFormat == 'FBX':
elif input.model_file_format =='FBX':
check_failed_exists(f"{model_path}.fbx")
bpy.ops.export_scene.fbx(
filepath=f"{model_path}.fbx",
check_existing=True,
use_selection=True
)
elif input.modelFileFormat == 'OBJ':
elif input.model_file_format =='OBJ':
check_failed_exists(f"{model_path}.obj")
bpy.ops.export_scene.obj(
filepath=f"{model_path}.obj",
check_existing=True,
use_selection=True,
)
elif input.modelFileFormat == 'X3D':
elif input.model_file_format =='X3D':
check_failed_exists(f"{model_path}.x3d")
bpy.ops.export_scene.x3d(
filepath=f"{model_path}.x3d",
check_existing=True,
use_selection=True
)
elif input.modelFileFormat == 'STL':
elif input.model_file_format =='STL':
check_failed_exists(f"{model_path}.stl")
bpy.ops.export_mesh.stl(
filepath=f"{model_path}.stl",
check_existing=True,
use_selection=True
)
elif input.modelFileFormat == 'VOX':
elif input.model_file_format =='VOX':
check_failed_exists(f"{model_path}.vox")
bpy.ops.export_vox.some_data(filepath=f"{model_path}.vox")
@ -492,22 +492,22 @@ def render_and_save_nfts(input):
)
# Generating Metadata:
if input.cardanoMetaDataBool:
if input.cardano_metadata_bool:
if not os.path.exists(cardano_metadata_path):
os.makedirs(cardano_metadata_path)
createCardanoMetadata(
create_cardano_metadata(
name,
order_num,
full_single_dna,
dna_dictionary,
metadata_material_dict,
input.custom_Fields,
input.enableCustomFields,
input.custom_fields,
input.enable_custom_fields,
input.cardano_description,
cardano_metadata_path
)
if input.solanaMetaDataBool:
if input.solana_metadata_bool:
if not os.path.exists(solana_metadata_path):
os.makedirs(solana_metadata_path)
createSolanaMetaData(
@ -516,23 +516,23 @@ def render_and_save_nfts(input):
full_single_dna,
dna_dictionary,
metadata_material_dict,
input.custom_Fields,
input.enableCustomFields,
input.custom_fields,
input.enable_custom_fields,
input.solana_description,
solana_metadata_path
)
if input.erc721MetaData:
if input.erc721_metadata:
if not os.path.exists(erc721_metadata_path):
os.makedirs(erc721_metadata_path)
createErc721MetaData(
create_erc721_meta_data(
name,
order_num,
full_single_dna,
dna_dictionary,
metadata_material_dict,
input.custom_Fields,
input.enableCustomFields,
input.custom_fields,
input.enable_custom_fields,
input.erc721_description,
erc721_metadata_path
)
@ -558,7 +558,7 @@ def render_and_save_nfts(input):
print(f"Completed {name} render in {time.time() - time_start_2}s")
save_completed(full_single_dna, a, x, input.batch_json_save_path, input.batchToGenerate)
save_completed(full_single_dna, a, x, input.batch_json_save_path, input.batch_to_generate)
x += 1
@ -569,17 +569,17 @@ def render_and_save_nfts(input):
batch_complete_time = time.time() - time_start_1
print(f"\nAll NFTs successfully generated and sent to {input.nftBatch_save_path}"
f"\nCompleted all renders in Batch{input.batchToGenerate}.json in {batch_complete_time}s\n")
print(f"\nAll NFTs successfully generated and sent to {input.nft_batch_save_path}"
f"\nCompleted all renders in Batch{input.batch_to_generate}.json in {batch_complete_time}s\n")
batch_info = {"Batch Render Time": batch_complete_time, "Number of NFTs generated in Batch": x - 1,
"Average time per generation": batch_complete_time / x - 1}
batch_info_folder = os.path.join(input.nftBatch_save_path, "Batch" + str(input.batchToGenerate), "batch_info.json")
batch_info_folder = os.path.join(input.nft_batch_save_path, "Batch" + str(input.batch_to_generate), "batch_info.json")
save_batch(batch_info, batch_info_folder)
# Send Email that Batch is complete:
if input.emailNotificationBool:
if input.email_notification_bool:
port = 465 # For SSL
smtp_server = "smtp.gmail.com"
sender_email = input.sender_from # Enter your address
@ -592,9 +592,9 @@ def render_and_save_nfts(input):
batch_data = get_batch_data(input.failed_batch, input.batch_json_save_path)
else:
batch_data = get_batch_data(input.batchToGenerate, input.batch_json_save_path)
batch_data = get_batch_data(input.batch_to_generate, input.batch_json_save_path)
batch = input.batchToGenerate
batch = input.batch_to_generate
generation_time = str(datetime.timedelta(seconds=batch_complete_time))
@ -627,11 +627,11 @@ def render_and_save_nfts(input):
if plateform == "Darwin":
os.system(f"shutdown /s /t {time}")
if input.enableAutoShutdown and not input.specify_timeBool:
if input.enable_auto_shutdown and not input.specify_time_bool:
shutdown(0)
# If user selects automatic shutdown and specify time after Batch completion
if input.enableAutoShutdown and input.specify_timeBool:
if input.enable_auto_shutdown and input.specify_time_bool:
hours = (int(input.hours) / 60) / 60
minutes = int(input.minutes) / 60
total_sleep_time = hours + minutes

Wyświetl plik

@ -5,7 +5,8 @@
import sys
import argparse
def getPythonArgs():
def get_python_args():
argv = sys.argv
@ -15,7 +16,7 @@ def getPythonArgs():
argv = argv[argv.index("--") + 1:] # get all args after "--"
usage_text = (
"Run Blend_My_NFTs headlessly from the command line\n"
"Run Blend_My_NFTs heedlessly from the command line\n"
"usage:\n"
"blender -background --python <Path to BMNFTs __init__.py> -- --config-file <path to config file>"
)
@ -64,4 +65,4 @@ def getPythonArgs():
help="Overwrite the logic file path in the config file"
)
return (parser.parse_args(argv), parser)
return parser.parse_args(argv), parser

Wyświetl plik

@ -408,7 +408,7 @@ def raise_error_num_batches_greater_then(num_batches):
# Raise Warnings:
def raise_warning_max_nfts(nfts_per_batch, collection_size):
"""
Prints warning if nftsPerBatch is greater than collectionSize.
Prints warning if nfts_per_batch is greater than collection_size.
"""
if nfts_per_batch > collection_size:
@ -421,7 +421,7 @@ def raise_warning_max_nfts(nfts_per_batch, collection_size):
def raise_warning_collection_size(dna_list, collection_size):
"""
Prints warning if BMNFTs cannot generate requested number of NFTs from a given collectionSize.
Prints warning if BMNFTs cannot generate requested number of NFTs from a given collection_size.
"""
if len(dna_list) < collection_size:

Wyświetl plik

@ -1,21 +1,23 @@
import json
import bpy
import json
from main import dna_generator, exporter
# TODO: migrate this code to the exporter.py to simplify render process into one file.
def send_To_Record_JSON(input, reverse_order=False):
if input.enableLogic:
if input.enable_Logic_Json and input.logicFile:
input.logicFile = json.load(open(input.logicFile))
if input.enable_Logic_Json and not input.logicFile:
def send_to_record(input, reverse_order=False):
if input.enable_logic:
if input.enable_logic_json and input.logic_file:
input.logic_file = json.load(open(input.logic_file))
if input.enable_logic_json and not input.logic_file:
print({'ERROR'}, f"No Logic.json file path set. Please set the file path to your Logic.json file.")
if not input.enable_Logic_Json:
if not input.enable_logic_json:
scn = bpy.context.scene
if reverse_order:
input.logicFile = {}
input.logic_file = {}
num = 1
for i in range(scn.logic_fields_index, -1, -1):
item = scn.logic_fields[i]
@ -23,20 +25,20 @@ def send_To_Record_JSON(input, reverse_order=False):
item_list1 = item.item_list1
rule_type = item.rule_type
item_list2 = item.item_list2
input.logicFile[f"Rule-{num}"] = {
input.logic_file[f"Rule-{num}"] = {
"IF": item_list1.split(','),
rule_type: item_list2.split(',')
}
print(rule_type)
num += 1
else:
input.logicFile = {}
input.logic_file = {}
num = 1
for item in scn.logic_fields:
item_list1 = item.item_list1
rule_type = item.rule_type
item_list2 = item.item_list2
input.logicFile[f"Rule-{num}"] = {
input.logic_file[f"Rule-{num}"] = {
"IF": item_list1.split(','),
rule_type: item_list2.split(',')
}
@ -44,37 +46,42 @@ def send_To_Record_JSON(input, reverse_order=False):
num += 1
dna_generator.send_to_record(input.collectionSize,
input.nftsPerBatch,
input.save_path,
input.enableRarity,
input.enableLogic,
input.logicFile,
input.enableMaterials,
input.materialsFile,
input.Blend_My_NFTs_Output,
input.batch_json_save_path,
input.enable_debug,
)
dna_generator.send_to_record(
input.collection_size,
input.nfts_per_batch,
input.save_path,
input.enable_rarity,
input.enable_logic,
input.logic_file,
input.enable_materials,
input.materials_file,
input.blend_my_nfts_output,
input.batch_json_save_path,
input.enable_debug,
)
def render_and_save_NFTs(input, reverse_order=False):
if input.enableCustomFields:
def render_and_save_nfts(input, reverse_order=False):
if input.enable_custom_fields:
scn = bpy.context.scene
if reverse_order:
for i in range(scn.custom_metadata_fields_index, -1, -1):
item = scn.custom_metadata_fields[i]
if item.field_name in list(input.custom_Fields.keys()):
if item.field_name in list(input.custom_fields.keys()):
raise ValueError(
f"A duplicate of '{item.field_name}' was found. Please ensure all Custom Metadata field Names are unique.")
f"A duplicate of '{item.field_name}' was found. Please ensure all Custom Metadata field Names "
f"are unique."
)
else:
input.custom_Fields[item.field_name] = item.field_value
input.custom_fields[item.field_name] = item.field_value
else:
for item in scn.custom_metadata_fields:
if item.field_name in list(input.custom_Fields.keys()):
if item.field_name in list(input.custom_fields.keys()):
raise ValueError(
f"A duplicate of '{item.field_name}' was found. Please ensure all Custom Metadata field Names are unique.")
f"A duplicate of '{item.field_name}' was found. Please ensure all Custom Metadata field Names "
f"are unique."
)
else:
input.custom_Fields[item.field_name] = item.field_value
input.custom_fields[item.field_name] = item.field_value
Exporter.render_and_save_nfts(input)
exporter.render_and_save_nfts(input)

Wyświetl plik

@ -1,19 +1,19 @@
# Purpose:
# 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
# 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 random
import collections
from .helpers import TextColors, removeList, remove_file_by_extension, save_result
from .helpers import TextColors
def reconstructDNA(deconstructedDNA):
reconstructed_DNA = ""
for a in deconstructedDNA:
def reconstruct_dna(deconstructed_dna):
reconstructed_dna = ""
for a in deconstructed_dna:
num = "-" + str(a)
reconstructed_DNA += num
return ''.join(reconstructed_DNA.split('-', 1))
reconstructed_dna += num
return ''.join(reconstructed_dna.split('-', 1))
def get_var_info(variant, hierarchy):
@ -33,11 +33,11 @@ def get_var_info(variant, hierarchy):
return [name, order_number, rarity_number, attribute, attribute_index] # list of Var info sent back
def apply_rules_to_dna(hierarchy, deconstructed_DNA, if_dict, result_dict, result_dict_type, enableRarity):
# Check if Variants in if_dict are in deconstructed_DNA, if so return if_list_selected = True:
def apply_rules_to_dna(hierarchy, deconstructed_dna, if_dict, result_dict, result_dict_type, enable_rarity):
# Check if Variants in if_dict are in deconstructed_dna, if so return if_list_selected = True:
if_list_selected = False
for a in deconstructed_DNA:
attribute_index = deconstructed_DNA.index(a)
for a in deconstructed_dna:
attribute_index = deconstructed_dna.index(a)
attribute = list(hierarchy.keys())[attribute_index]
for b in hierarchy[attribute]:
@ -49,23 +49,23 @@ def apply_rules_to_dna(hierarchy, deconstructed_DNA, if_dict, result_dict, resul
if_list_selected = True
# Apply changes in accordance to Variants in 'result_dict' and 'if_list_selected' bool above:
for a in deconstructed_DNA:
attribute_index = deconstructed_DNA.index(a)
for a in deconstructed_dna:
attribute_index = deconstructed_dna.index(a)
attribute = list(hierarchy.keys())[attribute_index]
if attribute in result_dict: # Check if Attribute from DNA is in 'result_dict'
# If 'a' is a full Attribute and Variants in if_dict not selected, set 'a' to empty (0):
if list(result_dict[attribute].keys()) == list(hierarchy[attribute].keys()) and not if_list_selected:
deconstructed_DNA[attribute_index] = "0"
deconstructed_dna[attribute_index] = "0"
# If 'a' is a full Attribute and result_dict_type = "NOT", set 'a' to empty (0):
if list(result_dict[attribute].keys()) == list(
hierarchy[attribute].keys()) and if_list_selected and result_dict_type == "NOT":
deconstructed_DNA[attribute_index] = "0"
deconstructed_dna[attribute_index] = "0"
# If Variants in if_dict are selected, set each attribute in 'result_dict' to a random or rarity selected Variant from
# 'result_dict[attribute]' variant_list:
# If Variants in if_dict are selected, set each attribute in 'result_dict' to a random or rarity selected Variant
# from 'result_dict[attribute]' variant_list:
if if_list_selected:
# Invert 'items_returned' if 'NOT' rule is selected:
@ -91,60 +91,60 @@ def apply_rules_to_dna(hierarchy, deconstructed_DNA, if_dict, result_dict, resul
if attribute in result_dict: # Check if Attribute from DNA is in 'then_dict'
number_List_Of_i = []
rarity_List_Of_i = []
ifZeroBool = None
variantNum = None
number_list_of_i = []
rarity_list_of_i = []
if_zero_bool = None
variant_num = None
for b in variant_list:
number = b.split("_")[1]
rarity = b.split("_")[2]
number_List_Of_i.append(int(number))
rarity_List_Of_i.append(float(rarity))
number_list_of_i.append(int(number))
rarity_list_of_i.append(float(rarity))
for b in rarity_List_Of_i:
for b in rarity_list_of_i:
if b == 0:
ifZeroBool = True
if_zero_bool = True
elif b != 0:
ifZeroBool = False
if_zero_bool = False
if enableRarity:
if enable_rarity:
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)
if if_zero_bool:
variant_num = random.choices(number_list_of_i, k=1)
elif not if_zero_bool:
variant_num = random.choices(number_list_of_i, weights=rarity_list_of_i, k=1)
except IndexError:
raise IndexError(
f"\n{TextColors.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{TextColors.RESET}"
f"An issue was found within the Attribute collection '{a}'. For more information on "
f"Blend_My_NFTs compatible scenes, see:\n{TextColors.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)
variant_num = random.choices(number_list_of_i, k=1)
except IndexError:
raise IndexError(
f"\n{TextColors.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{TextColors.RESET}"
f"An issue was found within the Attribute collection '{a}'. For more information on "
f"Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}"
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
)
deconstructed_DNA[int(attribute_index)] = str(variantNum[0])
deconstructed_dna[int(attribute_index)] = str(variant_num[0])
return deconstructed_DNA
return deconstructed_dna
def get_rule_break_type(hierarchy, deconstructed_DNA, if_dict, result_dict, result_dict_type):
# Check if Variants in 'if_dict' found in deconstructed_DNA:
if_bool = False # True if Variant in 'deconstructed_DNA' found in 'if_dict'
def get_rule_break_type(hierarchy, deconstructed_dna, if_dict, result_dict, result_dict_type):
# Check if Variants in 'if_dict' found in deconstructed_dna:
if_bool = False # True if Variant in 'deconstructed_dna' found in 'if_dict'
for a in if_dict: # Attribute in 'if_dict'
for b in if_dict[a]: # Variant in if_dict[Attribute]
var_order_num = str(if_dict[a][b][1]) # Order number of 'b' (Variant)
dna_order_num = str(
deconstructed_DNA[if_dict[a][b][4]]) # Order Number of 'b's attribute in deconstructed_DNA
deconstructed_dna[if_dict[a][b][4]]) # Order Number of 'b's attribute in deconstructed_dna
if var_order_num == dna_order_num: # If DNA selected Variants found inside IF list variants:
if_bool = True
@ -153,14 +153,14 @@ def get_rule_break_type(hierarchy, deconstructed_DNA, if_dict, result_dict, resu
continue
break
# Check if Variants in 'result_dict' found in deconstructed_DNA:
# Check if Variants in 'result_dict' found in deconstructed_dna:
full_att_bool = False
result_bool = False # True if Variant in 'deconstructed_DNA' found in 'result_dict'
result_bool = False # True if Variant in 'deconstructed_dna' found in 'result_dict'
for a in result_dict: # Attribute in 'result_dict'
for b in result_dict[a]: # Variant in if_dict[Attribute]
var_order_num = str(result_dict[a][b][1]) # Order number of 'b' (Variant)
dna_order_num = str(
deconstructed_DNA[result_dict[a][b][4]]) # Order Number of 'b's attribute in deconstructed_DNA
deconstructed_dna[result_dict[a][b][4]]) # Order Number of 'b's attribute in deconstructed_dna
if var_order_num == dna_order_num: # If DNA selected Variants found inside THEN list variants:
if list(result_dict[a].keys()) == list(hierarchy[a].keys()):
full_att_bool = True
@ -173,20 +173,20 @@ def get_rule_break_type(hierarchy, deconstructed_DNA, if_dict, result_dict, resu
# Rule Bool return summary:
violates_rule = False
# If Variants in 'if_dict' found in deconstructed_DNA and Variants in 'result_dict' not found in deconstructed_DNA:
# If Variants in 'if_dict' found in deconstructed_dna and Variants in 'result_dict' not found in deconstructed_dna:
if if_bool and not result_bool:
violates_rule = True
elif if_bool and result_bool and result_dict_type == "NOT":
violates_rule = True
# If Variants in 'if_dict' not found in deconstructed_DNA, and 'result_dict' variants are found in deconstructed_DNA,
# and they are a part of a full Attribute in 'then_dict'
# If Variants in 'if_dict' not found in deconstructed_dna, and 'result_dict' variants are found in
# deconstructed_dna, and they are a part of a full Attribute in 'then_dict'
elif not if_bool and result_bool and full_att_bool:
violates_rule = True
# If Variants in 'if_dict' not found in deconstructed_DNA, but Variants in 'then_dict' are found in deconstructed_DNA,
# and don't make up a full Attribute:
# If Variants in 'if_dict' not found in deconstructed_dna, but Variants in 'then_dict' are found in
# deconstructed_dna, and don't make up a full Attribute:
# elif not if_bool and result_bool and not full_att_bool:
# violates_rule = False
@ -252,41 +252,50 @@ def create_dicts(hierarchy, rule_list_items, result_dict_type):
return dict(items_returned)
def logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, enableMaterials):
deconstructed_DNA = singleDNA.split("-")
didReconstruct = True
originalDNA = str(singleDNA)
def logicafy_dna_single(hierarchy, single_dna, logic_file, enable_rarity):
deconstructed_dna = single_dna.split("-")
did_reconstruct = True
original_dna = str(single_dna)
while didReconstruct:
didReconstruct = False
for rule in logicFile:
while did_reconstruct:
did_reconstruct = False
for rule in logic_file:
# Items from 'IF' key for a given rule
if_dict = create_dicts(hierarchy, logicFile[rule]["IF"], "IF")
if_dict = create_dicts(hierarchy, logic_file[rule]["IF"], "IF")
result_dict_type = ""
if "THEN" in logicFile[rule]:
if "THEN" in logic_file[rule]:
result_dict_type = "THEN"
if "NOT" in logicFile[rule]:
if "NOT" in logic_file[rule]:
result_dict_type = "NOT"
result_dict = create_dicts(hierarchy, logicFile[rule][result_dict_type], result_dict_type)
result_dict = create_dicts(hierarchy, logic_file[rule][result_dict_type], result_dict_type)
# Change 'then_bool' to 'result_bool'
violates_rule, if_bool, then_bool, full_att_bool = get_rule_break_type(hierarchy, deconstructed_DNA,
if_dict, result_dict,
result_dict_type)
violates_rule, if_bool, then_bool, full_att_bool = get_rule_break_type(
hierarchy,
deconstructed_dna,
if_dict,
result_dict,
result_dict_type,
)
if violates_rule:
# print(f"======={deconstructed_DNA} VIOLATES RULE======")
# print(f"======={deconstructed_dna} VIOLATES RULE======")
deconstructed_DNA = apply_rules_to_dna(
hierarchy, deconstructed_DNA, if_dict, result_dict, result_dict_type, enableRarity
deconstructed_dna = apply_rules_to_dna(
hierarchy,
deconstructed_dna,
if_dict,
result_dict,
result_dict_type,
enable_rarity
)
newDNA = reconstructDNA(deconstructed_DNA)
if newDNA != originalDNA:
originalDNA = str(newDNA)
didReconstruct = True
new_dna = reconstruct_dna(deconstructed_dna)
if new_dna != original_dna:
original_dna = str(new_dna)
did_reconstruct = True
break
return str(reconstructDNA(deconstructed_DNA))
return str(reconstruct_dna(deconstructed_dna))

Wyświetl plik

@ -3,62 +3,61 @@
# 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
from .helpers import TextColors
def select_material(materialList, variant, enableRarity):
def select_material(material_list, variant, enable_rarity):
"""Selects a material from a passed material list. """
material_List_Of_i = [] # List of Material names instead of order numbers
rarity_List_Of_i = []
ifZeroBool = None
material_list_of_i = [] # List of Material names instead of order numbers
rarity_list_of_i = []
if_zero_bool = None
for material in materialList:
for material in material_list:
# 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 = list(material_list.keys()).index(material)
material_List_Of_i.append(material)
material_list_of_i.append(material)
material_rarity_percent = materialList[material]
rarity_List_Of_i.append(float(material_rarity_percent))
material_rarity_percent = material_list[material]
rarity_list_of_i.append(float(material_rarity_percent))
# print(f"MATERIAL_LIST_OF_I:{material_List_Of_i}")
# print(f"RARITY_LIST_OF_I:{rarity_List_Of_i}")
# print(f"MATERIAL_LIST_OF_I:{material_list_of_i}")
# print(f"RARITY_LIST_OF_I:{rarity_list_of_i}")
for b in rarity_List_Of_i:
for b in rarity_list_of_i:
if b == 0:
ifZeroBool = True
if_zero_bool = True
elif b != 0:
ifZeroBool = False
if_zero_bool = False
if enableRarity:
if enable_rarity:
try:
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)
if if_zero_bool:
selected_material = random.choices(material_list_of_i, k=1)
elif not if_zero_bool:
selected_material = random.choices(material_list_of_i, weights=rarity_list_of_i, k=1)
except IndexError:
raise IndexError(
f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n"
f"An issue was found within the Material List of the Variant collection '{variant}'. For more information on Blend_My_NFTs compatible scenes, "
f"see:\n{TextColors.RESET}"
f"An issue was found within the Material List of the Variant collection '{variant}'. For more "
f"information on Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}"
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
)
else:
try:
selected_material = random.choices(material_List_Of_i, k=1)
selected_material = random.choices(material_list_of_i, k=1)
except IndexError:
raise IndexError(
f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n"
f"An issue was found within the Material List of the Variant collection '{variant}'. For more information on Blend_My_NFTs compatible scenes, "
f"see:\n{TextColors.RESET}"
f"An issue was found within the Material List of the Variant collection '{variant}'. For more "
f"information on Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}"
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
)
return selected_material[0], materialList
return selected_material[0], material_list
def get_variant_att_index(variant, hierarchy):
variant_attribute = None
@ -72,26 +71,28 @@ def get_variant_att_index(variant, hierarchy):
variant_order_num = variant.split("_")[1]
return attribute_index, variant_order_num
def match_DNA_to_Variant(hierarchy, singleDNA):
def match_dna_to_variant(hierarchy, single_dna):
"""
Matches each DNA number separated by "-" to its attribute, then its variant.
"""
listAttributes = list(hierarchy.keys())
listDnaDecunstructed = singleDNA.split('-')
dnaDictionary = {}
list_attributes = list(hierarchy.keys())
list_dna_decunstructed = single_dna.split('-')
dna_dictionary = {}
for i, j in zip(listAttributes, listDnaDecunstructed):
dnaDictionary[i] = j
for i, j in zip(list_attributes, list_dna_decunstructed):
dna_dictionary[i] = j
for x in dnaDictionary:
for x in dna_dictionary:
for k in hierarchy[x]:
kNum = hierarchy[x][k]["number"]
if kNum == dnaDictionary[x]:
dnaDictionary.update({x: k})
return dnaDictionary
k_num = hierarchy[x][k]["number"]
if k_num == dna_dictionary[x]:
dna_dictionary.update({x: k})
return dna_dictionary
def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity):
def apply_materials(hierarchy, single_dna, materials_file, enable_rarity):
"""
DNA with applied material example: "1-1:1-1" <Normal DNA>:<Selected Material for each Variant>
@ -99,20 +100,23 @@ def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity):
list in the Variant_Material.json file.
"""
singleDNADict = match_DNA_to_Variant(hierarchy, singleDNA)
materialsFile = json.load(open(materialsFile))
deconstructed_MaterialDNA = {}
single_dna_dict = match_dna_to_variant(hierarchy, single_dna)
materials_file = json.load(open(materials_file))
deconstructed_material_dna = {}
for a in singleDNADict:
for a in single_dna_dict:
complete = False
for b in materialsFile:
if singleDNADict[a] == b:
material_name, materialList, = select_material(materialsFile[b]['Material List'], b, 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)
for b in materials_file:
if single_dna_dict[a] == b:
material_name, material_list, = select_material(materials_file[b]['Material List'], b, enable_rarity)
# Gets the Order Number of the Material
material_order_num = list(material_list.keys()).index(material_name)
deconstructed_material_dna[a] = str(material_order_num + 1)
complete = True
if not complete:
deconstructed_MaterialDNA[a] = "0"
deconstructed_material_dna[a] = "0"
# This section is now incorrect and needs updating:
@ -121,14 +125,14 @@ def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity):
# Attribute 'B' = 1, 'C' = 2, 'D' = 3, etc. For each pair you want to equal another, add its number it to this list:
# synced_material_attributes = [1, 2]
#
# first_mat = deconstructed_MaterialDNA[synced_material_attributes[0]]
# first_mat = deconstructed_material_dna[synced_material_attributes[0]]
# for i in synced_material_attributes:
# deconstructed_MaterialDNA[i] = first_mat
# deconstructed_material_dna[i] = first_mat
material_DNA = ""
for a in deconstructed_MaterialDNA:
num = "-" + str(deconstructed_MaterialDNA[a])
material_DNA += num
material_DNA = ''.join(material_DNA.split('-', 1))
material_dna = ""
for a in deconstructed_material_dna:
num = "-" + str(deconstructed_material_dna[a])
material_dna += num
material_dna = ''.join(material_dna.split('-', 1))
return f"{singleDNA}:{material_DNA}"
return f"{single_dna}:{material_dna}"

Wyświetl plik

@ -3,26 +3,37 @@
# https://discord.gg/QTT7dzcuVs
# Purpose:
# This file returns the specified meta data format to the exporter.py for a given NFT DNA.
# This file returns the specified metadata format to the exporter.py for a given NFT DNA.
import bpy
import os
import json
def sendMetaDataToJson(metaDataDict, save_path, file_name):
jsonMetaData = json.dumps(metaDataDict, indent=1, ensure_ascii=True)
with open(os.path.join(save_path, f"{file_name}.json"), 'w') as outfile:
outfile.write(jsonMetaData + '\n')
def stripNums(variant):
def send_metadata_to_json(meta_data_dict, save_path, file_name):
json_metadata = json.dumps(meta_data_dict, indent=1, ensure_ascii=True)
with open(os.path.join(save_path, f"{file_name}.json"), 'w') as outfile:
outfile.write(json_metadata + '\n')
def strip_nums(variant):
variant = str(variant).split('_')[0]
return variant
# Cardano Template
def createCardanoMetadata(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes,
custom_Fields, enableCustomFields, cardano_description, cardanoMetadataPath):
metaDataDictCardano = {"721": {
# Cardano Template
def create_cardano_metadata(
name,
order_num,
nft_dna,
nft_variants,
material_attributes,
custom_fields,
enable_custom_fields,
cardano_description,
cardano_metadata_path
):
meta_data_dict_cardano = {"721": {
"<policy_id>": {
name: {
"name": name,
@ -35,73 +46,107 @@ def createCardanoMetadata(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attri
}}
# Variants and Attributes:
for i in NFT_Variants:
metaDataDictCardano["721"]["<policy_id>"][name][i] = stripNums(NFT_Variants[i])
for i in nft_variants:
meta_data_dict_cardano["721"]["<policy_id>"][name][i] = strip_nums(nft_variants[i])
# Material Variants and Attributes:
for i in Material_Attributes:
metaDataDictCardano["721"]["<policy_id>"][name][i] = Material_Attributes[i]
for i in material_attributes:
meta_data_dict_cardano["721"]["<policy_id>"][name][i] = material_attributes[i]
# Custom Fields:
if enableCustomFields:
for i in custom_Fields:
metaDataDictCardano["721"]["<policy_id>"][name][i] = custom_Fields[i]
if enable_custom_fields:
for i in custom_fields:
meta_data_dict_cardano["721"]["<policy_id>"][name][i] = custom_fields[i]
sendMetaDataToJson(metaDataDictCardano, cardanoMetadataPath, name)
send_metadata_to_json(
meta_data_dict_cardano,
cardano_metadata_path,
name
)
# Solana Template
def createSolanaMetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes, custom_Fields, enableCustomFields,
solana_description, solanaMetadataPath):
metaDataDictSolana = {"name": name, "symbol": "", "description": solana_description, "seller_fee_basis_points": None,
"image": "", "animation_url": "", "external_url": ""}
def createSolanaMetaData(
name,
order_num,
nft_dna,
nft_variants,
material_attributes,
custom_fields,
enable_custom_fields,
solana_description,
solana_metadata_path
):
metadata_dict_solana = {
"name": name,
"symbol": "",
"description": solana_description,
"seller_fee_basis_points": None,
"image": "",
"animation_url": "",
"external_url": ""
}
attributes = []
# Variant and Attributes:
for i in NFT_Variants:
for i in nft_variants:
dictionary = {
"trait_type": i,
"value": stripNums(NFT_Variants[i])
"value": strip_nums(nft_variants[i])
}
attributes.append(dictionary)
# Material Variants and Attributes:
for i in Material_Attributes:
for i in material_attributes:
dictionary = {
"trait_type": i,
"value": Material_Attributes[i]
"value": material_attributes[i]
}
attributes.append(dictionary)
# Custom Fields:
if enableCustomFields:
for i in custom_Fields:
if enable_custom_fields:
for i in custom_fields:
dictionary = {
"trait_type": i,
"value": custom_Fields[i]
"value": custom_fields[i]
}
attributes.append(dictionary)
metaDataDictSolana["attributes"] = attributes
metaDataDictSolana["collection"] = {
metadata_dict_solana["attributes"] = attributes
metadata_dict_solana["collection"] = {
"name": "",
"family": ""
}
metaDataDictSolana["properties"] = {
metadata_dict_solana["properties"] = {
"files": [{"uri": "", "type": ""}],
"category": "",
"creators": [{"address": "", "share": None}]
}
sendMetaDataToJson(metaDataDictSolana, solanaMetadataPath, name)
send_metadata_to_json(
metadata_dict_solana,
solana_metadata_path,
name
)
# ERC721 Template
def createErc721MetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes, custom_Fields, enableCustomFields,
erc721_description, erc721MetadataPath):
metaDataDictErc721 = {
def create_erc721_meta_data(
name,
order_num,
nft_dna,
nft_variants,
material_attributes,
custom_fields,
enable_custom_fields,
erc721_description,
erc721_metadata_path
):
metadata_dict_erc721 = {
"name": name,
"description": erc721_description,
"image": "",
@ -111,33 +156,36 @@ def createErc721MetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attrib
attributes = []
# Variants and Attributes:
for i in NFT_Variants:
for i in nft_variants:
dictionary = {
"trait_type": i,
"value": stripNums(NFT_Variants[i])
"value": strip_nums(nft_variants[i])
}
attributes.append(dictionary)
# Material Variants and Attributes:
for i in Material_Attributes:
for i in material_attributes:
dictionary = {
"trait_type": i,
"value": Material_Attributes[i]
"value": material_attributes[i]
}
attributes.append(dictionary)
# Custom Fields:
if enableCustomFields:
for i in custom_Fields:
if enable_custom_fields:
for i in custom_fields:
dictionary = {
"trait_type": i,
"value": custom_Fields[i]
"value": custom_fields[i]
}
attributes.append(dictionary)
metaDataDictErc721["attributes"] = attributes
sendMetaDataToJson(metaDataDictErc721, erc721MetadataPath, name)
metadata_dict_erc721["attributes"] = attributes
send_metadata_to_json(
metadata_dict_erc721,
erc721_metadata_path,
name
)

Wyświetl plik

@ -1,48 +1,46 @@
# Purpose:
# This file goes through all batches, renames, and sorts all nft files to a Complete_Collection folder in Blend_My_NFTs
import bpy
import os
import json
import shutil
from .helpers import TextColors, removeList, remove_file_by_extension
from .helpers import remove_file_by_extension
def reformatNFTCollection(refactor_panel_input):
completeCollPath = os.path.join(refactor_panel_input.save_path, "Blend_My_NFTs Output", "Complete_Collection")
def reformat_nft_collection(refactor_panel_input):
complete_coll_path = os.path.join(refactor_panel_input.save_path, "Blend_My_NFTs Output", "Complete_Collection")
if not os.path.exists(completeCollPath):
os.mkdir(completeCollPath)
if not os.path.exists(complete_coll_path):
os.mkdir(complete_coll_path)
batchListDirty = os.listdir(refactor_panel_input.nftBatch_save_path)
batchList = remove_file_by_extension(batchListDirty)
batch_list_dirty = os.listdir(refactor_panel_input.nft_batch_save_path)
batch_list = remove_file_by_extension(batch_list_dirty)
collection_info = {"Total Time": 0}
for folder in batchList:
batch_info = json.load(open(os.path.join(refactor_panel_input.nftBatch_save_path, folder, "batch_info.json")))
for folder in batch_list:
batch_info = json.load(open(os.path.join(refactor_panel_input.nft_batch_save_path, folder, "batch_info.json")))
collection_info[os.path.basename(folder)] = batch_info
collection_info["Total Time"] = collection_info["Total Time"] + batch_info["Batch Render Time"]
fileListDirty = os.listdir(os.path.join(refactor_panel_input.nftBatch_save_path, folder))
filelist = remove_file_by_extension(fileListDirty)
file_list_dirty = os.listdir(os.path.join(refactor_panel_input.nft_batch_save_path, folder))
filelist = remove_file_by_extension(file_list_dirty)
for mediaTypeFolder in filelist:
if mediaTypeFolder != "batch_info.json":
mediaTypeFolderDir = os.path.join(refactor_panel_input.nftBatch_save_path, folder, mediaTypeFolder)
media_type_folder_dir = os.path.join(refactor_panel_input.nft_batch_save_path, folder, mediaTypeFolder)
for i in os.listdir(mediaTypeFolderDir):
destination = os.path.join(completeCollPath, mediaTypeFolder)
for i in os.listdir(media_type_folder_dir):
destination = os.path.join(complete_coll_path, mediaTypeFolder)
if not os.path.exists(destination):
os.makedirs(destination)
shutil.move(os.path.join(mediaTypeFolderDir, i), destination)
shutil.move(os.path.join(media_type_folder_dir, i), destination)
collection_info = json.dumps(collection_info, indent=1, ensure_ascii=True)
with open(os.path.join(completeCollPath, "collection_info.json"), 'w') as outfile:
with open(os.path.join(complete_coll_path, "collection_info.json"), 'w') as outfile:
outfile.write(collection_info + '\n')
print(f"All NFT files stored and sorted to the Complete_Collection folder in {refactor_panel_input.save_path}")
shutil.rmtree(refactor_panel_input.nftBatch_save_path)
shutil.rmtree(refactor_panel_input.nft_batch_save_path)