diff --git a/UILists/custom_metadata_ui_list.py b/UILists/custom_metadata_ui_list.py index db88f25..54b4575 100644 --- a/UILists/custom_metadata_ui_list.py +++ b/UILists/custom_metadata_ui_list.py @@ -11,6 +11,7 @@ from bpy.types import (Operator, PropertyGroup, UIList) + # ======== Operators ======== # class CUSTOM_OT_custom_metadata_fields_actions(Operator): """Move items up and down, add and remove""" @@ -103,6 +104,7 @@ class CUSTOM_UL_custom_metadata_fields_items(UIList): def invoke(self, context, event): pass + # ======== Property Collection ======== # class CUSTOM_custom_metadata_fields_objectCollection(PropertyGroup): # name: StringProperty() -> Instantiated by default diff --git a/UILists/logic_ui_list.py b/UILists/logic_ui_list.py index 0f82f42..43c2f7f 100644 --- a/UILists/logic_ui_list.py +++ b/UILists/logic_ui_list.py @@ -11,6 +11,7 @@ from bpy.types import (Operator, PropertyGroup, UIList) + # ======== Operators ======== # class CUSTOM_OT_logic_actions(Operator): """Move items up and down, add and remove""" diff --git a/__init__.py b/__init__.py index 7de5fdb..640b43a 100644 --- a/__init__.py +++ b/__init__.py @@ -1,18 +1,19 @@ bl_info = { "name": "Blend_My_NFTs", - "author": "Torrin Leonard, This Cozy Studio Inc", - "version": (4, 5, 0), + "author": "Torrin Leonard, This Cozy Studio Inc.", + "version": (4, 5, 1), "blender": (3, 2, 2), "location": "View3D", - "description": "A free and opensource Blender add-on that enables you to create thousands of unique images, animations, and 3D models.", + "description": "A free and opensource Blender add-on that enables you to create thousands of unique images, " + "animations, and 3D models.", "support": "COMMUNITY", "doc_url": "https://github.com/torrinworx/Blend_My_NFTs", "tracker_url": "https://github.com/torrinworx/Blend_My_NFTs/issues/new", "category": "Development", } -BMNFTS_VERSION = "v4.5.0" -LAST_UPDATED = "12:34AM, Aug 11th, 2022" +BMNFTS_VERSION = "v4.5.1" +LAST_UPDATED = "01:02PM, Aug 24th, 2022" # ======== Import handling ======== # @@ -111,64 +112,64 @@ bpy.app.handlers.depsgraph_update_post.append(Refresh_UI) # ======== Defining BMNFTs Data ======== # @dataclass class BMNFTData: - nftName: str + nft_name: str save_path: str - nftsPerBatch: int - batchToGenerate: int - collectionSize: int + nfts_per_batch: int + batch_to_generate: int + collection_size: int - Blend_My_NFTs_Output: str + blend_my_nfts_output: str batch_json_save_path: str - nftBatch_save_path: str + nft_batch_save_path: str - enableImages: bool - imageFileFormat: str + enable_images: bool + image_file_format: str - enableAnimations: bool - animationFileFormat: str + enable_animations: bool + animation_file_format: str - enableModelsBlender: bool - modelFileFormat: str + enable_models: bool + model_file_format: str - enableCustomFields: bool + enable_custom_fields: bool - cardanoMetaDataBool: bool - solanaMetaDataBool: bool - erc721MetaData: bool + cardano_metadata_bool: bool + solana_metadata_bool: bool + erc721_metadata: bool cardano_description: str solana_description: str erc721_description: str - enableMaterials: bool - materialsFile: str + enable_materials: bool + materials_file: str - enableLogic: bool - enable_Logic_Json: bool - logicFile: str + enable_logic: bool + enable_logic_json: bool + logic_file: str - enableRarity: bool + enable_rarity: bool - enableAutoShutdown: bool + enable_auto_shutdown: bool - specify_timeBool: bool + specify_time_bool: bool hours: int minutes: int - emailNotificationBool: bool + email_notification_bool: bool sender_from: str email_password: str receiver_to: str enable_debug: bool - custom_Fields: dict = None + custom_fields: dict = None fail_state: Any = False failed_batch: Any = None failed_dna: Any = None failed_dna_index: Any = None def __post_init__(self): - self.custom_Fields = {} + self.custom_fields = {} def getBMNFTData(): @@ -176,51 +177,51 @@ def getBMNFTData(): _Blend_My_NFTs_Output, _batch_json_save_path, _nftBatch_save_path = make_directories(_save_path) data = BMNFTData( - nftName=bpy.context.scene.input_tool.nftName, + nft_name=bpy.context.scene.input_tool.nft_name, save_path=_save_path, - nftsPerBatch=bpy.context.scene.input_tool.nftsPerBatch, - batchToGenerate=bpy.context.scene.input_tool.batchToGenerate, - collectionSize=bpy.context.scene.input_tool.collectionSize, + nfts_per_batch=bpy.context.scene.input_tool.nfts_per_batch, + batch_to_generate=bpy.context.scene.input_tool.batch_to_generate, + collection_size=bpy.context.scene.input_tool.collection_size, - enableRarity=bpy.context.scene.input_tool.enableRarity, + enable_rarity=bpy.context.scene.input_tool.enable_rarity, - Blend_My_NFTs_Output=_Blend_My_NFTs_Output, + blend_my_nfts_output=_Blend_My_NFTs_Output, batch_json_save_path=_batch_json_save_path, - nftBatch_save_path=_nftBatch_save_path, + nft_batch_save_path=_nftBatch_save_path, - enableLogic=bpy.context.scene.input_tool.enableLogic, - enable_Logic_Json=bpy.context.scene.input_tool.enable_Logic_Json, - logicFile=bpy.context.scene.input_tool.logicFile, + enable_logic=bpy.context.scene.input_tool.enable_logic, + enable_logic_json=bpy.context.scene.input_tool.enable_logic_json, + logic_file=bpy.context.scene.input_tool.logic_file, - enableImages=bpy.context.scene.input_tool.imageBool, - imageFileFormat=bpy.context.scene.input_tool.imageEnum, + enable_images=bpy.context.scene.input_tool.image_bool, + image_file_format=bpy.context.scene.input_tool.image_enum, - enableAnimations=bpy.context.scene.input_tool.animationBool, - animationFileFormat=bpy.context.scene.input_tool.animationEnum, + enable_animations=bpy.context.scene.input_tool.animation_bool, + animation_file_format=bpy.context.scene.input_tool.animation_enum, - enableModelsBlender=bpy.context.scene.input_tool.modelBool, - modelFileFormat=bpy.context.scene.input_tool.modelEnum, + enable_models=bpy.context.scene.input_tool.model_bool, + model_file_format=bpy.context.scene.input_tool.model_enum, - enableCustomFields=bpy.context.scene.input_tool.enableCustomFields, + enable_custom_fields=bpy.context.scene.input_tool.enable_custom_fields, - cardanoMetaDataBool=bpy.context.scene.input_tool.cardanoMetaDataBool, - solanaMetaDataBool=bpy.context.scene.input_tool.solanaMetaDataBool, - erc721MetaData=bpy.context.scene.input_tool.erc721MetaData, + cardano_metadata_bool=bpy.context.scene.input_tool.cardano_metadata_bool, + solana_metadata_bool=bpy.context.scene.input_tool.solana_metadata_bool, + erc721_metadata=bpy.context.scene.input_tool.erc721_metadata, cardano_description=bpy.context.scene.input_tool.cardano_description, solana_description=bpy.context.scene.input_tool.solana_description, erc721_description=bpy.context.scene.input_tool.erc721_description, - enableMaterials=bpy.context.scene.input_tool.enableMaterials, - materialsFile=bpy.path.abspath(bpy.context.scene.input_tool.materialsFile), + enable_materials=bpy.context.scene.input_tool.enable_materials, + materials_file=bpy.path.abspath(bpy.context.scene.input_tool.materials_file), - enableAutoShutdown=bpy.context.scene.input_tool.enableAutoShutdown, + enable_auto_shutdown=bpy.context.scene.input_tool.enable_auto_shutdown, - specify_timeBool=bpy.context.scene.input_tool.specify_timeBool, + specify_time_bool=bpy.context.scene.input_tool.specify_time_bool, hours=bpy.context.scene.input_tool.hours, minutes=bpy.context.scene.input_tool.minutes, - emailNotificationBool=bpy.context.scene.input_tool.emailNotificationBool, + email_notification_bool=bpy.context.scene.input_tool.email_notification_bool, sender_from=bpy.context.scene.input_tool.sender_from, email_password=bpy.context.scene.input_tool.email_password, receiver_to=bpy.context.scene.input_tool.receiver_to, @@ -263,35 +264,35 @@ def runAsHeadless(): print('Using {} devices for rendering!'.format(cprefs.get_num_gpu_devices())) - def dumpSettings(settings): - output = ( - f"nftName={settings.nftName}\n" - f"collectionSize={str(settings.collectionSize)}\n" - f"nftsPerBatch={str(settings.nftsPerBatch)}\n" - f"save_path={settings.save_path}\n" - f"enableRarity={(settings.enableRarity)}\n" - f"enableLogic={str(settings.enableLogic)}\n" - f"imageBool={str(settings.imageBool)}\n" - f"imageEnum={settings.imageEnum}\n" - f"animationBool={str(settings.animationBool)}\n" - f"animationEnum={settings.animationEnum}\n" - f"modelBool={str(settings.modelBool)}\n" - f"modelEnum={settings.modelEnum}\n" - f"batch_to_generate={str(settings.batchToGenerate)}\n" - f"cardanoMetaDataBool={str(settings.cardanoMetaDataBool)}\n" - f"cardano_description={settings.cardano_description}\n" - f"erc721MetaData={str(settings.erc721MetaData)}\n" - f"erc721_description={settings.erc721_description}\n" - f"solanaMetaDataBool={str(settings.solanaMetaDataBool)}\n" - f"solana_description={settings.solana_description}\n" - f"enableCustomFields={str(settings.enableCustomFields)}\n" - f"customfieldsFile={settings.customfieldsFile}\n" - f"enableMaterials={str(settings.customfieldsFile)}\n" - f"materialsFile={settings.materialsFile}\n" - ) - print(output) + # def dumpSettings(settings): + # output = ( + # f"nft_name={settings.nft_name}\n" + # f"collection_size={str(settings.collection_size)}\n" + # f"nfts_per_batch={str(settings.nfts_per_batch)}\n" + # f"save_path={settings.save_path}\n" + # f"enable_rarity={(settings.enable_rarity)}\n" + # f"enable_logic={str(settings.enable_logic)}\n" + # f"image_bool={str(settings.image_bool)}\n" + # f"image_enum={settings.image_enum}\n" + # f"animation_bool={str(settings.animation_bool)}\n" + # f"animation_enum={settings.animation_enum}\n" + # f"model_bool={str(settings.model_bool)}\n" + # f"model_enum={settings.model_enum}\n" + # f"batch_to_generate={str(settings.batch_to_generate)}\n" + # f"cardano_metadata_bool={str(settings.cardano_metadata_bool)}\n" + # f"cardano_description={settings.cardano_description}\n" + # f"erc721_metadata={str(settings.erc721_metadata)}\n" + # f"erc721_description={settings.erc721_description}\n" + # f"solana_metadata_bool={str(settings.solana_metadata_bool)}\n" + # f"solana_description={settings.solana_description}\n" + # f"enable_custom_fields={str(settings.enable_custom_fields)}\n" + # f"custom_fields_file={settings.custom_fields_file}\n" + # f"enable_materials={str(settings.custom_fields_file)}\n" + # f"materials_file={settings.materials_file}\n" + # ) + # print(output) - args, parser = headless_util.getPythonArgs() + args, parser = headless_util.get_python_args() settings = bpy.context.scene.input_tool @@ -304,37 +305,37 @@ def runAsHeadless(): # print(pairs) - settings.nftName = pairs[0][1] - settings.collectionSize = int(pairs[1][1]) - settings.nftsPerBatch = int(pairs[2][1]) + settings.nft_name = pairs[0][1] + settings.collection_size = int(pairs[1][1]) + settings.nfts_per_batch = int(pairs[2][1]) settings.save_path = pairs[3][1] - settings.enableRarity = pairs[4][1] == 'True' - settings.enableLogic = pairs[5][1] == 'True' + settings.enable_rarity = pairs[4][1]=='True' + settings.enable_logic = pairs[5][1]=='True' settings.enableLogicJson = pairs[6][1] == 'True' - settings.logicFile = pairs[7][1] - settings.imageBool = pairs[8][1] == 'True' - settings.imageEnum = pairs[9][1] - settings.animationBool = pairs[10][1] == 'True' - settings.animationEnum = pairs[11][1] - settings.modelBool = pairs[12][1] == 'True' - settings.modelEnum = pairs[13][1] - settings.batchToGenerate = int(pairs[14][1]) - settings.cardanoMetaDataBool = pairs[15][1] == 'True' + settings.logic_file = pairs[7][1] + settings.image_bool = pairs[8][1]=='True' + settings.image_enum = pairs[9][1] + settings.animation_bool = pairs[10][1]=='True' + settings.animation_enum = pairs[11][1] + settings.model_bool = pairs[12][1]=='True' + settings.model_enum = pairs[13][1] + settings.batch_to_generate = int(pairs[14][1]) + settings.cardano_metadata_bool = pairs[15][1]=='True' settings.cardano_description = pairs[16][1] - settings.erc721MetaData = pairs[17][1] == 'True' + settings.erc721_metadata = pairs[17][1]=='True' settings.erc721_description = pairs[18][1] - settings.solanaMetaDataBool = pairs[19][1] == 'True' + settings.solana_metadata_bool = pairs[19][1]=='True' settings.solanaDescription = pairs[20][1] - settings.enableCustomFields = pairs[21][1] == 'True' - settings.customfieldsFile = pairs[22][1] - settings.enableMaterials = pairs[23][1] == 'True' - settings.materialsFile = pairs[24][1] + settings.enable_custom_fields = pairs[21][1]=='True' + settings.custom_fields_file = pairs[22][1] + settings.enable_materials = pairs[23][1]=='True' + settings.materials_file = pairs[24][1] if args.save_path: settings.save_path = args.save_path if args.batch_number: - settings.batchToGenerate = args.batch_number + settings.batch_to_generate = args.batch_number input = getBMNFTData() @@ -342,27 +343,27 @@ def runAsHeadless(): input.batch_json_save_path = args.batch_data_path if args.operation == 'create-dna': - intermediate.send_To_Record_JSON(input) + intermediate.send_to_record(input) elif args.operation == 'generate-nfts': - intermediate.render_and_save_NFTs(input) + intermediate.render_and_save_nfts(input) elif args.operation == 'refactor-batches': - refactorer.reformatNFTCollection(input) + refactorer.reformat_nft_collection(input) # ======== User input Property Group ======== # class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): # Create NFT Data Panel: - nftName: bpy.props.StringProperty(name="NFT Name") + nft_name: bpy.props.StringProperty(name="NFT Name") - collectionSize: bpy.props.IntProperty( + collection_size: bpy.props.IntProperty( name="NFT Collection Size", default=1, min=1 ) # max=(combinations - offset) - nftsPerBatch: bpy.props.IntProperty( + nfts_per_batch: bpy.props.IntProperty( name="NFTs Per Batch", default=1, min=1 @@ -376,17 +377,17 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): subtype="DIR_PATH" ) - enableRarity: bpy.props.BoolProperty( + enable_rarity: bpy.props.BoolProperty( name="Enable Rarity" ) - enableLogic: bpy.props.BoolProperty( + enable_logic: bpy.props.BoolProperty( name="Enable Logic" ) - enable_Logic_Json: bpy.props.BoolProperty( + enable_logic_json: bpy.props.BoolProperty( name="Use Logic.json instead" ) - logicFile: bpy.props.StringProperty( + logic_file: bpy.props.StringProperty( name="Logic File Path", description="Path where Logic.json is located.", default="", @@ -394,10 +395,10 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): subtype="FILE_PATH" ) - enableMaterials: bpy.props.BoolProperty( + enable_materials: bpy.props.BoolProperty( name="Enable Materials" ) - materialsFile: bpy.props.StringProperty( + materials_file: bpy.props.StringProperty( name="Materials File", description="Path where Materials.json is located.", default="", @@ -406,10 +407,10 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): ) # Generate NFTs Panel: - imageBool: bpy.props.BoolProperty( + image_bool: bpy.props.BoolProperty( name="Image" ) - imageEnum: bpy.props.EnumProperty( + image_enum: bpy.props.EnumProperty( name="Image File Format", description="Select Image file format", items=[ @@ -418,10 +419,10 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): ] ) - animationBool: bpy.props.BoolProperty( + animation_bool: bpy.props.BoolProperty( name="Animation" ) - animationEnum: bpy.props.EnumProperty( + animation_enum: bpy.props.EnumProperty( name="Animation File Format", description="Select Animation file format", items=[ @@ -434,10 +435,10 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): ] ) - modelBool: bpy.props.BoolProperty( + model_bool: bpy.props.BoolProperty( name="3D Model" ) - modelEnum: bpy.props.EnumProperty( + model_enum: bpy.props.EnumProperty( name="3D Model File Format", description="Select 3D Model file format", items=[ @@ -454,38 +455,38 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): ] ) - batchToGenerate: bpy.props.IntProperty( + batch_to_generate: bpy.props.IntProperty( name="Batch To Generate", default=1, min=1 ) # Refactor Batches & Create Metadata Panel: - cardanoMetaDataBool: bpy.props.BoolProperty( + cardano_metadata_bool: bpy.props.BoolProperty( name="Cardano Cip" ) cardano_description: bpy.props.StringProperty( name="Cardano description" ) - solanaMetaDataBool: bpy.props.BoolProperty( + solana_metadata_bool: bpy.props.BoolProperty( name="Solana Metaplex" ) solana_description: bpy.props.StringProperty( name="Solana description" ) - erc721MetaData: bpy.props.BoolProperty( + erc721_metadata: bpy.props.BoolProperty( name="ERC721" ) erc721_description: bpy.props.StringProperty( name="ERC721 description" ) - enableCustomFields: bpy.props.BoolProperty( + enable_custom_fields: bpy.props.BoolProperty( name="Enable Custom Metadata Fields" ) - customfieldsFile: bpy.props.StringProperty( + custom_fields_file: bpy.props.StringProperty( name="Custom Fields File", description="Path where Custom_Fields.json is located.", default="", @@ -496,17 +497,17 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): # TODO: Add 'Other' panel inputs to Headless functionality. # Other Panel: - enableAutoSave: bpy.props.BoolProperty( + enable_auto_save: bpy.props.BoolProperty( name="Auto Save Before Generation", description="Automatically saves your Blender file when 'Generate NFTs & Create Metadata' button is clicked" ) - enableAutoShutdown: bpy.props.BoolProperty( + enable_auto_shutdown: bpy.props.BoolProperty( name="Auto Shutdown", description="Automatically shuts down your computer after a Batch is finished Generating" ) - specify_timeBool: bpy.props.BoolProperty( + specify_time_bool: bpy.props.BoolProperty( name="Shutdown in a Given Amount of Time", description="Wait a given amount of time after a Batch is generated before Automatic Shutdown" ) @@ -517,7 +518,7 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): default=0, min=0 ) - emailNotificationBool: bpy.props.BoolProperty( + email_notification_bool: bpy.props.BoolProperty( name="Email Notifications", description="Receive Email Notifications from Blender once a batch is finished generating" ) @@ -541,17 +542,18 @@ class BMNFTS_PGT_Input_Properties(bpy.types.PropertyGroup): ) # API Panel properties: - apiKey: bpy.props.StringProperty( + api_key: bpy.props.StringProperty( name="API Key", subtype='PASSWORD' ) # Test code for future features # ======== Main Operators ======== # -class createData(bpy.types.Operator): +class Createdata(bpy.types.Operator): bl_idname = 'create.data' bl_label = 'Create Data' - bl_description = 'Creates NFT Data. Run after any changes were made to scene. All previous data will be overwritten and cannot be recovered.' + bl_description = 'Creates NFT Data. Run after any changes were made to scene. All previous data will be ' \ + 'overwritten and cannot be recovered.' bl_options = {"REGISTER", "UNDO"} reverse_order: BoolProperty( @@ -562,12 +564,12 @@ class createData(bpy.types.Operator): # Handling Custom Fields UIList input: input = getBMNFTData() - if input.enableLogic: - if input.enable_Logic_Json and not input.logicFile: + if input.enable_logic: + if input.enable_logic_json and not input.logic_file: self.report({'ERROR'}, f"No Logic.json file path set. Please set the file path to your Logic.json file.") - intermediate.send_To_Record_JSON(input) + intermediate.send_to_record(input) self.report({'INFO'}, f"NFT Data created!") return {"FINISHED"} @@ -576,7 +578,7 @@ class createData(bpy.types.Operator): return context.window_manager.invoke_confirm(self, event) -class exportNFTs(bpy.types.Operator): +class ExportNFTs(bpy.types.Operator): bl_idname = 'exporter.nfts' bl_label = 'Export NFTs' bl_description = 'Generate and export a given batch of NFTs.' @@ -590,14 +592,14 @@ class exportNFTs(bpy.types.Operator): input = getBMNFTData() # Handling Custom Fields UIList input: - intermediate.render_and_save_NFTs(input) + intermediate.render_and_save_nfts(input) - self.report({'INFO'}, f"All NFTs generated for batch {input.batchToGenerate}!") + self.report({'INFO'}, f"All NFTs generated for batch {input.batch_to_generate}!") return {"FINISHED"} -class resume_failed_batch(bpy.types.Operator): +class ResumeFailedBatch(bpy.types.Operator): bl_idname = 'exporter.resume_nfts' bl_label = 'Resume Failed Batch' bl_description = 'Failed Batch detected. Generate NFTs where the previous batch failed?' @@ -607,7 +609,7 @@ class resume_failed_batch(bpy.types.Operator): _save_path = bpy.path.abspath(bpy.context.scene.input_tool.save_path) _Blend_My_NFTs_Output, _batch_json_save_path, _nftBatch_save_path = make_directories(_save_path) - _batchToGenerate = bpy.context.scene.input_tool.batchToGenerate + _batchToGenerate = bpy.context.scene.input_tool.batch_to_generate file_name = os.path.join(_batch_json_save_path, "Batch{}.json".format(_batchToGenerate)) batchData = json.load(open(file_name)) @@ -617,51 +619,51 @@ class resume_failed_batch(bpy.types.Operator): render_settings = batchData["Generation Save"][-1]["Render_Settings"] input = BMNFTData( - nftName=render_settings["nftName"], + nft_name=render_settings["nft_name"], save_path=_save_path, - nftsPerBatch=render_settings["nftsPerBatch"], - batchToGenerate=render_settings["batch_to_generate"], - collectionSize=render_settings["collectionSize"], + nfts_per_batch=render_settings["nfts_per_batch"], + batch_to_generate=render_settings["batch_to_generate"], + collection_size=render_settings["collection_size"], - Blend_My_NFTs_Output=_Blend_My_NFTs_Output, + blend_my_nfts_output=_Blend_My_NFTs_Output, batch_json_save_path=_batch_json_save_path, - nftBatch_save_path=render_settings["nftBatch_save_path"], + nft_batch_save_path=render_settings["nft_batch_save_path"], - enableImages=render_settings["enableImages"], - imageFileFormat=render_settings["imageFileFormat"], + enable_images=render_settings["enable_images"], + image_file_format=render_settings["image_file_format"], - enableAnimations=render_settings["enableAnimations"], - animationFileFormat=render_settings["animationFileFormat"], + enable_animations=render_settings["enable_animations"], + animation_file_format=render_settings["animation_file_format"], - enableModelsBlender=render_settings["enableModelsBlender"], - modelFileFormat=render_settings["modelFileFormat"], + enable_models=render_settings["enable_models"], + model_file_format=render_settings["model_file_format"], - enableCustomFields=render_settings["enableCustomFields"], + enable_custom_fields=render_settings["enable_custom_fields"], - cardanoMetaDataBool=render_settings["cardanoMetaDataBool"], - solanaMetaDataBool=render_settings["solanaMetaDataBool"], - erc721MetaData=render_settings["erc721MetaData"], + cardano_metadata_bool=render_settings["cardano_metadata_bool"], + solana_metadata_bool=render_settings["solana_metadata_bool"], + erc721_metadata=render_settings["erc721_metadata"], cardano_description=render_settings["cardano_description"], solana_description=render_settings["solana_description"], erc721_description=render_settings["erc721_description"], - enableMaterials=render_settings["enableMaterials"], - materialsFile=render_settings["materialsFile"], + enable_materials=render_settings["enable_materials"], + materials_file=render_settings["materials_file"], - enableLogic=render_settings["enableLogic"], - enable_Logic_Json=render_settings["enable_Logic_Json"], - logicFile=render_settings["logicFile"], + enable_logic=render_settings["enable_logic"], + enable_logic_json=render_settings["enable_logic_json"], + logic_file=render_settings["logic_file"], - enableRarity=render_settings["enableRarity"], + enable_rarity=render_settings["enable_rarity"], - enableAutoShutdown=render_settings["enableAutoShutdown"], + enable_auto_shutdown=render_settings["enable_auto_shutdown"], - specify_timeBool=render_settings["specify_timeBool"], + specify_time_bool=render_settings["specify_time_bool"], hours=render_settings["hours"], minutes=render_settings["minutes"], - emailNotificationBool=render_settings["emailNotificationBool"], + email_notification_bool=render_settings["email_notification_bool"], sender_from=render_settings["sender_from"], email_password=render_settings["email_password"], receiver_to=render_settings["receiver_to"], @@ -672,7 +674,7 @@ class resume_failed_batch(bpy.types.Operator): failed_dna=_failed_dna, failed_dna_index=_failed_dna_index, - custom_Fields=render_settings["custom_Fields"], + custom_fields=render_settings["custom_fields"], ) exporter.render_and_save_nfts(input) @@ -682,7 +684,7 @@ class resume_failed_batch(bpy.types.Operator): return {"FINISHED"} -class refactor_Batches(bpy.types.Operator): +class RefactorBatches(bpy.types.Operator): """Refactor your collection? This action cannot be undone.""" bl_idname = 'refactor.batches' bl_label = 'Refactor your Batches?' @@ -695,14 +697,14 @@ class refactor_Batches(bpy.types.Operator): def execute(self, context): # Passing info to main functions for refactoring: - refactorer.reformatNFTCollection(getBMNFTData()) + refactorer.reformat_nft_collection(getBMNFTData()) return {"FINISHED"} def invoke(self, context, event): return context.window_manager.invoke_confirm(self, event) -class export_settings(bpy.types.Operator): +class ExportSettings(bpy.types.Operator): """Export your settings into a configuration file.""" bl_idname = 'export.settings' bl_label = 'Export Settings' @@ -721,51 +723,51 @@ class export_settings(bpy.types.Operator): "#when running Blend_My_NFTs in a headless environment.\n" "\n" "#The name of your nft project\n" - f"nftName={settings.nftName}\n" + f"nft_name={settings.nft_name}\n" "\n" "#NFT Collection Size\n" - f"collectionSize={settings.collectionSize}\n" + f"collection_size={settings.collection_size}\n" "\n" "#The number of NFTs to generate per batch\n" - f"nftsPerBatch={str(settings.nftsPerBatch)}\n" + f"nfts_per_batch={str(settings.nfts_per_batch)}\n" "\n" "#Save path for your NFT files\n" f"save_path={settings.save_path}\n" "\n" "#Enable Rarity\n" - f"enableRarity={(settings.enableRarity)}\n" + f"enable_rarity={settings.enable_rarity}\n" "\n" "#Enable Logic\n" - f"enableLogic={str(settings.enableLogic)}\n" - f"enableLogicJson={str(settings.enable_Logic_Json)}\n" - f"logicFilePath={settings.logicFile}\n" + f"enable_logic={str(settings.enable_logic)}\n" + f"enableLogicJson={str(settings.enable_logic_json)}\n" + f"logicFilePath={settings.logic_file}\n" "\n" "#NFT Media output type(s):\n" - f"imageBool={str(settings.imageBool)}\n" - f"imageEnum={settings.imageEnum}\n" - f"animationBool={str(settings.animationBool)}\n" - f"animationEnum={settings.animationEnum}\n" - f"modelBool={str(settings.modelBool)}\n" - f"modelEnum={settings.modelEnum}\n" + f"image_bool={str(settings.image_bool)}\n" + f"image_enum={settings.image_enum}\n" + f"animation_bool={str(settings.animation_bool)}\n" + f"animation_enum={settings.animation_enum}\n" + f"model_bool={str(settings.model_bool)}\n" + f"model_enum={settings.model_enum}\n" "\n" "#Batch to generate\n" - f"batch_to_generate={str(settings.batchToGenerate)}\n" + f"batch_to_generate={str(settings.batch_to_generate)}\n" "\n" "#Metadata Format\n" - f"cardanoMetaDataBool={str(settings.cardanoMetaDataBool)}\n" + f"cardano_metadata_bool={str(settings.cardano_metadata_bool)}\n" f"cardano_description={settings.cardano_description}\n" - f"erc721MetaData={str(settings.erc721MetaData)}\n" + f"erc721_metadata={str(settings.erc721_metadata)}\n" f"erc721_description={settings.erc721_description}\n" - f"solanaMetaDataBool={str(settings.solanaMetaDataBool)}\n" + f"solana_metadata_bool={str(settings.solana_metadata_bool)}\n" f"solana_description={settings.solana_description}\n" "\n" "#Enable Custom Fields\n" - f"enableCustomFields={str(settings.enableCustomFields)}\n" - f"customfieldsFile={settings.customfieldsFile}\n" + f"enable_custom_fields={str(settings.enable_custom_fields)}\n" + f"custom_fields_file={settings.custom_fields_file}\n" "\n" "#Enable Materials\n" - f"enableMaterials={str(settings.enableMaterials)}\n" - f"materialsFile={settings.materialsFile}\n" + f"enable_materials={str(settings.enable_materials)}\n" + f"materials_file={settings.materials_file}\n" ) print(output, file=config) @@ -789,29 +791,29 @@ class BMNFTS_PT_CreateData(bpy.types.Panel): input_tool_scene = scene.input_tool row = layout.row() - row.prop(input_tool_scene, "nftName") + row.prop(input_tool_scene, "nft_name") row = layout.row() layout.label(text=f"Maximum Number Of NFTs: {combinations}") layout.label(text=f"Recommended limit: {recommended_limit}") row = layout.row() - row.prop(input_tool_scene, "collectionSize") + row.prop(input_tool_scene, "collection_size") row = layout.row() - row.prop(input_tool_scene, "nftsPerBatch") + row.prop(input_tool_scene, "nfts_per_batch") row = layout.row() row.prop(input_tool_scene, "save_path") row = layout.row() - row.prop(input_tool_scene, "enableRarity") + row.prop(input_tool_scene, "enable_rarity") row = layout.row() - row.prop(input_tool_scene, "enableLogic") + row.prop(input_tool_scene, "enable_logic") # Logic_UIList implementation: - if bpy.context.scene.input_tool.enableLogic: + if bpy.context.scene.input_tool.enable_logic: layout = self.layout scn = bpy.context.scene @@ -835,18 +837,18 @@ class BMNFTS_PT_CreateData(bpy.types.Panel): row.label(text=f"*Field Names must be unique.") row = layout.row() - row.prop(input_tool_scene, "enable_Logic_Json") + row.prop(input_tool_scene, "enable_logic_json") - if bpy.context.scene.input_tool.enable_Logic_Json: + if bpy.context.scene.input_tool.enable_logic_json: row = layout.row() - row.prop(input_tool_scene, "logicFile") + row.prop(input_tool_scene, "logic_file") row = layout.row() - row.prop(input_tool_scene, "enableMaterials") + row.prop(input_tool_scene, "enable_materials") - if bpy.context.scene.input_tool.enableMaterials: + if bpy.context.scene.input_tool.enable_materials: row = layout.row() - row.prop(input_tool_scene, "materialsFile") + row.prop(input_tool_scene, "materials_file") row = layout.row() self.layout.operator("create.data", icon='DISCLOSURE_TRI_RIGHT', text="Create Data") @@ -870,26 +872,26 @@ class BMNFTS_PT_GenerateNFTs(bpy.types.Panel): layout.label(text="NFT Media files:") row = layout.row() - row.prop(input_tool_scene, "imageBool") - if bpy.context.scene.input_tool.imageBool: - row.prop(input_tool_scene, "imageEnum") + row.prop(input_tool_scene, "image_bool") + if bpy.context.scene.input_tool.image_bool: + row.prop(input_tool_scene, "image_enum") row = layout.row() - row.prop(input_tool_scene, "animationBool") - if bpy.context.scene.input_tool.animationBool: - row.prop(input_tool_scene, "animationEnum") + row.prop(input_tool_scene, "animation_bool") + if bpy.context.scene.input_tool.animation_bool: + row.prop(input_tool_scene, "animation_enum") row = layout.row() - row.prop(input_tool_scene, "modelBool") - if bpy.context.scene.input_tool.modelBool: - row.prop(input_tool_scene, "modelEnum") + row.prop(input_tool_scene, "model_bool") + if bpy.context.scene.input_tool.model_bool: + row.prop(input_tool_scene, "model_enum") row = layout.row() layout.label(text="Meta Data format:") row = layout.row() - row.prop(input_tool_scene, "cardanoMetaDataBool") - if bpy.context.scene.input_tool.cardanoMetaDataBool: + row.prop(input_tool_scene, "cardano_metadata_bool") + if bpy.context.scene.input_tool.cardano_metadata_bool: row = layout.row() row.prop(input_tool_scene, "cardano_description") @@ -898,8 +900,8 @@ class BMNFTS_PT_GenerateNFTs(bpy.types.Panel): icon='URL').url = "https://cips.cardano.org/cips/cip25/" row = layout.row() - row.prop(input_tool_scene, "solanaMetaDataBool") - if bpy.context.scene.input_tool.solanaMetaDataBool: + row.prop(input_tool_scene, "solana_metadata_bool") + if bpy.context.scene.input_tool.solana_metadata_bool: row = layout.row() row.prop(input_tool_scene, "solana_description") @@ -908,8 +910,8 @@ class BMNFTS_PT_GenerateNFTs(bpy.types.Panel): icon='URL').url = "https://docs.metaplex.com/token-metadata/specification" row = layout.row() - row.prop(input_tool_scene, "erc721MetaData") - if bpy.context.scene.input_tool.erc721MetaData: + row.prop(input_tool_scene, "erc721_metadata") + if bpy.context.scene.input_tool.erc721_metadata: row = layout.row() row.prop(input_tool_scene, "erc721_description") @@ -918,10 +920,10 @@ class BMNFTS_PT_GenerateNFTs(bpy.types.Panel): icon='URL').url = "https://docs.opensea.io/docs/metadata-standards" row = layout.row() - row.prop(input_tool_scene, "enableCustomFields") + row.prop(input_tool_scene, "enable_custom_fields") # Custom Metadata Fields UIList: - if bpy.context.scene.input_tool.enableCustomFields: + if bpy.context.scene.input_tool.enable_custom_fields: layout = self.layout scn = bpy.context.scene @@ -1010,16 +1012,16 @@ class BMNFTS_PT_Other(bpy.types.Panel): """ row = layout.row() - row.prop(input_tool_scene, "enableAutoSave") + row.prop(input_tool_scene, "enable_auto_save") # Auto Shutdown: row = layout.row() - row.prop(input_tool_scene, "enableAutoShutdown") + row.prop(input_tool_scene, "enable_auto_shutdown") row.label(text="*Must Run Blender as Admin") - if bpy.context.scene.input_tool.enableAutoShutdown: + if bpy.context.scene.input_tool.enable_auto_shutdown: row = layout.row() - row.prop(input_tool_scene, "specify_timeBool") + row.prop(input_tool_scene, "specify_time_bool") time_row1 = layout.row() time_row1.label(text=f"Hours") @@ -1029,7 +1031,7 @@ class BMNFTS_PT_Other(bpy.types.Panel): time_row2.label(text=f"Minutes") time_row2.prop(input_tool_scene, "minutes", text="") - if not bpy.context.scene.input_tool.specify_timeBool: + if not bpy.context.scene.input_tool.specify_time_bool: time_row1.enabled = False time_row2.enabled = False else: @@ -1038,10 +1040,10 @@ class BMNFTS_PT_Other(bpy.types.Panel): layout.separator() row = layout.row() - row.prop(input_tool_scene, "emailNotificationBool") + row.prop(input_tool_scene, "email_notification_bool") row.label(text="*Windows 10+ only") - if bpy.context.scene.input_tool.emailNotificationBool: + if bpy.context.scene.input_tool.email_notification_bool: row = layout.row() row.prop(input_tool_scene, "sender_from") row = layout.row() @@ -1089,22 +1091,22 @@ class BMNFTS_PT_Other(bpy.types.Panel): # ======== Blender add-on register/unregister handling ======== # classes = ( - # Property Group Classes: - BMNFTS_PGT_Input_Properties, + # Property Group Classes: + BMNFTS_PGT_Input_Properties, - # Operator Classes: - createData, - exportNFTs, - resume_failed_batch, - refactor_Batches, - export_settings, + # Operator Classes: + Createdata, + ExportNFTs, + ResumeFailedBatch, + RefactorBatches, + ExportSettings, - # Panel Classes: - BMNFTS_PT_CreateData, - BMNFTS_PT_GenerateNFTs, - BMNFTS_PT_Refactor, - BMNFTS_PT_Other, - ) + custom_metadata_ui_list.classes_Custom_Metadata_UIList + logic_ui_list.classes_Logic_UIList + # Panel Classes: + BMNFTS_PT_CreateData, + BMNFTS_PT_GenerateNFTs, + BMNFTS_PT_Refactor, + BMNFTS_PT_Other, +) + custom_metadata_ui_list.classes_Custom_Metadata_UIList + logic_ui_list.classes_Logic_UIList def register(): diff --git a/main/dna_generator.py b/main/dna_generator.py index 289d56b..62a30c1 100644 --- a/main/dna_generator.py +++ b/main/dna_generator.py @@ -110,7 +110,7 @@ def generate_nft_dna( # print(f"Rarity DNA: {single_dna}") if enable_logic: - single_dna = logic.logicafyDNAsingle(hierarchy, single_dna, logic_file, enable_rarity, enable_materials) + single_dna = logic.logicafy_dna_single(hierarchy, single_dna, logic_file, enable_rarity, enable_materials) # print(f"Logic DNA: {single_dna}") if enable_materials: @@ -170,7 +170,7 @@ def make_batches( batch_json_save_path ): """ - Sorts through all the batches and outputs a given number of batches depending on collectionSize and nftsPerBatch. + Sorts through all the batches and outputs a given number of batches depending on collection_size and nfts_per_batch. These files are then saved as Batch#.json files to batch_json_save_path """ diff --git a/main/exporter.py b/main/exporter.py index 0c640e0..2a70c35 100644 --- a/main/exporter.py +++ b/main/exporter.py @@ -12,7 +12,7 @@ import datetime import platform from .helpers import TextColors, Loader -from .metadata_templates import createCardanoMetadata, createSolanaMetaData, createErc721MetaData +from .metadata_templates import create_cardano_metadata, createSolanaMetaData, create_erc721_meta_data # Save info @@ -28,7 +28,7 @@ def save_generation_state(input): Saves date and time of generation start, and generation types; Images, Animations, 3D Models, and the file types for each. """ - file_name = os.path.join(input.batch_json_save_path, "Batch{}.json".format(input.batchToGenerate)) + file_name = os.path.join(input.batch_json_save_path, "Batch{}.json".format(input.batch_to_generate)) batch = json.load(open(file_name)) current_time = datetime.datetime.now().strftime("%H:%M:%S") @@ -46,56 +46,56 @@ def save_generation_state(input): "DNA Generated": None, "Generation Start Date and Time": [current_time, current_date, local_timezone], "Render_Settings": { - "nftName": input.nftName, + "nft_name": input.nft_name, "save_path": input.save_path, - "nftsPerBatch": input.nftsPerBatch, - "batch_to_generate": input.batchToGenerate, - "collectionSize": input.collectionSize, + "nfts_per_batch": input.nfts_per_batch, + "batch_to_generate": input.batch_to_generate, + "collection_size": input.collection_size, - "Blend_My_NFTs_Output": input.Blend_My_NFTs_Output, + "blend_my_nfts_output": input.blend_my_nfts_output, "batch_json_save_path": input.batch_json_save_path, - "nftBatch_save_path": input.nftBatch_save_path, + "nft_batch_save_path": input.nft_batch_save_path, - "enableImages": input.enableImages, - "imageFileFormat": input.imageFileFormat, + "enable_images": input.enable_images, + "image_file_format": input.image_file_format, - "enableAnimations": input.enableAnimations, - "animationFileFormat": input.animationFileFormat, + "enable_animations": input.enable_animations, + "animation_file_format": input.animation_file_format, - "enableModelsBlender": input.enableModelsBlender, - "modelFileFormat": input.modelFileFormat, + "enable_models": input.enable_models, + "model_file_format": input.model_file_format, - "enableCustomFields": input.enableCustomFields, + "enable_custom_fields": input.enable_custom_fields, - "cardanoMetaDataBool": input.cardanoMetaDataBool, - "solanaMetaDataBool": input.solanaMetaDataBool, - "erc721MetaData": input.erc721MetaData, + "cardano_metadata_bool": input.cardano_metadata_bool, + "solana_metadata_bool": input.solana_metadata_bool, + "erc721_metadata": input.erc721_metadata, "cardano_description": input.cardano_description, "solana_description": input.solana_description, "erc721_description": input.erc721_description, - "enableMaterials": input.enableMaterials, - "materialsFile": input.materialsFile, + "enable_materials": input.enable_materials, + "materials_file": input.materials_file, - "enableLogic": input.enableLogic, - "enable_Logic_Json": input.enable_Logic_Json, - "logicFile": input.logicFile, + "enable_logic": input.enable_logic, + "enable_logic_json": input.enable_logic_json, + "logic_file": input.logic_file, - "enableRarity": input.enableRarity, + "enable_rarity": input.enable_rarity, - "enableAutoShutdown": input.enableAutoShutdown, + "enable_auto_shutdown": input.enable_auto_shutdown, - "specify_timeBool": input.specify_timeBool, + "specify_time_bool": input.specify_time_bool, "hours": input.hours, "minutes": input.minutes, - "emailNotificationBool": input.emailNotificationBool, + "email_notification_bool": input.email_notification_bool, "sender_from": input.sender_from, "email_password": input.email_password, "receiver_to": input.receiver_to, - "custom_Fields": input.custom_Fields, + "custom_fields": input.custom_fields, }, }) @@ -148,23 +148,23 @@ def render_and_save_nfts(input): # If user is generating the normal way: else: - print(f"\nGenerating Batch #{input.batchToGenerate}\n") - nfts_in_batch, hierarchy, batch_dna_list = get_batch_data(input.batchToGenerate, input.batch_json_save_path) + print(f"\nGenerating Batch #{input.batch_to_generate}\n") + nfts_in_batch, hierarchy, batch_dna_list = get_batch_data(input.batch_to_generate, input.batch_json_save_path) save_generation_state(input) x = 1 - if input.enableMaterials: - materials_file = json.load(open(input.materialsFile)) + if input.enable_materials: + materials_file = json.load(open(input.materials_file)) for a in batch_dna_list: full_single_dna = list(a.keys())[0] order_num = a[full_single_dna]['order_num'] # Material handling: - if input.enableMaterials: + if input.enable_materials: single_dna, material_dna = full_single_dna.split(':') - if not input.enableMaterials: + if not input.enable_materials: single_dna = full_single_dna def match_dna_to_variant(single_dna): @@ -221,7 +221,7 @@ def render_and_save_nfts(input): metadata_material_dict = {} - if input.enableMaterials: + if input.enable_materials: material_dna_dictionary = match_material_dna_to_material(single_dna, material_dna, materials_file) for var_mat in list(material_dna_dictionary.keys()): @@ -263,7 +263,7 @@ def render_and_save_nfts(input): ) dna_dictionary = match_dna_to_variant(single_dna) - name = input.nftName + "_" + str(order_num) + name = input.nft_name + "_" + str(order_num) # Change Text Object in Scene to match DNA string: # Variables that can be used: full_single_dna, name, order_num @@ -273,7 +273,7 @@ def render_and_save_nfts(input): print(f"\n{TextColors.OK}======== Generating NFT {x}/{nfts_in_batch}: {name} ========{TextColors.RESET}") print(f"\nVariants selected:") print(f"{dna_dictionary}") - if input.enableMaterials: + if input.enable_materials: print(f"\nMaterials selected:") print(f"{material_dna_dictionary}") @@ -288,7 +288,7 @@ def render_and_save_nfts(input): time_start_2 = time.time() # Main paths for batch sub-folders: - batch_folder = os.path.join(input.nftBatch_save_path, "Batch" + str(input.batchToGenerate)) + batch_folder = os.path.join(input.nft_batch_save_path, "Batch" + str(input.batch_to_generate)) image_folder = os.path.join(batch_folder, "Images") animation_folder = os.path.join(batch_folder, "Animations") @@ -313,7 +313,7 @@ def render_and_save_nfts(input): os.remove(file_path) # Generation/Rendering: - if input.enableImages: + if input.enable_images: print(f"{TextColors.OK}-------- Image --------{TextColors.RESET}") @@ -326,7 +326,7 @@ def render_and_save_nfts(input): os.makedirs(image_folder) bpy.context.scene.render.filepath = image_path - bpy.context.scene.render.image_settings.file_format = input.imageFileFormat + bpy.context.scene.render.image_settings.file_format = input.image_file_format bpy.ops.render.render(write_still=True) # Loading Animation: @@ -341,7 +341,7 @@ def render_and_save_nfts(input): f"\n{TextColors.RESET}" ) - if input.enableAnimations: + if input.enable_animations: print(f"{TextColors.OK}-------- Animation --------{TextColors.RESET}") animation_render_time_start = time.time() @@ -352,7 +352,7 @@ def render_and_save_nfts(input): if not os.path.exists(animation_folder): os.makedirs(animation_folder) - if input.animationFileFormat == "MP4": + if input.animation_file_format =="MP4": bpy.context.scene.render.filepath = animation_path bpy.context.scene.render.image_settings.file_format = "FFMPEG" @@ -360,25 +360,25 @@ def render_and_save_nfts(input): bpy.context.scene.render.ffmpeg.codec = 'H264' bpy.ops.render.render(animation=True) - elif input.animationFileFormat == 'PNG': + elif input.animation_file_format =='PNG': if not os.path.exists(animation_path): os.makedirs(animation_path) bpy.context.scene.render.filepath = os.path.join(animation_path, name) - bpy.context.scene.render.image_settings.file_format = input.animationFileFormat + bpy.context.scene.render.image_settings.file_format = input.animation_file_format bpy.ops.render.render(animation=True) - elif input.animationFileFormat == 'TIFF': + elif input.animation_file_format =='TIFF': if not os.path.exists(animation_path): os.makedirs(animation_path) bpy.context.scene.render.filepath = os.path.join(animation_path, name) - bpy.context.scene.render.image_settings.file_format = input.animationFileFormat + bpy.context.scene.render.image_settings.file_format = input.animation_file_format bpy.ops.render.render(animation=True) else: bpy.context.scene.render.filepath = animation_path - bpy.context.scene.render.image_settings.file_format = input.animationFileFormat + bpy.context.scene.render.image_settings.file_format = input.animation_file_format bpy.ops.render.render(animation=True) # Loading Animation: @@ -393,7 +393,7 @@ def render_and_save_nfts(input): f"\n{TextColors.RESET}" ) - if input.enableModelsBlender: + if input.enable_models: print(f"{TextColors.OK}-------- 3D Model --------{TextColors.RESET}") model_generation_time_start = time.time() @@ -419,7 +419,7 @@ def render_and_save_nfts(input): # if obj.name in remove_objects: # obj.select_set(False) - if input.modelFileFormat == 'GLB': + if input.model_file_format =='GLB': check_failed_exists(f"{model_path}.glb") bpy.ops.export_scene.gltf( filepath=f"{model_path}.glb", @@ -428,7 +428,7 @@ def render_and_save_nfts(input): export_keep_originals=True, use_selection=True ) - if input.modelFileFormat == 'GLTF_SEPARATE': + if input.model_file_format =='GLTF_SEPARATE': check_failed_exists(f"{model_path}.gltf") check_failed_exists(f"{model_path}.bin") bpy.ops.export_scene.gltf( @@ -438,7 +438,7 @@ def render_and_save_nfts(input): export_keep_originals=True, use_selection=True ) - if input.modelFileFormat == 'GLTF_EMBEDDED': + if input.model_file_format =='GLTF_EMBEDDED': check_failed_exists(f"{model_path}.gltf") bpy.ops.export_scene.gltf( filepath=f"{model_path}.gltf", @@ -447,35 +447,35 @@ def render_and_save_nfts(input): export_keep_originals=True, use_selection=True ) - elif input.modelFileFormat == 'FBX': + elif input.model_file_format =='FBX': check_failed_exists(f"{model_path}.fbx") bpy.ops.export_scene.fbx( filepath=f"{model_path}.fbx", check_existing=True, use_selection=True ) - elif input.modelFileFormat == 'OBJ': + elif input.model_file_format =='OBJ': check_failed_exists(f"{model_path}.obj") bpy.ops.export_scene.obj( filepath=f"{model_path}.obj", check_existing=True, use_selection=True, ) - elif input.modelFileFormat == 'X3D': + elif input.model_file_format =='X3D': check_failed_exists(f"{model_path}.x3d") bpy.ops.export_scene.x3d( filepath=f"{model_path}.x3d", check_existing=True, use_selection=True ) - elif input.modelFileFormat == 'STL': + elif input.model_file_format =='STL': check_failed_exists(f"{model_path}.stl") bpy.ops.export_mesh.stl( filepath=f"{model_path}.stl", check_existing=True, use_selection=True ) - elif input.modelFileFormat == 'VOX': + elif input.model_file_format =='VOX': check_failed_exists(f"{model_path}.vox") bpy.ops.export_vox.some_data(filepath=f"{model_path}.vox") @@ -492,22 +492,22 @@ def render_and_save_nfts(input): ) # Generating Metadata: - if input.cardanoMetaDataBool: + if input.cardano_metadata_bool: if not os.path.exists(cardano_metadata_path): os.makedirs(cardano_metadata_path) - createCardanoMetadata( + create_cardano_metadata( name, order_num, full_single_dna, dna_dictionary, metadata_material_dict, - input.custom_Fields, - input.enableCustomFields, + input.custom_fields, + input.enable_custom_fields, input.cardano_description, cardano_metadata_path ) - if input.solanaMetaDataBool: + if input.solana_metadata_bool: if not os.path.exists(solana_metadata_path): os.makedirs(solana_metadata_path) createSolanaMetaData( @@ -516,23 +516,23 @@ def render_and_save_nfts(input): full_single_dna, dna_dictionary, metadata_material_dict, - input.custom_Fields, - input.enableCustomFields, + input.custom_fields, + input.enable_custom_fields, input.solana_description, solana_metadata_path ) - if input.erc721MetaData: + if input.erc721_metadata: if not os.path.exists(erc721_metadata_path): os.makedirs(erc721_metadata_path) - createErc721MetaData( + create_erc721_meta_data( name, order_num, full_single_dna, dna_dictionary, metadata_material_dict, - input.custom_Fields, - input.enableCustomFields, + input.custom_fields, + input.enable_custom_fields, input.erc721_description, erc721_metadata_path ) @@ -558,7 +558,7 @@ def render_and_save_nfts(input): print(f"Completed {name} render in {time.time() - time_start_2}s") - save_completed(full_single_dna, a, x, input.batch_json_save_path, input.batchToGenerate) + save_completed(full_single_dna, a, x, input.batch_json_save_path, input.batch_to_generate) x += 1 @@ -569,17 +569,17 @@ def render_and_save_nfts(input): batch_complete_time = time.time() - time_start_1 - print(f"\nAll NFTs successfully generated and sent to {input.nftBatch_save_path}" - f"\nCompleted all renders in Batch{input.batchToGenerate}.json in {batch_complete_time}s\n") + print(f"\nAll NFTs successfully generated and sent to {input.nft_batch_save_path}" + f"\nCompleted all renders in Batch{input.batch_to_generate}.json in {batch_complete_time}s\n") batch_info = {"Batch Render Time": batch_complete_time, "Number of NFTs generated in Batch": x - 1, "Average time per generation": batch_complete_time / x - 1} - batch_info_folder = os.path.join(input.nftBatch_save_path, "Batch" + str(input.batchToGenerate), "batch_info.json") + batch_info_folder = os.path.join(input.nft_batch_save_path, "Batch" + str(input.batch_to_generate), "batch_info.json") save_batch(batch_info, batch_info_folder) # Send Email that Batch is complete: - if input.emailNotificationBool: + if input.email_notification_bool: port = 465 # For SSL smtp_server = "smtp.gmail.com" sender_email = input.sender_from # Enter your address @@ -592,9 +592,9 @@ def render_and_save_nfts(input): batch_data = get_batch_data(input.failed_batch, input.batch_json_save_path) else: - batch_data = get_batch_data(input.batchToGenerate, input.batch_json_save_path) + batch_data = get_batch_data(input.batch_to_generate, input.batch_json_save_path) - batch = input.batchToGenerate + batch = input.batch_to_generate generation_time = str(datetime.timedelta(seconds=batch_complete_time)) @@ -627,11 +627,11 @@ def render_and_save_nfts(input): if plateform == "Darwin": os.system(f"shutdown /s /t {time}") - if input.enableAutoShutdown and not input.specify_timeBool: + if input.enable_auto_shutdown and not input.specify_time_bool: shutdown(0) # If user selects automatic shutdown and specify time after Batch completion - if input.enableAutoShutdown and input.specify_timeBool: + if input.enable_auto_shutdown and input.specify_time_bool: hours = (int(input.hours) / 60) / 60 minutes = int(input.minutes) / 60 total_sleep_time = hours + minutes diff --git a/main/headless_util.py b/main/headless_util.py index 6c4b283..dbe0f6e 100644 --- a/main/headless_util.py +++ b/main/headless_util.py @@ -5,7 +5,8 @@ import sys import argparse -def getPythonArgs(): + +def get_python_args(): argv = sys.argv @@ -15,7 +16,7 @@ def getPythonArgs(): argv = argv[argv.index("--") + 1:] # get all args after "--" usage_text = ( - "Run Blend_My_NFTs headlessly from the command line\n" + "Run Blend_My_NFTs heedlessly from the command line\n" "usage:\n" "blender -background --python -- --config-file " ) @@ -64,4 +65,4 @@ def getPythonArgs(): help="Overwrite the logic file path in the config file" ) - return (parser.parse_args(argv), parser) \ No newline at end of file + return parser.parse_args(argv), parser diff --git a/main/helpers.py b/main/helpers.py index e606bca..870adfa 100644 --- a/main/helpers.py +++ b/main/helpers.py @@ -408,7 +408,7 @@ def raise_error_num_batches_greater_then(num_batches): # Raise Warnings: def raise_warning_max_nfts(nfts_per_batch, collection_size): """ - Prints warning if nftsPerBatch is greater than collectionSize. + Prints warning if nfts_per_batch is greater than collection_size. """ if nfts_per_batch > collection_size: @@ -421,7 +421,7 @@ def raise_warning_max_nfts(nfts_per_batch, collection_size): def raise_warning_collection_size(dna_list, collection_size): """ - Prints warning if BMNFTs cannot generate requested number of NFTs from a given collectionSize. + Prints warning if BMNFTs cannot generate requested number of NFTs from a given collection_size. """ if len(dna_list) < collection_size: diff --git a/main/intermediate.py b/main/intermediate.py index 323bf56..ae0eece 100644 --- a/main/intermediate.py +++ b/main/intermediate.py @@ -1,21 +1,23 @@ -import json import bpy +import json from main import dna_generator, exporter +# TODO: migrate this code to the exporter.py to simplify render process into one file. -def send_To_Record_JSON(input, reverse_order=False): - if input.enableLogic: - if input.enable_Logic_Json and input.logicFile: - input.logicFile = json.load(open(input.logicFile)) - if input.enable_Logic_Json and not input.logicFile: +def send_to_record(input, reverse_order=False): + if input.enable_logic: + if input.enable_logic_json and input.logic_file: + input.logic_file = json.load(open(input.logic_file)) + + if input.enable_logic_json and not input.logic_file: print({'ERROR'}, f"No Logic.json file path set. Please set the file path to your Logic.json file.") - if not input.enable_Logic_Json: + if not input.enable_logic_json: scn = bpy.context.scene if reverse_order: - input.logicFile = {} + input.logic_file = {} num = 1 for i in range(scn.logic_fields_index, -1, -1): item = scn.logic_fields[i] @@ -23,20 +25,20 @@ def send_To_Record_JSON(input, reverse_order=False): item_list1 = item.item_list1 rule_type = item.rule_type item_list2 = item.item_list2 - input.logicFile[f"Rule-{num}"] = { + input.logic_file[f"Rule-{num}"] = { "IF": item_list1.split(','), rule_type: item_list2.split(',') } print(rule_type) num += 1 else: - input.logicFile = {} + input.logic_file = {} num = 1 for item in scn.logic_fields: item_list1 = item.item_list1 rule_type = item.rule_type item_list2 = item.item_list2 - input.logicFile[f"Rule-{num}"] = { + input.logic_file[f"Rule-{num}"] = { "IF": item_list1.split(','), rule_type: item_list2.split(',') } @@ -44,37 +46,42 @@ def send_To_Record_JSON(input, reverse_order=False): num += 1 - dna_generator.send_to_record(input.collectionSize, - input.nftsPerBatch, - input.save_path, - input.enableRarity, - input.enableLogic, - input.logicFile, - input.enableMaterials, - input.materialsFile, - input.Blend_My_NFTs_Output, - input.batch_json_save_path, - input.enable_debug, - ) + dna_generator.send_to_record( + input.collection_size, + input.nfts_per_batch, + input.save_path, + input.enable_rarity, + input.enable_logic, + input.logic_file, + input.enable_materials, + input.materials_file, + input.blend_my_nfts_output, + input.batch_json_save_path, + input.enable_debug, + ) -def render_and_save_NFTs(input, reverse_order=False): - if input.enableCustomFields: +def render_and_save_nfts(input, reverse_order=False): + if input.enable_custom_fields: scn = bpy.context.scene if reverse_order: for i in range(scn.custom_metadata_fields_index, -1, -1): item = scn.custom_metadata_fields[i] - if item.field_name in list(input.custom_Fields.keys()): + if item.field_name in list(input.custom_fields.keys()): raise ValueError( - f"A duplicate of '{item.field_name}' was found. Please ensure all Custom Metadata field Names are unique.") + f"A duplicate of '{item.field_name}' was found. Please ensure all Custom Metadata field Names " + f"are unique." + ) else: - input.custom_Fields[item.field_name] = item.field_value + input.custom_fields[item.field_name] = item.field_value else: for item in scn.custom_metadata_fields: - if item.field_name in list(input.custom_Fields.keys()): + if item.field_name in list(input.custom_fields.keys()): raise ValueError( - f"A duplicate of '{item.field_name}' was found. Please ensure all Custom Metadata field Names are unique.") + f"A duplicate of '{item.field_name}' was found. Please ensure all Custom Metadata field Names " + f"are unique." + ) else: - input.custom_Fields[item.field_name] = item.field_value + input.custom_fields[item.field_name] = item.field_value - Exporter.render_and_save_nfts(input) + exporter.render_and_save_nfts(input) diff --git a/main/logic.py b/main/logic.py index d76f6a4..7f2b0de 100644 --- a/main/logic.py +++ b/main/logic.py @@ -1,19 +1,19 @@ # Purpose: -# The purpose of this file is to add logic and rules to the DNA that are sent to the NFTRecord.json file in dna_generator.py +# The purpose of this file is to add logic and rules to the DNA that are sent to the NFTRecord.json file in +# dna_generator.py -import bpy import random import collections -from .helpers import TextColors, removeList, remove_file_by_extension, save_result +from .helpers import TextColors -def reconstructDNA(deconstructedDNA): - reconstructed_DNA = "" - for a in deconstructedDNA: +def reconstruct_dna(deconstructed_dna): + reconstructed_dna = "" + for a in deconstructed_dna: num = "-" + str(a) - reconstructed_DNA += num - return ''.join(reconstructed_DNA.split('-', 1)) + reconstructed_dna += num + return ''.join(reconstructed_dna.split('-', 1)) def get_var_info(variant, hierarchy): @@ -33,11 +33,11 @@ def get_var_info(variant, hierarchy): return [name, order_number, rarity_number, attribute, attribute_index] # list of Var info sent back -def apply_rules_to_dna(hierarchy, deconstructed_DNA, if_dict, result_dict, result_dict_type, enableRarity): - # Check if Variants in if_dict are in deconstructed_DNA, if so return if_list_selected = True: +def apply_rules_to_dna(hierarchy, deconstructed_dna, if_dict, result_dict, result_dict_type, enable_rarity): + # Check if Variants in if_dict are in deconstructed_dna, if so return if_list_selected = True: if_list_selected = False - for a in deconstructed_DNA: - attribute_index = deconstructed_DNA.index(a) + for a in deconstructed_dna: + attribute_index = deconstructed_dna.index(a) attribute = list(hierarchy.keys())[attribute_index] for b in hierarchy[attribute]: @@ -49,23 +49,23 @@ def apply_rules_to_dna(hierarchy, deconstructed_DNA, if_dict, result_dict, resul if_list_selected = True # Apply changes in accordance to Variants in 'result_dict' and 'if_list_selected' bool above: - for a in deconstructed_DNA: - attribute_index = deconstructed_DNA.index(a) + for a in deconstructed_dna: + attribute_index = deconstructed_dna.index(a) attribute = list(hierarchy.keys())[attribute_index] if attribute in result_dict: # Check if Attribute from DNA is in 'result_dict' # If 'a' is a full Attribute and Variants in if_dict not selected, set 'a' to empty (0): if list(result_dict[attribute].keys()) == list(hierarchy[attribute].keys()) and not if_list_selected: - deconstructed_DNA[attribute_index] = "0" + deconstructed_dna[attribute_index] = "0" # If 'a' is a full Attribute and result_dict_type = "NOT", set 'a' to empty (0): if list(result_dict[attribute].keys()) == list( hierarchy[attribute].keys()) and if_list_selected and result_dict_type == "NOT": - deconstructed_DNA[attribute_index] = "0" + deconstructed_dna[attribute_index] = "0" - # If Variants in if_dict are selected, set each attribute in 'result_dict' to a random or rarity selected Variant from - # 'result_dict[attribute]' variant_list: + # If Variants in if_dict are selected, set each attribute in 'result_dict' to a random or rarity selected Variant + # from 'result_dict[attribute]' variant_list: if if_list_selected: # Invert 'items_returned' if 'NOT' rule is selected: @@ -91,60 +91,60 @@ def apply_rules_to_dna(hierarchy, deconstructed_DNA, if_dict, result_dict, resul if attribute in result_dict: # Check if Attribute from DNA is in 'then_dict' - number_List_Of_i = [] - rarity_List_Of_i = [] - ifZeroBool = None - variantNum = None + number_list_of_i = [] + rarity_list_of_i = [] + if_zero_bool = None + variant_num = None for b in variant_list: number = b.split("_")[1] rarity = b.split("_")[2] - number_List_Of_i.append(int(number)) - rarity_List_Of_i.append(float(rarity)) + number_list_of_i.append(int(number)) + rarity_list_of_i.append(float(rarity)) - for b in rarity_List_Of_i: + for b in rarity_list_of_i: if b == 0: - ifZeroBool = True + if_zero_bool = True elif b != 0: - ifZeroBool = False + if_zero_bool = False - if enableRarity: + if enable_rarity: try: - if ifZeroBool: - variantNum = random.choices(number_List_Of_i, k=1) - elif not ifZeroBool: - variantNum = random.choices(number_List_Of_i, weights=rarity_List_Of_i, k=1) + if if_zero_bool: + variant_num = random.choices(number_list_of_i, k=1) + elif not if_zero_bool: + variant_num = random.choices(number_list_of_i, weights=rarity_list_of_i, k=1) except IndexError: raise IndexError( f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n" - f"An issue was found within the Attribute collection '{a}'. For more information on Blend_My_NFTs compatible scenes, " - f"see:\n{TextColors.RESET}" + f"An issue was found within the Attribute collection '{a}'. For more information on " + f"Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}" f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n" ) else: try: - variantNum = random.choices(number_List_Of_i, k=1) + variant_num = random.choices(number_list_of_i, k=1) except IndexError: raise IndexError( f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n" - f"An issue was found within the Attribute collection '{a}'. For more information on Blend_My_NFTs compatible scenes, " - f"see:\n{TextColors.RESET}" + f"An issue was found within the Attribute collection '{a}'. For more information on " + f"Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}" f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n" ) - deconstructed_DNA[int(attribute_index)] = str(variantNum[0]) + deconstructed_dna[int(attribute_index)] = str(variant_num[0]) - return deconstructed_DNA + return deconstructed_dna -def get_rule_break_type(hierarchy, deconstructed_DNA, if_dict, result_dict, result_dict_type): - # Check if Variants in 'if_dict' found in deconstructed_DNA: - if_bool = False # True if Variant in 'deconstructed_DNA' found in 'if_dict' +def get_rule_break_type(hierarchy, deconstructed_dna, if_dict, result_dict, result_dict_type): + # Check if Variants in 'if_dict' found in deconstructed_dna: + if_bool = False # True if Variant in 'deconstructed_dna' found in 'if_dict' for a in if_dict: # Attribute in 'if_dict' for b in if_dict[a]: # Variant in if_dict[Attribute] var_order_num = str(if_dict[a][b][1]) # Order number of 'b' (Variant) dna_order_num = str( - deconstructed_DNA[if_dict[a][b][4]]) # Order Number of 'b's attribute in deconstructed_DNA + deconstructed_dna[if_dict[a][b][4]]) # Order Number of 'b's attribute in deconstructed_dna if var_order_num == dna_order_num: # If DNA selected Variants found inside IF list variants: if_bool = True @@ -153,14 +153,14 @@ def get_rule_break_type(hierarchy, deconstructed_DNA, if_dict, result_dict, resu continue break - # Check if Variants in 'result_dict' found in deconstructed_DNA: + # Check if Variants in 'result_dict' found in deconstructed_dna: full_att_bool = False - result_bool = False # True if Variant in 'deconstructed_DNA' found in 'result_dict' + result_bool = False # True if Variant in 'deconstructed_dna' found in 'result_dict' for a in result_dict: # Attribute in 'result_dict' for b in result_dict[a]: # Variant in if_dict[Attribute] var_order_num = str(result_dict[a][b][1]) # Order number of 'b' (Variant) dna_order_num = str( - deconstructed_DNA[result_dict[a][b][4]]) # Order Number of 'b's attribute in deconstructed_DNA + deconstructed_dna[result_dict[a][b][4]]) # Order Number of 'b's attribute in deconstructed_dna if var_order_num == dna_order_num: # If DNA selected Variants found inside THEN list variants: if list(result_dict[a].keys()) == list(hierarchy[a].keys()): full_att_bool = True @@ -173,20 +173,20 @@ def get_rule_break_type(hierarchy, deconstructed_DNA, if_dict, result_dict, resu # Rule Bool return summary: violates_rule = False - # If Variants in 'if_dict' found in deconstructed_DNA and Variants in 'result_dict' not found in deconstructed_DNA: + # If Variants in 'if_dict' found in deconstructed_dna and Variants in 'result_dict' not found in deconstructed_dna: if if_bool and not result_bool: violates_rule = True elif if_bool and result_bool and result_dict_type == "NOT": violates_rule = True - # If Variants in 'if_dict' not found in deconstructed_DNA, and 'result_dict' variants are found in deconstructed_DNA, - # and they are a part of a full Attribute in 'then_dict' + # If Variants in 'if_dict' not found in deconstructed_dna, and 'result_dict' variants are found in + # deconstructed_dna, and they are a part of a full Attribute in 'then_dict' elif not if_bool and result_bool and full_att_bool: violates_rule = True - # If Variants in 'if_dict' not found in deconstructed_DNA, but Variants in 'then_dict' are found in deconstructed_DNA, - # and don't make up a full Attribute: + # If Variants in 'if_dict' not found in deconstructed_dna, but Variants in 'then_dict' are found in + # deconstructed_dna, and don't make up a full Attribute: # elif not if_bool and result_bool and not full_att_bool: # violates_rule = False @@ -252,41 +252,50 @@ def create_dicts(hierarchy, rule_list_items, result_dict_type): return dict(items_returned) -def logicafyDNAsingle(hierarchy, singleDNA, logicFile, enableRarity, enableMaterials): - deconstructed_DNA = singleDNA.split("-") - didReconstruct = True - originalDNA = str(singleDNA) +def logicafy_dna_single(hierarchy, single_dna, logic_file, enable_rarity): + deconstructed_dna = single_dna.split("-") + did_reconstruct = True + original_dna = str(single_dna) - while didReconstruct: - didReconstruct = False - for rule in logicFile: + while did_reconstruct: + did_reconstruct = False + for rule in logic_file: # Items from 'IF' key for a given rule - if_dict = create_dicts(hierarchy, logicFile[rule]["IF"], "IF") + if_dict = create_dicts(hierarchy, logic_file[rule]["IF"], "IF") result_dict_type = "" - if "THEN" in logicFile[rule]: + if "THEN" in logic_file[rule]: result_dict_type = "THEN" - if "NOT" in logicFile[rule]: + if "NOT" in logic_file[rule]: result_dict_type = "NOT" - result_dict = create_dicts(hierarchy, logicFile[rule][result_dict_type], result_dict_type) + result_dict = create_dicts(hierarchy, logic_file[rule][result_dict_type], result_dict_type) # Change 'then_bool' to 'result_bool' - violates_rule, if_bool, then_bool, full_att_bool = get_rule_break_type(hierarchy, deconstructed_DNA, - if_dict, result_dict, - result_dict_type) + violates_rule, if_bool, then_bool, full_att_bool = get_rule_break_type( + hierarchy, + deconstructed_dna, + if_dict, + result_dict, + result_dict_type, + ) if violates_rule: - # print(f"======={deconstructed_DNA} VIOLATES RULE======") + # print(f"======={deconstructed_dna} VIOLATES RULE======") - deconstructed_DNA = apply_rules_to_dna( - hierarchy, deconstructed_DNA, if_dict, result_dict, result_dict_type, enableRarity + deconstructed_dna = apply_rules_to_dna( + hierarchy, + deconstructed_dna, + if_dict, + result_dict, + result_dict_type, + enable_rarity ) - newDNA = reconstructDNA(deconstructed_DNA) - if newDNA != originalDNA: - originalDNA = str(newDNA) - didReconstruct = True + new_dna = reconstruct_dna(deconstructed_dna) + if new_dna != original_dna: + original_dna = str(new_dna) + did_reconstruct = True break - return str(reconstructDNA(deconstructed_DNA)) + return str(reconstruct_dna(deconstructed_dna)) diff --git a/main/material_generator.py b/main/material_generator.py index e0eda71..5dc2d89 100644 --- a/main/material_generator.py +++ b/main/material_generator.py @@ -3,62 +3,61 @@ # also specified in the .json file. The Materialized DNA is then returned in the following format: 1-1-1:1-1-1 # Where the numbers right of the ":" are the material numbers applied to the respective Variants to the left of the ":" -import bpy - import json import random from .helpers import TextColors -def select_material(materialList, variant, enableRarity): +def select_material(material_list, variant, enable_rarity): """Selects a material from a passed material list. """ - material_List_Of_i = [] # List of Material names instead of order numbers - rarity_List_Of_i = [] - ifZeroBool = None + material_list_of_i = [] # List of Material names instead of order numbers + rarity_list_of_i = [] + if_zero_bool = None - for material in materialList: + for material in material_list: # Material Order Number comes from index in the Material List in materials.json for a given Variant. - # material_order_num = list(materialList.keys()).index(material) + # material_order_num = list(material_list.keys()).index(material) - material_List_Of_i.append(material) + material_list_of_i.append(material) - material_rarity_percent = materialList[material] - rarity_List_Of_i.append(float(material_rarity_percent)) + material_rarity_percent = material_list[material] + rarity_list_of_i.append(float(material_rarity_percent)) - # print(f"MATERIAL_LIST_OF_I:{material_List_Of_i}") - # print(f"RARITY_LIST_OF_I:{rarity_List_Of_i}") + # print(f"MATERIAL_LIST_OF_I:{material_list_of_i}") + # print(f"RARITY_LIST_OF_I:{rarity_list_of_i}") - for b in rarity_List_Of_i: + for b in rarity_list_of_i: if b == 0: - ifZeroBool = True + if_zero_bool = True elif b != 0: - ifZeroBool = False + if_zero_bool = False - if enableRarity: + if enable_rarity: try: - if ifZeroBool: - selected_material = random.choices(material_List_Of_i, k=1) - elif not ifZeroBool: - selected_material = random.choices(material_List_Of_i, weights=rarity_List_Of_i, k=1) + if if_zero_bool: + selected_material = random.choices(material_list_of_i, k=1) + elif not if_zero_bool: + selected_material = random.choices(material_list_of_i, weights=rarity_list_of_i, k=1) except IndexError: raise IndexError( f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n" - f"An issue was found within the Material List of the Variant collection '{variant}'. For more information on Blend_My_NFTs compatible scenes, " - f"see:\n{TextColors.RESET}" + f"An issue was found within the Material List of the Variant collection '{variant}'. For more " + f"information on Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}" f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n" ) else: try: - selected_material = random.choices(material_List_Of_i, k=1) + selected_material = random.choices(material_list_of_i, k=1) except IndexError: raise IndexError( f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n" - f"An issue was found within the Material List of the Variant collection '{variant}'. For more information on Blend_My_NFTs compatible scenes, " - f"see:\n{TextColors.RESET}" + f"An issue was found within the Material List of the Variant collection '{variant}'. For more " + f"information on Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}" f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n" ) - return selected_material[0], materialList + return selected_material[0], material_list + def get_variant_att_index(variant, hierarchy): variant_attribute = None @@ -72,26 +71,28 @@ def get_variant_att_index(variant, hierarchy): variant_order_num = variant.split("_")[1] return attribute_index, variant_order_num -def match_DNA_to_Variant(hierarchy, singleDNA): + +def match_dna_to_variant(hierarchy, single_dna): """ Matches each DNA number separated by "-" to its attribute, then its variant. """ - listAttributes = list(hierarchy.keys()) - listDnaDecunstructed = singleDNA.split('-') - dnaDictionary = {} + list_attributes = list(hierarchy.keys()) + list_dna_decunstructed = single_dna.split('-') + dna_dictionary = {} - for i, j in zip(listAttributes, listDnaDecunstructed): - dnaDictionary[i] = j + for i, j in zip(list_attributes, list_dna_decunstructed): + dna_dictionary[i] = j - for x in dnaDictionary: + for x in dna_dictionary: for k in hierarchy[x]: - kNum = hierarchy[x][k]["number"] - if kNum == dnaDictionary[x]: - dnaDictionary.update({x: k}) - return dnaDictionary + k_num = hierarchy[x][k]["number"] + if k_num == dna_dictionary[x]: + dna_dictionary.update({x: k}) + return dna_dictionary -def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity): + +def apply_materials(hierarchy, single_dna, materials_file, enable_rarity): """ DNA with applied material example: "1-1:1-1" : @@ -99,20 +100,23 @@ def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity): list in the Variant_Material.json file. """ - singleDNADict = match_DNA_to_Variant(hierarchy, singleDNA) - materialsFile = json.load(open(materialsFile)) - deconstructed_MaterialDNA = {} + single_dna_dict = match_dna_to_variant(hierarchy, single_dna) + materials_file = json.load(open(materials_file)) + deconstructed_material_dna = {} - for a in singleDNADict: + for a in single_dna_dict: complete = False - for b in materialsFile: - if singleDNADict[a] == b: - material_name, materialList, = select_material(materialsFile[b]['Material List'], b, enableRarity) - material_order_num = list(materialList.keys()).index(material_name) # Gets the Order Number of the Material - deconstructed_MaterialDNA[a] = str(material_order_num + 1) + for b in materials_file: + if single_dna_dict[a] == b: + material_name, material_list, = select_material(materials_file[b]['Material List'], b, enable_rarity) + + # Gets the Order Number of the Material + material_order_num = list(material_list.keys()).index(material_name) + + deconstructed_material_dna[a] = str(material_order_num + 1) complete = True if not complete: - deconstructed_MaterialDNA[a] = "0" + deconstructed_material_dna[a] = "0" # This section is now incorrect and needs updating: @@ -121,14 +125,14 @@ def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity): # Attribute 'B' = 1, 'C' = 2, 'D' = 3, etc. For each pair you want to equal another, add its number it to this list: # synced_material_attributes = [1, 2] # - # first_mat = deconstructed_MaterialDNA[synced_material_attributes[0]] + # first_mat = deconstructed_material_dna[synced_material_attributes[0]] # for i in synced_material_attributes: - # deconstructed_MaterialDNA[i] = first_mat + # deconstructed_material_dna[i] = first_mat - material_DNA = "" - for a in deconstructed_MaterialDNA: - num = "-" + str(deconstructed_MaterialDNA[a]) - material_DNA += num - material_DNA = ''.join(material_DNA.split('-', 1)) + material_dna = "" + for a in deconstructed_material_dna: + num = "-" + str(deconstructed_material_dna[a]) + material_dna += num + material_dna = ''.join(material_dna.split('-', 1)) - return f"{singleDNA}:{material_DNA}" \ No newline at end of file + return f"{single_dna}:{material_dna}" diff --git a/main/metadata_templates.py b/main/metadata_templates.py index 2d7b8ca..1aa6210 100644 --- a/main/metadata_templates.py +++ b/main/metadata_templates.py @@ -3,26 +3,37 @@ # https://discord.gg/QTT7dzcuVs # Purpose: -# This file returns the specified meta data format to the exporter.py for a given NFT DNA. +# This file returns the specified metadata format to the exporter.py for a given NFT DNA. -import bpy import os import json -def sendMetaDataToJson(metaDataDict, save_path, file_name): - jsonMetaData = json.dumps(metaDataDict, indent=1, ensure_ascii=True) - with open(os.path.join(save_path, f"{file_name}.json"), 'w') as outfile: - outfile.write(jsonMetaData + '\n') -def stripNums(variant): +def send_metadata_to_json(meta_data_dict, save_path, file_name): + json_metadata = json.dumps(meta_data_dict, indent=1, ensure_ascii=True) + with open(os.path.join(save_path, f"{file_name}.json"), 'w') as outfile: + outfile.write(json_metadata + '\n') + + +def strip_nums(variant): variant = str(variant).split('_')[0] return variant -# Cardano Template -def createCardanoMetadata(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes, - custom_Fields, enableCustomFields, cardano_description, cardanoMetadataPath): - metaDataDictCardano = {"721": { +# Cardano Template +def create_cardano_metadata( + name, + order_num, + nft_dna, + nft_variants, + material_attributes, + custom_fields, + enable_custom_fields, + cardano_description, + cardano_metadata_path +): + + meta_data_dict_cardano = {"721": { "": { name: { "name": name, @@ -35,73 +46,107 @@ def createCardanoMetadata(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attri }} # Variants and Attributes: - for i in NFT_Variants: - metaDataDictCardano["721"][""][name][i] = stripNums(NFT_Variants[i]) + for i in nft_variants: + meta_data_dict_cardano["721"][""][name][i] = strip_nums(nft_variants[i]) # Material Variants and Attributes: - for i in Material_Attributes: - metaDataDictCardano["721"][""][name][i] = Material_Attributes[i] + for i in material_attributes: + meta_data_dict_cardano["721"][""][name][i] = material_attributes[i] # Custom Fields: - if enableCustomFields: - for i in custom_Fields: - metaDataDictCardano["721"][""][name][i] = custom_Fields[i] + if enable_custom_fields: + for i in custom_fields: + meta_data_dict_cardano["721"][""][name][i] = custom_fields[i] - sendMetaDataToJson(metaDataDictCardano, cardanoMetadataPath, name) + send_metadata_to_json( + meta_data_dict_cardano, + cardano_metadata_path, + name + ) # Solana Template -def createSolanaMetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes, custom_Fields, enableCustomFields, - solana_description, solanaMetadataPath): - metaDataDictSolana = {"name": name, "symbol": "", "description": solana_description, "seller_fee_basis_points": None, - "image": "", "animation_url": "", "external_url": ""} +def createSolanaMetaData( + name, + order_num, + nft_dna, + nft_variants, + material_attributes, + custom_fields, + enable_custom_fields, + solana_description, + solana_metadata_path +): + metadata_dict_solana = { + "name": name, + "symbol": "", + "description": solana_description, + "seller_fee_basis_points": None, + "image": "", + "animation_url": "", + "external_url": "" + } attributes = [] # Variant and Attributes: - for i in NFT_Variants: + for i in nft_variants: dictionary = { "trait_type": i, - "value": stripNums(NFT_Variants[i]) + "value": strip_nums(nft_variants[i]) } attributes.append(dictionary) # Material Variants and Attributes: - for i in Material_Attributes: + for i in material_attributes: dictionary = { "trait_type": i, - "value": Material_Attributes[i] + "value": material_attributes[i] } attributes.append(dictionary) # Custom Fields: - if enableCustomFields: - for i in custom_Fields: + if enable_custom_fields: + for i in custom_fields: dictionary = { "trait_type": i, - "value": custom_Fields[i] + "value": custom_fields[i] } attributes.append(dictionary) - metaDataDictSolana["attributes"] = attributes - metaDataDictSolana["collection"] = { + metadata_dict_solana["attributes"] = attributes + metadata_dict_solana["collection"] = { "name": "", "family": "" } - metaDataDictSolana["properties"] = { + metadata_dict_solana["properties"] = { "files": [{"uri": "", "type": ""}], "category": "", "creators": [{"address": "", "share": None}] } - sendMetaDataToJson(metaDataDictSolana, solanaMetadataPath, name) + send_metadata_to_json( + metadata_dict_solana, + solana_metadata_path, + name + ) # ERC721 Template -def createErc721MetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes, custom_Fields, enableCustomFields, - erc721_description, erc721MetadataPath): - metaDataDictErc721 = { +def create_erc721_meta_data( + name, + order_num, + nft_dna, + nft_variants, + material_attributes, + custom_fields, + enable_custom_fields, + erc721_description, + erc721_metadata_path +): + + metadata_dict_erc721 = { "name": name, "description": erc721_description, "image": "", @@ -111,33 +156,36 @@ def createErc721MetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attrib attributes = [] # Variants and Attributes: - for i in NFT_Variants: + for i in nft_variants: dictionary = { "trait_type": i, - "value": stripNums(NFT_Variants[i]) + "value": strip_nums(nft_variants[i]) } attributes.append(dictionary) # Material Variants and Attributes: - for i in Material_Attributes: + for i in material_attributes: dictionary = { "trait_type": i, - "value": Material_Attributes[i] + "value": material_attributes[i] } attributes.append(dictionary) # Custom Fields: - if enableCustomFields: - for i in custom_Fields: + if enable_custom_fields: + for i in custom_fields: dictionary = { "trait_type": i, - "value": custom_Fields[i] + "value": custom_fields[i] } attributes.append(dictionary) - metaDataDictErc721["attributes"] = attributes - - sendMetaDataToJson(metaDataDictErc721, erc721MetadataPath, name) + metadata_dict_erc721["attributes"] = attributes + send_metadata_to_json( + metadata_dict_erc721, + erc721_metadata_path, + name + ) diff --git a/main/refactorer.py b/main/refactorer.py index d842e05..b29f1c7 100644 --- a/main/refactorer.py +++ b/main/refactorer.py @@ -1,48 +1,46 @@ # Purpose: # This file goes through all batches, renames, and sorts all nft files to a Complete_Collection folder in Blend_My_NFTs -import bpy import os import json import shutil -from .helpers import TextColors, removeList, remove_file_by_extension +from .helpers import remove_file_by_extension -def reformatNFTCollection(refactor_panel_input): - completeCollPath = os.path.join(refactor_panel_input.save_path, "Blend_My_NFTs Output", "Complete_Collection") +def reformat_nft_collection(refactor_panel_input): + complete_coll_path = os.path.join(refactor_panel_input.save_path, "Blend_My_NFTs Output", "Complete_Collection") - if not os.path.exists(completeCollPath): - os.mkdir(completeCollPath) + if not os.path.exists(complete_coll_path): + os.mkdir(complete_coll_path) - batchListDirty = os.listdir(refactor_panel_input.nftBatch_save_path) - batchList = remove_file_by_extension(batchListDirty) + batch_list_dirty = os.listdir(refactor_panel_input.nft_batch_save_path) + batch_list = remove_file_by_extension(batch_list_dirty) collection_info = {"Total Time": 0} - for folder in batchList: - batch_info = json.load(open(os.path.join(refactor_panel_input.nftBatch_save_path, folder, "batch_info.json"))) + for folder in batch_list: + batch_info = json.load(open(os.path.join(refactor_panel_input.nft_batch_save_path, folder, "batch_info.json"))) collection_info[os.path.basename(folder)] = batch_info collection_info["Total Time"] = collection_info["Total Time"] + batch_info["Batch Render Time"] - fileListDirty = os.listdir(os.path.join(refactor_panel_input.nftBatch_save_path, folder)) - filelist = remove_file_by_extension(fileListDirty) + file_list_dirty = os.listdir(os.path.join(refactor_panel_input.nft_batch_save_path, folder)) + filelist = remove_file_by_extension(file_list_dirty) for mediaTypeFolder in filelist: if mediaTypeFolder != "batch_info.json": - mediaTypeFolderDir = os.path.join(refactor_panel_input.nftBatch_save_path, folder, mediaTypeFolder) + media_type_folder_dir = os.path.join(refactor_panel_input.nft_batch_save_path, folder, mediaTypeFolder) - for i in os.listdir(mediaTypeFolderDir): - destination = os.path.join(completeCollPath, mediaTypeFolder) + for i in os.listdir(media_type_folder_dir): + destination = os.path.join(complete_coll_path, mediaTypeFolder) if not os.path.exists(destination): os.makedirs(destination) - shutil.move(os.path.join(mediaTypeFolderDir, i), destination) + shutil.move(os.path.join(media_type_folder_dir, i), destination) collection_info = json.dumps(collection_info, indent=1, ensure_ascii=True) - with open(os.path.join(completeCollPath, "collection_info.json"), 'w') as outfile: + with open(os.path.join(complete_coll_path, "collection_info.json"), 'w') as outfile: outfile.write(collection_info + '\n') print(f"All NFT files stored and sorted to the Complete_Collection folder in {refactor_panel_input.save_path}") - shutil.rmtree(refactor_panel_input.nftBatch_save_path) - + shutil.rmtree(refactor_panel_input.nft_batch_save_path)