kopia lustrzana https://github.com/torrinworx/Blend_My_NFTs
Pep8 formatting and renaming key variables
rodzic
7c389e15df
commit
57ec4b1ac1
|
@ -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
|
||||
|
|
|
@ -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"""
|
||||
|
|
492
__init__.py
492
__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():
|
||||
|
|
|
@ -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
|
||||
"""
|
||||
|
||||
|
|
152
main/exporter.py
152
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
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
import sys
|
||||
import argparse
|
||||
|
||||
def getPythonArgs():
|
||||
|
||||
def get_python_args():
|
||||
|
||||
argv = sys.argv
|
||||
|
||||
|
@ -15,7 +16,7 @@ def getPythonArgs():
|
|||
argv = argv[argv.index("--") + 1:] # get all args after "--"
|
||||
|
||||
usage_text = (
|
||||
"Run Blend_My_NFTs headlessly from the command line\n"
|
||||
"Run Blend_My_NFTs heedlessly from the command line\n"
|
||||
"usage:\n"
|
||||
"blender -background --python <Path to BMNFTs __init__.py> -- --config-file <path to config file>"
|
||||
)
|
||||
|
@ -64,4 +65,4 @@ def getPythonArgs():
|
|||
help="Overwrite the logic file path in the config file"
|
||||
)
|
||||
|
||||
return (parser.parse_args(argv), parser)
|
||||
return parser.parse_args(argv), parser
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
155
main/logic.py
155
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))
|
||||
|
|
|
@ -3,62 +3,61 @@
|
|||
# also specified in the .json file. The Materialized DNA is then returned in the following format: 1-1-1:1-1-1
|
||||
# Where the numbers right of the ":" are the material numbers applied to the respective Variants to the left of the ":"
|
||||
|
||||
import bpy
|
||||
|
||||
import json
|
||||
import random
|
||||
from .helpers import TextColors
|
||||
|
||||
|
||||
def select_material(materialList, variant, enableRarity):
|
||||
def select_material(material_list, variant, enable_rarity):
|
||||
"""Selects a material from a passed material list. """
|
||||
material_List_Of_i = [] # List of Material names instead of order numbers
|
||||
rarity_List_Of_i = []
|
||||
ifZeroBool = None
|
||||
material_list_of_i = [] # List of Material names instead of order numbers
|
||||
rarity_list_of_i = []
|
||||
if_zero_bool = None
|
||||
|
||||
for material in materialList:
|
||||
for material in material_list:
|
||||
# Material Order Number comes from index in the Material List in materials.json for a given Variant.
|
||||
# material_order_num = list(materialList.keys()).index(material)
|
||||
# material_order_num = list(material_list.keys()).index(material)
|
||||
|
||||
material_List_Of_i.append(material)
|
||||
material_list_of_i.append(material)
|
||||
|
||||
material_rarity_percent = materialList[material]
|
||||
rarity_List_Of_i.append(float(material_rarity_percent))
|
||||
material_rarity_percent = material_list[material]
|
||||
rarity_list_of_i.append(float(material_rarity_percent))
|
||||
|
||||
# print(f"MATERIAL_LIST_OF_I:{material_List_Of_i}")
|
||||
# print(f"RARITY_LIST_OF_I:{rarity_List_Of_i}")
|
||||
# print(f"MATERIAL_LIST_OF_I:{material_list_of_i}")
|
||||
# print(f"RARITY_LIST_OF_I:{rarity_list_of_i}")
|
||||
|
||||
for b in rarity_List_Of_i:
|
||||
for b in rarity_list_of_i:
|
||||
if b == 0:
|
||||
ifZeroBool = True
|
||||
if_zero_bool = True
|
||||
elif b != 0:
|
||||
ifZeroBool = False
|
||||
if_zero_bool = False
|
||||
|
||||
if enableRarity:
|
||||
if enable_rarity:
|
||||
try:
|
||||
if ifZeroBool:
|
||||
selected_material = random.choices(material_List_Of_i, k=1)
|
||||
elif not ifZeroBool:
|
||||
selected_material = random.choices(material_List_Of_i, weights=rarity_List_Of_i, k=1)
|
||||
if if_zero_bool:
|
||||
selected_material = random.choices(material_list_of_i, k=1)
|
||||
elif not if_zero_bool:
|
||||
selected_material = random.choices(material_list_of_i, weights=rarity_list_of_i, k=1)
|
||||
except IndexError:
|
||||
raise IndexError(
|
||||
f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n"
|
||||
f"An issue was found within the Material List of the Variant collection '{variant}'. For more information on Blend_My_NFTs compatible scenes, "
|
||||
f"see:\n{TextColors.RESET}"
|
||||
f"An issue was found within the Material List of the Variant collection '{variant}'. For more "
|
||||
f"information on Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}"
|
||||
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
|
||||
)
|
||||
else:
|
||||
try:
|
||||
selected_material = random.choices(material_List_Of_i, k=1)
|
||||
selected_material = random.choices(material_list_of_i, k=1)
|
||||
except IndexError:
|
||||
raise IndexError(
|
||||
f"\n{TextColors.ERROR}Blend_My_NFTs Error:\n"
|
||||
f"An issue was found within the Material List of the Variant collection '{variant}'. For more information on Blend_My_NFTs compatible scenes, "
|
||||
f"see:\n{TextColors.RESET}"
|
||||
f"An issue was found within the Material List of the Variant collection '{variant}'. For more "
|
||||
f"information on Blend_My_NFTs compatible scenes, see:\n{TextColors.RESET}"
|
||||
f"https://github.com/torrinworx/Blend_My_NFTs#blender-file-organization-and-structure\n"
|
||||
)
|
||||
|
||||
return selected_material[0], materialList
|
||||
return selected_material[0], material_list
|
||||
|
||||
|
||||
def get_variant_att_index(variant, hierarchy):
|
||||
variant_attribute = None
|
||||
|
@ -72,26 +71,28 @@ def get_variant_att_index(variant, hierarchy):
|
|||
variant_order_num = variant.split("_")[1]
|
||||
return attribute_index, variant_order_num
|
||||
|
||||
def match_DNA_to_Variant(hierarchy, singleDNA):
|
||||
|
||||
def match_dna_to_variant(hierarchy, single_dna):
|
||||
"""
|
||||
Matches each DNA number separated by "-" to its attribute, then its variant.
|
||||
"""
|
||||
|
||||
listAttributes = list(hierarchy.keys())
|
||||
listDnaDecunstructed = singleDNA.split('-')
|
||||
dnaDictionary = {}
|
||||
list_attributes = list(hierarchy.keys())
|
||||
list_dna_decunstructed = single_dna.split('-')
|
||||
dna_dictionary = {}
|
||||
|
||||
for i, j in zip(listAttributes, listDnaDecunstructed):
|
||||
dnaDictionary[i] = j
|
||||
for i, j in zip(list_attributes, list_dna_decunstructed):
|
||||
dna_dictionary[i] = j
|
||||
|
||||
for x in dnaDictionary:
|
||||
for x in dna_dictionary:
|
||||
for k in hierarchy[x]:
|
||||
kNum = hierarchy[x][k]["number"]
|
||||
if kNum == dnaDictionary[x]:
|
||||
dnaDictionary.update({x: k})
|
||||
return dnaDictionary
|
||||
k_num = hierarchy[x][k]["number"]
|
||||
if k_num == dna_dictionary[x]:
|
||||
dna_dictionary.update({x: k})
|
||||
return dna_dictionary
|
||||
|
||||
def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity):
|
||||
|
||||
def apply_materials(hierarchy, single_dna, materials_file, enable_rarity):
|
||||
"""
|
||||
DNA with applied material example: "1-1:1-1" <Normal DNA>:<Selected Material for each Variant>
|
||||
|
||||
|
@ -99,20 +100,23 @@ def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity):
|
|||
list in the Variant_Material.json file.
|
||||
"""
|
||||
|
||||
singleDNADict = match_DNA_to_Variant(hierarchy, singleDNA)
|
||||
materialsFile = json.load(open(materialsFile))
|
||||
deconstructed_MaterialDNA = {}
|
||||
single_dna_dict = match_dna_to_variant(hierarchy, single_dna)
|
||||
materials_file = json.load(open(materials_file))
|
||||
deconstructed_material_dna = {}
|
||||
|
||||
for a in singleDNADict:
|
||||
for a in single_dna_dict:
|
||||
complete = False
|
||||
for b in materialsFile:
|
||||
if singleDNADict[a] == b:
|
||||
material_name, materialList, = select_material(materialsFile[b]['Material List'], b, enableRarity)
|
||||
material_order_num = list(materialList.keys()).index(material_name) # Gets the Order Number of the Material
|
||||
deconstructed_MaterialDNA[a] = str(material_order_num + 1)
|
||||
for b in materials_file:
|
||||
if single_dna_dict[a] == b:
|
||||
material_name, material_list, = select_material(materials_file[b]['Material List'], b, enable_rarity)
|
||||
|
||||
# Gets the Order Number of the Material
|
||||
material_order_num = list(material_list.keys()).index(material_name)
|
||||
|
||||
deconstructed_material_dna[a] = str(material_order_num + 1)
|
||||
complete = True
|
||||
if not complete:
|
||||
deconstructed_MaterialDNA[a] = "0"
|
||||
deconstructed_material_dna[a] = "0"
|
||||
|
||||
# This section is now incorrect and needs updating:
|
||||
|
||||
|
@ -121,14 +125,14 @@ def apply_materials(hierarchy, singleDNA, materialsFile, enableRarity):
|
|||
# Attribute 'B' = 1, 'C' = 2, 'D' = 3, etc. For each pair you want to equal another, add its number it to this list:
|
||||
# synced_material_attributes = [1, 2]
|
||||
#
|
||||
# first_mat = deconstructed_MaterialDNA[synced_material_attributes[0]]
|
||||
# first_mat = deconstructed_material_dna[synced_material_attributes[0]]
|
||||
# for i in synced_material_attributes:
|
||||
# deconstructed_MaterialDNA[i] = first_mat
|
||||
# deconstructed_material_dna[i] = first_mat
|
||||
|
||||
material_DNA = ""
|
||||
for a in deconstructed_MaterialDNA:
|
||||
num = "-" + str(deconstructed_MaterialDNA[a])
|
||||
material_DNA += num
|
||||
material_DNA = ''.join(material_DNA.split('-', 1))
|
||||
material_dna = ""
|
||||
for a in deconstructed_material_dna:
|
||||
num = "-" + str(deconstructed_material_dna[a])
|
||||
material_dna += num
|
||||
material_dna = ''.join(material_dna.split('-', 1))
|
||||
|
||||
return f"{singleDNA}:{material_DNA}"
|
||||
return f"{single_dna}:{material_dna}"
|
||||
|
|
|
@ -3,26 +3,37 @@
|
|||
# https://discord.gg/QTT7dzcuVs
|
||||
|
||||
# Purpose:
|
||||
# This file returns the specified meta data format to the exporter.py for a given NFT DNA.
|
||||
# This file returns the specified metadata format to the exporter.py for a given NFT DNA.
|
||||
|
||||
import bpy
|
||||
import os
|
||||
import json
|
||||
|
||||
def sendMetaDataToJson(metaDataDict, save_path, file_name):
|
||||
jsonMetaData = json.dumps(metaDataDict, indent=1, ensure_ascii=True)
|
||||
with open(os.path.join(save_path, f"{file_name}.json"), 'w') as outfile:
|
||||
outfile.write(jsonMetaData + '\n')
|
||||
|
||||
def stripNums(variant):
|
||||
def send_metadata_to_json(meta_data_dict, save_path, file_name):
|
||||
json_metadata = json.dumps(meta_data_dict, indent=1, ensure_ascii=True)
|
||||
with open(os.path.join(save_path, f"{file_name}.json"), 'w') as outfile:
|
||||
outfile.write(json_metadata + '\n')
|
||||
|
||||
|
||||
def strip_nums(variant):
|
||||
variant = str(variant).split('_')[0]
|
||||
return variant
|
||||
|
||||
# Cardano Template
|
||||
def createCardanoMetadata(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes,
|
||||
custom_Fields, enableCustomFields, cardano_description, cardanoMetadataPath):
|
||||
|
||||
metaDataDictCardano = {"721": {
|
||||
# Cardano Template
|
||||
def create_cardano_metadata(
|
||||
name,
|
||||
order_num,
|
||||
nft_dna,
|
||||
nft_variants,
|
||||
material_attributes,
|
||||
custom_fields,
|
||||
enable_custom_fields,
|
||||
cardano_description,
|
||||
cardano_metadata_path
|
||||
):
|
||||
|
||||
meta_data_dict_cardano = {"721": {
|
||||
"<policy_id>": {
|
||||
name: {
|
||||
"name": name,
|
||||
|
@ -35,73 +46,107 @@ def createCardanoMetadata(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attri
|
|||
}}
|
||||
|
||||
# Variants and Attributes:
|
||||
for i in NFT_Variants:
|
||||
metaDataDictCardano["721"]["<policy_id>"][name][i] = stripNums(NFT_Variants[i])
|
||||
for i in nft_variants:
|
||||
meta_data_dict_cardano["721"]["<policy_id>"][name][i] = strip_nums(nft_variants[i])
|
||||
|
||||
# Material Variants and Attributes:
|
||||
for i in Material_Attributes:
|
||||
metaDataDictCardano["721"]["<policy_id>"][name][i] = Material_Attributes[i]
|
||||
for i in material_attributes:
|
||||
meta_data_dict_cardano["721"]["<policy_id>"][name][i] = material_attributes[i]
|
||||
|
||||
# Custom Fields:
|
||||
if enableCustomFields:
|
||||
for i in custom_Fields:
|
||||
metaDataDictCardano["721"]["<policy_id>"][name][i] = custom_Fields[i]
|
||||
if enable_custom_fields:
|
||||
for i in custom_fields:
|
||||
meta_data_dict_cardano["721"]["<policy_id>"][name][i] = custom_fields[i]
|
||||
|
||||
sendMetaDataToJson(metaDataDictCardano, cardanoMetadataPath, name)
|
||||
send_metadata_to_json(
|
||||
meta_data_dict_cardano,
|
||||
cardano_metadata_path,
|
||||
name
|
||||
)
|
||||
|
||||
|
||||
# Solana Template
|
||||
def createSolanaMetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes, custom_Fields, enableCustomFields,
|
||||
solana_description, solanaMetadataPath):
|
||||
metaDataDictSolana = {"name": name, "symbol": "", "description": solana_description, "seller_fee_basis_points": None,
|
||||
"image": "", "animation_url": "", "external_url": ""}
|
||||
def createSolanaMetaData(
|
||||
name,
|
||||
order_num,
|
||||
nft_dna,
|
||||
nft_variants,
|
||||
material_attributes,
|
||||
custom_fields,
|
||||
enable_custom_fields,
|
||||
solana_description,
|
||||
solana_metadata_path
|
||||
):
|
||||
metadata_dict_solana = {
|
||||
"name": name,
|
||||
"symbol": "",
|
||||
"description": solana_description,
|
||||
"seller_fee_basis_points": None,
|
||||
"image": "",
|
||||
"animation_url": "",
|
||||
"external_url": ""
|
||||
}
|
||||
|
||||
attributes = []
|
||||
|
||||
# Variant and Attributes:
|
||||
for i in NFT_Variants:
|
||||
for i in nft_variants:
|
||||
dictionary = {
|
||||
"trait_type": i,
|
||||
"value": stripNums(NFT_Variants[i])
|
||||
"value": strip_nums(nft_variants[i])
|
||||
}
|
||||
attributes.append(dictionary)
|
||||
|
||||
# Material Variants and Attributes:
|
||||
for i in Material_Attributes:
|
||||
for i in material_attributes:
|
||||
dictionary = {
|
||||
"trait_type": i,
|
||||
"value": Material_Attributes[i]
|
||||
"value": material_attributes[i]
|
||||
}
|
||||
attributes.append(dictionary)
|
||||
|
||||
# Custom Fields:
|
||||
if enableCustomFields:
|
||||
for i in custom_Fields:
|
||||
if enable_custom_fields:
|
||||
for i in custom_fields:
|
||||
dictionary = {
|
||||
"trait_type": i,
|
||||
"value": custom_Fields[i]
|
||||
"value": custom_fields[i]
|
||||
}
|
||||
attributes.append(dictionary)
|
||||
|
||||
metaDataDictSolana["attributes"] = attributes
|
||||
metaDataDictSolana["collection"] = {
|
||||
metadata_dict_solana["attributes"] = attributes
|
||||
metadata_dict_solana["collection"] = {
|
||||
"name": "",
|
||||
"family": ""
|
||||
}
|
||||
|
||||
metaDataDictSolana["properties"] = {
|
||||
metadata_dict_solana["properties"] = {
|
||||
"files": [{"uri": "", "type": ""}],
|
||||
"category": "",
|
||||
"creators": [{"address": "", "share": None}]
|
||||
}
|
||||
|
||||
sendMetaDataToJson(metaDataDictSolana, solanaMetadataPath, name)
|
||||
send_metadata_to_json(
|
||||
metadata_dict_solana,
|
||||
solana_metadata_path,
|
||||
name
|
||||
)
|
||||
|
||||
|
||||
# ERC721 Template
|
||||
def createErc721MetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attributes, custom_Fields, enableCustomFields,
|
||||
erc721_description, erc721MetadataPath):
|
||||
metaDataDictErc721 = {
|
||||
def create_erc721_meta_data(
|
||||
name,
|
||||
order_num,
|
||||
nft_dna,
|
||||
nft_variants,
|
||||
material_attributes,
|
||||
custom_fields,
|
||||
enable_custom_fields,
|
||||
erc721_description,
|
||||
erc721_metadata_path
|
||||
):
|
||||
|
||||
metadata_dict_erc721 = {
|
||||
"name": name,
|
||||
"description": erc721_description,
|
||||
"image": "",
|
||||
|
@ -111,33 +156,36 @@ def createErc721MetaData(name, Order_Num, NFT_DNA, NFT_Variants, Material_Attrib
|
|||
attributes = []
|
||||
|
||||
# Variants and Attributes:
|
||||
for i in NFT_Variants:
|
||||
for i in nft_variants:
|
||||
dictionary = {
|
||||
"trait_type": i,
|
||||
"value": stripNums(NFT_Variants[i])
|
||||
"value": strip_nums(nft_variants[i])
|
||||
}
|
||||
|
||||
attributes.append(dictionary)
|
||||
|
||||
# Material Variants and Attributes:
|
||||
for i in Material_Attributes:
|
||||
for i in material_attributes:
|
||||
dictionary = {
|
||||
"trait_type": i,
|
||||
"value": Material_Attributes[i]
|
||||
"value": material_attributes[i]
|
||||
}
|
||||
|
||||
attributes.append(dictionary)
|
||||
|
||||
# Custom Fields:
|
||||
if enableCustomFields:
|
||||
for i in custom_Fields:
|
||||
if enable_custom_fields:
|
||||
for i in custom_fields:
|
||||
dictionary = {
|
||||
"trait_type": i,
|
||||
"value": custom_Fields[i]
|
||||
"value": custom_fields[i]
|
||||
}
|
||||
attributes.append(dictionary)
|
||||
|
||||
metaDataDictErc721["attributes"] = attributes
|
||||
|
||||
sendMetaDataToJson(metaDataDictErc721, erc721MetadataPath, name)
|
||||
metadata_dict_erc721["attributes"] = attributes
|
||||
|
||||
send_metadata_to_json(
|
||||
metadata_dict_erc721,
|
||||
erc721_metadata_path,
|
||||
name
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
Ładowanie…
Reference in New Issue