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, PropertyGroup,
UIList) UIList)
# ======== Operators ======== # # ======== Operators ======== #
class CUSTOM_OT_custom_metadata_fields_actions(Operator): class CUSTOM_OT_custom_metadata_fields_actions(Operator):
"""Move items up and down, add and remove""" """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): def invoke(self, context, event):
pass pass
# ======== Property Collection ======== # # ======== Property Collection ======== #
class CUSTOM_custom_metadata_fields_objectCollection(PropertyGroup): class CUSTOM_custom_metadata_fields_objectCollection(PropertyGroup):
# name: StringProperty() -> Instantiated by default # name: StringProperty() -> Instantiated by default

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -110,7 +110,7 @@ def generate_nft_dna(
# print(f"Rarity DNA: {single_dna}") # print(f"Rarity DNA: {single_dna}")
if enable_logic: 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}") # print(f"Logic DNA: {single_dna}")
if enable_materials: if enable_materials:
@ -170,7 +170,7 @@ def make_batches(
batch_json_save_path batch_json_save_path
): ):
""" """
Sorts through all the batches and outputs a given number of batches depending on collectionSize and nftsPerBatch. Sorts through all the batches and outputs a given number of batches depending on collection_size and nfts_per_batch.
These files are then saved as Batch#.json files to batch_json_save_path These files are then saved as Batch#.json files to batch_json_save_path
""" """

Wyświetl plik

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

Wyświetl plik

@ -5,7 +5,8 @@
import sys import sys
import argparse import argparse
def getPythonArgs():
def get_python_args():
argv = sys.argv argv = sys.argv
@ -15,7 +16,7 @@ def getPythonArgs():
argv = argv[argv.index("--") + 1:] # get all args after "--" argv = argv[argv.index("--") + 1:] # get all args after "--"
usage_text = ( usage_text = (
"Run Blend_My_NFTs headlessly from the command line\n" "Run Blend_My_NFTs heedlessly from the command line\n"
"usage:\n" "usage:\n"
"blender -background --python <Path to BMNFTs __init__.py> -- --config-file <path to config file>" "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" 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: # Raise Warnings:
def raise_warning_max_nfts(nfts_per_batch, collection_size): 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: 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): 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: if len(dna_list) < collection_size:

Wyświetl plik

@ -1,21 +1,23 @@
import json
import bpy import bpy
import json
from main import dna_generator, exporter 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.") 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 scn = bpy.context.scene
if reverse_order: if reverse_order:
input.logicFile = {} input.logic_file = {}
num = 1 num = 1
for i in range(scn.logic_fields_index, -1, -1): for i in range(scn.logic_fields_index, -1, -1):
item = scn.logic_fields[i] item = scn.logic_fields[i]
@ -23,20 +25,20 @@ def send_To_Record_JSON(input, reverse_order=False):
item_list1 = item.item_list1 item_list1 = item.item_list1
rule_type = item.rule_type rule_type = item.rule_type
item_list2 = item.item_list2 item_list2 = item.item_list2
input.logicFile[f"Rule-{num}"] = { input.logic_file[f"Rule-{num}"] = {
"IF": item_list1.split(','), "IF": item_list1.split(','),
rule_type: item_list2.split(',') rule_type: item_list2.split(',')
} }
print(rule_type) print(rule_type)
num += 1 num += 1
else: else:
input.logicFile = {} input.logic_file = {}
num = 1 num = 1
for item in scn.logic_fields: for item in scn.logic_fields:
item_list1 = item.item_list1 item_list1 = item.item_list1
rule_type = item.rule_type rule_type = item.rule_type
item_list2 = item.item_list2 item_list2 = item.item_list2
input.logicFile[f"Rule-{num}"] = { input.logic_file[f"Rule-{num}"] = {
"IF": item_list1.split(','), "IF": item_list1.split(','),
rule_type: item_list2.split(',') rule_type: item_list2.split(',')
} }
@ -44,37 +46,42 @@ def send_To_Record_JSON(input, reverse_order=False):
num += 1 num += 1
dna_generator.send_to_record(input.collectionSize, dna_generator.send_to_record(
input.nftsPerBatch, input.collection_size,
input.save_path, input.nfts_per_batch,
input.enableRarity, input.save_path,
input.enableLogic, input.enable_rarity,
input.logicFile, input.enable_logic,
input.enableMaterials, input.logic_file,
input.materialsFile, input.enable_materials,
input.Blend_My_NFTs_Output, input.materials_file,
input.batch_json_save_path, input.blend_my_nfts_output,
input.enable_debug, input.batch_json_save_path,
) input.enable_debug,
)
def render_and_save_NFTs(input, reverse_order=False): def render_and_save_nfts(input, reverse_order=False):
if input.enableCustomFields: if input.enable_custom_fields:
scn = bpy.context.scene scn = bpy.context.scene
if reverse_order: if reverse_order:
for i in range(scn.custom_metadata_fields_index, -1, -1): for i in range(scn.custom_metadata_fields_index, -1, -1):
item = scn.custom_metadata_fields[i] 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( 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: else:
input.custom_Fields[item.field_name] = item.field_value input.custom_fields[item.field_name] = item.field_value
else: else:
for item in scn.custom_metadata_fields: 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( 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: 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: # 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 random
import collections import collections
from .helpers import TextColors, removeList, remove_file_by_extension, save_result from .helpers import TextColors
def reconstructDNA(deconstructedDNA): def reconstruct_dna(deconstructed_dna):
reconstructed_DNA = "" reconstructed_dna = ""
for a in deconstructedDNA: for a in deconstructed_dna:
num = "-" + str(a) num = "-" + str(a)
reconstructed_DNA += num reconstructed_dna += num
return ''.join(reconstructed_DNA.split('-', 1)) return ''.join(reconstructed_dna.split('-', 1))
def get_var_info(variant, hierarchy): 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 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): 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: # Check if Variants in if_dict are in deconstructed_dna, if so return if_list_selected = True:
if_list_selected = False if_list_selected = False
for a in deconstructed_DNA: for a in deconstructed_dna:
attribute_index = deconstructed_DNA.index(a) attribute_index = deconstructed_dna.index(a)
attribute = list(hierarchy.keys())[attribute_index] attribute = list(hierarchy.keys())[attribute_index]
for b in hierarchy[attribute]: 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 if_list_selected = True
# Apply changes in accordance to Variants in 'result_dict' and 'if_list_selected' bool above: # Apply changes in accordance to Variants in 'result_dict' and 'if_list_selected' bool above:
for a in deconstructed_DNA: for a in deconstructed_dna:
attribute_index = deconstructed_DNA.index(a) attribute_index = deconstructed_dna.index(a)
attribute = list(hierarchy.keys())[attribute_index] attribute = list(hierarchy.keys())[attribute_index]
if attribute in result_dict: # Check if Attribute from DNA is in 'result_dict' 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 '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: 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 'a' is a full Attribute and result_dict_type = "NOT", set 'a' to empty (0):
if list(result_dict[attribute].keys()) == list( if list(result_dict[attribute].keys()) == list(
hierarchy[attribute].keys()) and if_list_selected and result_dict_type == "NOT": 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 # If Variants in if_dict are selected, set each attribute in 'result_dict' to a random or rarity selected Variant
# 'result_dict[attribute]' variant_list: # from 'result_dict[attribute]' variant_list:
if if_list_selected: if if_list_selected:
# Invert 'items_returned' if 'NOT' rule is 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' if attribute in result_dict: # Check if Attribute from DNA is in 'then_dict'
number_List_Of_i = [] number_list_of_i = []
rarity_List_Of_i = [] rarity_list_of_i = []
ifZeroBool = None if_zero_bool = None
variantNum = None variant_num = None
for b in variant_list: for b in variant_list:
number = b.split("_")[1] number = b.split("_")[1]
rarity = b.split("_")[2] rarity = b.split("_")[2]
number_List_Of_i.append(int(number)) number_list_of_i.append(int(number))
rarity_List_Of_i.append(float(rarity)) rarity_list_of_i.append(float(rarity))
for b in rarity_List_Of_i: for b in rarity_list_of_i:
if b == 0: if b == 0:
ifZeroBool = True if_zero_bool = True
elif b != 0: elif b != 0:
ifZeroBool = False if_zero_bool = False
if enableRarity: if enable_rarity:
try: try:
if ifZeroBool: if if_zero_bool:
variantNum = random.choices(number_List_Of_i, k=1) variant_num = random.choices(number_list_of_i, k=1)
elif not ifZeroBool: elif not if_zero_bool:
variantNum = random.choices(number_List_Of_i, weights=rarity_List_Of_i, k=1) variant_num = random.choices(number_list_of_i, weights=rarity_list_of_i, k=1)
except IndexError: except IndexError:
raise IndexError( raise IndexError(
f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n" f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n"
f"An issue was found within the Attribute collection '{a}'. For more information on Blend_My_NFTs compatible scenes, " f"An issue was found within the Attribute collection '{a}'. For more information on "
f"see:\n{TextColors.RESET}" f"Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}"
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n" f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
) )
else: else:
try: try:
variantNum = random.choices(number_List_Of_i, k=1) variant_num = random.choices(number_list_of_i, k=1)
except IndexError: except IndexError:
raise IndexError( raise IndexError(
f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n" f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n"
f"An issue was found within the Attribute collection '{a}'. For more information on Blend_My_NFTs compatible scenes, " f"An issue was found within the Attribute collection '{a}'. For more information on "
f"see:\n{TextColors.RESET}" f"Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}"
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n" f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
) )
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): 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: # Check if Variants in 'if_dict' found in deconstructed_dna:
if_bool = False # True if Variant in 'deconstructed_DNA' found in 'if_dict' if_bool = False # True if Variant in 'deconstructed_dna' found in 'if_dict'
for a in if_dict: # Attribute in 'if_dict' for a in if_dict: # Attribute in 'if_dict'
for b in if_dict[a]: # Variant in if_dict[Attribute] 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) var_order_num = str(if_dict[a][b][1]) # Order number of 'b' (Variant)
dna_order_num = str( 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 var_order_num == dna_order_num: # If DNA selected Variants found inside IF list variants:
if_bool = True if_bool = True
@ -153,14 +153,14 @@ def get_rule_break_type(hierarchy, deconstructed_DNA, if_dict, result_dict, resu
continue continue
break 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 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 a in result_dict: # Attribute in 'result_dict'
for b in result_dict[a]: # Variant in if_dict[Attribute] 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) var_order_num = str(result_dict[a][b][1]) # Order number of 'b' (Variant)
dna_order_num = str( 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 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()): if list(result_dict[a].keys()) == list(hierarchy[a].keys()):
full_att_bool = True 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: # Rule Bool return summary:
violates_rule = False 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: if if_bool and not result_bool:
violates_rule = True violates_rule = True
elif if_bool and result_bool and result_dict_type == "NOT": elif if_bool and result_bool and result_dict_type == "NOT":
violates_rule = True violates_rule = True
# If Variants in 'if_dict' not found in deconstructed_DNA, and 'result_dict' variants are found in deconstructed_DNA, # If Variants in 'if_dict' not found in deconstructed_dna, and 'result_dict' variants are found in
# and they are a part of a full Attribute in 'then_dict' # 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: elif not if_bool and result_bool and full_att_bool:
violates_rule = True violates_rule = True
# If Variants in 'if_dict' not found in deconstructed_DNA, but Variants in 'then_dict' are found in deconstructed_DNA, # If Variants in 'if_dict' not found in deconstructed_dna, but Variants in 'then_dict' are found in
# and don't make up a full Attribute: # deconstructed_dna, and don't make up a full Attribute:
# elif not if_bool and result_bool and not full_att_bool: # elif not if_bool and result_bool and not full_att_bool:
# violates_rule = False # violates_rule = False
@ -252,41 +252,50 @@ def create_dicts(hierarchy, rule_list_items, result_dict_type):
return dict(items_returned) return dict(items_returned)
def logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, enableMaterials): def logicafy_dna_single(hierarchy, single_dna, logic_file, enable_rarity):
deconstructed_DNA = singleDNA.split("-") deconstructed_dna = single_dna.split("-")
didReconstruct = True did_reconstruct = True
originalDNA = str(singleDNA) original_dna = str(single_dna)
while didReconstruct: while did_reconstruct:
didReconstruct = False did_reconstruct = False
for rule in logicFile: for rule in logic_file:
# Items from 'IF' key for a given rule # 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 = "" result_dict_type = ""
if "THEN" in logicFile[rule]: if "THEN" in logic_file[rule]:
result_dict_type = "THEN" result_dict_type = "THEN"
if "NOT" in logicFile[rule]: if "NOT" in logic_file[rule]:
result_dict_type = "NOT" 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' # Change 'then_bool' to 'result_bool'
violates_rule, if_bool, then_bool, full_att_bool = get_rule_break_type(hierarchy, deconstructed_DNA, violates_rule, if_bool, then_bool, full_att_bool = get_rule_break_type(
if_dict, result_dict, hierarchy,
result_dict_type) deconstructed_dna,
if_dict,
result_dict,
result_dict_type,
)
if violates_rule: if violates_rule:
# print(f"======={deconstructed_DNA} VIOLATES RULE======") # print(f"======={deconstructed_dna} VIOLATES RULE======")
deconstructed_DNA = apply_rules_to_dna( deconstructed_dna = apply_rules_to_dna(
hierarchy, deconstructed_DNA, if_dict, result_dict, result_dict_type, enableRarity hierarchy,
deconstructed_dna,
if_dict,
result_dict,
result_dict_type,
enable_rarity
) )
newDNA = reconstructDNA(deconstructed_DNA) new_dna = reconstruct_dna(deconstructed_dna)
if newDNA != originalDNA: if new_dna != original_dna:
originalDNA = str(newDNA) original_dna = str(new_dna)
didReconstruct = True did_reconstruct = True
break 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 # 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 ":" # 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 json
import random import random
from .helpers import TextColors 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. """ """Selects a material from a passed material list. """
material_List_Of_i = [] # List of Material names instead of order numbers material_list_of_i = [] # List of Material names instead of order numbers
rarity_List_Of_i = [] rarity_list_of_i = []
ifZeroBool = None 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 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] material_rarity_percent = material_list[material]
rarity_List_Of_i.append(float(material_rarity_percent)) rarity_list_of_i.append(float(material_rarity_percent))
# print(f"MATERIAL_LIST_OF_I:{material_List_Of_i}") # print(f"MATERIAL_LIST_OF_I:{material_list_of_i}")
# print(f"RARITY_LIST_OF_I:{rarity_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: if b == 0:
ifZeroBool = True if_zero_bool = True
elif b != 0: elif b != 0:
ifZeroBool = False if_zero_bool = False
if enableRarity: if enable_rarity:
try: try:
if ifZeroBool: if if_zero_bool:
selected_material = random.choices(material_List_Of_i, k=1) selected_material = random.choices(material_list_of_i, k=1)
elif not ifZeroBool: elif not if_zero_bool:
selected_material = random.choices(material_List_Of_i, weights=rarity_List_Of_i, k=1) selected_material = random.choices(material_list_of_i, weights=rarity_list_of_i, k=1)
except IndexError: except IndexError:
raise IndexError( raise IndexError(
f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n" 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"An issue was found within the Material List of the Variant collection '{variant}'. For more "
f"see:\n{TextColors.RESET}" 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" f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
) )
else: else:
try: try:
selected_material = random.choices(material_List_Of_i, k=1) selected_material = random.choices(material_list_of_i, k=1)
except IndexError: except IndexError:
raise IndexError( raise IndexError(
f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n" 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"An issue was found within the Material List of the Variant collection '{variant}'. For more "
f"see:\n{TextColors.RESET}" 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" 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): def get_variant_att_index(variant, hierarchy):
variant_attribute = None variant_attribute = None
@ -72,26 +71,28 @@ def get_variant_att_index(variant, hierarchy):
variant_order_num = variant.split("_")[1] variant_order_num = variant.split("_")[1]
return attribute_index, variant_order_num 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. Matches each DNA number separated by "-" to its attribute, then its variant.
""" """
listAttributes = list(hierarchy.keys()) list_attributes = list(hierarchy.keys())
listDnaDecunstructed = singleDNA.split('-') list_dna_decunstructed = single_dna.split('-')
dnaDictionary = {} dna_dictionary = {}
for i, j in zip(listAttributes, listDnaDecunstructed): for i, j in zip(list_attributes, list_dna_decunstructed):
dnaDictionary[i] = j dna_dictionary[i] = j
for x in dnaDictionary: for x in dna_dictionary:
for k in hierarchy[x]: for k in hierarchy[x]:
kNum = hierarchy[x][k]["number"] k_num = hierarchy[x][k]["number"]
if kNum == dnaDictionary[x]: if k_num == dna_dictionary[x]:
dnaDictionary.update({x: k}) dna_dictionary.update({x: k})
return dnaDictionary 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> 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. list in the Variant_Material.json file.
""" """
singleDNADict = match_DNA_to_Variant(hierarchy, singleDNA) single_dna_dict = match_dna_to_variant(hierarchy, single_dna)
materialsFile = json.load(open(materialsFile)) materials_file = json.load(open(materials_file))
deconstructed_MaterialDNA = {} deconstructed_material_dna = {}
for a in singleDNADict: for a in single_dna_dict:
complete = False complete = False
for b in materialsFile: for b in materials_file:
if singleDNADict[a] == b: if single_dna_dict[a] == b:
material_name, materialList, = select_material(materialsFile[b]['Material List'], b, enableRarity) material_name, material_list, = select_material(materials_file[b]['Material List'], b, enable_rarity)
material_order_num = list(materialList.keys()).index(material_name) # Gets the Order Number of the Material
deconstructed_MaterialDNA[a] = str(material_order_num + 1) # 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 complete = True
if not complete: if not complete:
deconstructed_MaterialDNA[a] = "0" deconstructed_material_dna[a] = "0"
# This section is now incorrect and needs updating: # 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: # 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] # 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: # for i in synced_material_attributes:
# deconstructed_MaterialDNA[i] = first_mat # deconstructed_material_dna[i] = first_mat
material_DNA = "" material_dna = ""
for a in deconstructed_MaterialDNA: for a in deconstructed_material_dna:
num = "-" + str(deconstructed_MaterialDNA[a]) num = "-" + str(deconstructed_material_dna[a])
material_DNA += num material_dna += num
material_DNA = ''.join(material_DNA.split('-', 1)) 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 # https://discord.gg/QTT7dzcuVs
# Purpose: # 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 os
import json 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] variant = str(variant).split('_')[0]
return variant 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>": { "<policy_id>": {
name: { name: {
"name": name, "name": name,
@ -35,73 +46,107 @@ def createCardanoMetadata(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attri
}} }}
# Variants and Attributes: # Variants and Attributes:
for i in NFT_Variants: for i in nft_variants:
metaDataDictCardano["721"]["<policy_id>"][name][i] = stripNums(NFT_Variants[i]) meta_data_dict_cardano["721"]["<policy_id>"][name][i] = strip_nums(nft_variants[i])
# Material Variants and Attributes: # Material Variants and Attributes:
for i in Material_Attributes: for i in material_attributes:
metaDataDictCardano["721"]["<policy_id>"][name][i] = Material_Attributes[i] meta_data_dict_cardano["721"]["<policy_id>"][name][i] = material_attributes[i]
# Custom Fields: # Custom Fields:
if enableCustomFields: if enable_custom_fields:
for i in custom_Fields: for i in custom_fields:
metaDataDictCardano["721"]["<policy_id>"][name][i] = custom_Fields[i] 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 # Solana Template
def createSolanaMetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes, custom_Fields, enableCustomFields, def createSolanaMetaData(
solana_description, solanaMetadataPath): name,
metaDataDictSolana = {"name": name, "symbol": "", "description": solana_description, "seller_fee_basis_points": None, order_num,
"image": "", "animation_url": "", "external_url": ""} 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 = [] attributes = []
# Variant and Attributes: # Variant and Attributes:
for i in NFT_Variants: for i in nft_variants:
dictionary = { dictionary = {
"trait_type": i, "trait_type": i,
"value": stripNums(NFT_Variants[i]) "value": strip_nums(nft_variants[i])
} }
attributes.append(dictionary) attributes.append(dictionary)
# Material Variants and Attributes: # Material Variants and Attributes:
for i in Material_Attributes: for i in material_attributes:
dictionary = { dictionary = {
"trait_type": i, "trait_type": i,
"value": Material_Attributes[i] "value": material_attributes[i]
} }
attributes.append(dictionary) attributes.append(dictionary)
# Custom Fields: # Custom Fields:
if enableCustomFields: if enable_custom_fields:
for i in custom_Fields: for i in custom_fields:
dictionary = { dictionary = {
"trait_type": i, "trait_type": i,
"value": custom_Fields[i] "value": custom_fields[i]
} }
attributes.append(dictionary) attributes.append(dictionary)
metaDataDictSolana["attributes"] = attributes metadata_dict_solana["attributes"] = attributes
metaDataDictSolana["collection"] = { metadata_dict_solana["collection"] = {
"name": "", "name": "",
"family": "" "family": ""
} }
metaDataDictSolana["properties"] = { metadata_dict_solana["properties"] = {
"files": [{"uri": "", "type": ""}], "files": [{"uri": "", "type": ""}],
"category": "", "category": "",
"creators": [{"address": "", "share": None}] "creators": [{"address": "", "share": None}]
} }
sendMetaDataToJson(metaDataDictSolana, solanaMetadataPath, name) send_metadata_to_json(
metadata_dict_solana,
solana_metadata_path,
name
)
# ERC721 Template # ERC721 Template
def createErc721MetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes, custom_Fields, enableCustomFields, def create_erc721_meta_data(
erc721_description, erc721MetadataPath): name,
metaDataDictErc721 = { order_num,
nft_dna,
nft_variants,
material_attributes,
custom_fields,
enable_custom_fields,
erc721_description,
erc721_metadata_path
):
metadata_dict_erc721 = {
"name": name, "name": name,
"description": erc721_description, "description": erc721_description,
"image": "", "image": "",
@ -111,33 +156,36 @@ def createErc721MetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attrib
attributes = [] attributes = []
# Variants and Attributes: # Variants and Attributes:
for i in NFT_Variants: for i in nft_variants:
dictionary = { dictionary = {
"trait_type": i, "trait_type": i,
"value": stripNums(NFT_Variants[i]) "value": strip_nums(nft_variants[i])
} }
attributes.append(dictionary) attributes.append(dictionary)
# Material Variants and Attributes: # Material Variants and Attributes:
for i in Material_Attributes: for i in material_attributes:
dictionary = { dictionary = {
"trait_type": i, "trait_type": i,
"value": Material_Attributes[i] "value": material_attributes[i]
} }
attributes.append(dictionary) attributes.append(dictionary)
# Custom Fields: # Custom Fields:
if enableCustomFields: if enable_custom_fields:
for i in custom_Fields: for i in custom_fields:
dictionary = { dictionary = {
"trait_type": i, "trait_type": i,
"value": custom_Fields[i] "value": custom_fields[i]
} }
attributes.append(dictionary) attributes.append(dictionary)
metaDataDictErc721["attributes"] = attributes metadata_dict_erc721["attributes"] = attributes
sendMetaDataToJson(metaDataDictErc721, erc721MetadataPath, name)
send_metadata_to_json(
metadata_dict_erc721,
erc721_metadata_path,
name
)

Wyświetl plik

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