2022-02-02 15:37:42 +00:00
bl_info = {
2022-05-31 12:19:24 +00:00
" name " : " Blend_My_NFTs " ,
2022-02-02 15:37:42 +00:00
" author " : " Torrin Leonard, This Cozy Studio Inc " ,
2022-08-11 13:48:01 +00:00
" version " : ( 4 , 5 , 0 ) ,
" blender " : ( 3 , 2 , 2 ) ,
2022-02-02 15:37:42 +00:00
" location " : " View3D " ,
2022-08-11 13:48:01 +00:00
" 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 " ,
2022-02-02 15:37:42 +00:00
" category " : " Development " ,
}
2022-08-11 13:48:01 +00:00
BMNFTS_VERSION = " v4.5.0 "
2022-08-11 16:35:08 +00:00
LAST_UPDATED = " 12:34AM, Aug 11th, 2022 "
2022-05-25 23:58:33 +00:00
2022-04-14 02:18:09 +00:00
# ======== Import handling ======== #
2022-02-02 15:37:42 +00:00
import bpy
2022-02-03 00:40:05 +00:00
from bpy . app . handlers import persistent
2022-04-18 15:06:04 +00:00
from bpy . props import ( IntProperty ,
BoolProperty ,
CollectionProperty )
2022-08-11 13:48:01 +00:00
# Python modules:
2022-02-02 15:37:42 +00:00
import os
2022-04-11 17:20:00 +00:00
import sys
2022-03-26 03:47:54 +00:00
import json
2022-02-02 15:37:42 +00:00
import importlib
2022-08-11 13:48:01 +00:00
import traceback
2022-08-11 02:18:35 +00:00
from typing import Any
2022-08-11 13:48:01 +00:00
from dataclasses import dataclass
from datetime import datetime , timezone
2022-02-02 15:37:42 +00:00
2022-06-28 06:44:07 +00:00
# "a little hacky bs" - matt159 ;)
2022-04-11 17:20:00 +00:00
sys . path . append ( os . path . dirname ( os . path . realpath ( __file__ ) ) )
2022-02-02 15:37:42 +00:00
2022-08-11 13:48:01 +00:00
# Local file imports:
2022-04-17 20:42:47 +00:00
from main import \
2022-08-24 12:56:10 +00:00
Helpers , \
2022-04-17 20:42:47 +00:00
DNA_Generator , \
Exporter , \
HeadlessUtil , \
2022-07-01 04:44:15 +00:00
Intermediate , \
2022-04-17 20:42:47 +00:00
Logic , \
Material_Generator , \
Metadata , \
Refactorer
2022-04-20 01:04:17 +00:00
from UILists import \
Custom_Metadata_UIList , \
Logic_UIList
2022-04-17 20:42:47 +00:00
2022-04-18 15:06:04 +00:00
if " bpy " in locals ( ) :
2022-04-17 20:42:47 +00:00
modules = {
2022-08-24 12:56:10 +00:00
" Helpers " : Helpers ,
2022-04-17 20:42:47 +00:00
" DNA_Generator " : DNA_Generator ,
" Exporter " : Exporter ,
" HeadlessUtil " : HeadlessUtil ,
2022-07-14 13:57:21 +00:00
" Intermediate " : Intermediate ,
2022-04-17 20:42:47 +00:00
" Logic " : Logic ,
" Material_Generator " : Material_Generator ,
" Metadata " : Metadata ,
2022-04-18 15:06:04 +00:00
" Refactorer " : Refactorer ,
2022-04-20 01:07:59 +00:00
" Custom_Metadata_UIList " : Custom_Metadata_UIList ,
" Logic_UIList " : Logic_UIList ,
2022-04-17 20:42:47 +00:00
}
for i in modules :
if i in locals ( ) :
importlib . reload ( modules [ i ] )
2022-04-14 02:18:09 +00:00
2022-08-24 12:56:10 +00:00
# ======== Persistent UI Refresh ======== #
2022-04-14 02:18:09 +00:00
# Used for updating text and buttons in UI panels
2022-08-24 12:56:10 +00:00
2022-04-14 02:18:09 +00:00
combinations : int = 0
recommended_limit : int = 0
2022-08-11 13:48:01 +00:00
dt = datetime . now ( timezone . utc ) . astimezone ( ) # Date Time in UTC local
2022-04-14 02:18:09 +00:00
2022-08-11 13:48:01 +00:00
@persistent
def Refresh_UI ( dummy1 , dummy2 ) :
"""
Refreshes the UI upon user interacting with Blender ( using depsgraph_update_post handler ) . Might be a better handler
to use .
"""
global combinations
global recommended_limit
2022-08-24 12:56:10 +00:00
combinations = ( Helpers . get_combinations ( ) )
2022-08-11 13:48:01 +00:00
recommended_limit = int ( round ( combinations / 2 ) )
# Add panel classes that require refresh to this refresh_panels tuple:
refresh_panel_classes = (
BMNFTS_PT_CreateData ,
)
def redraw_panel ( panels ) :
for i in panels :
try :
bpy . utils . unregister_class ( i )
except Exception :
print ( traceback . format_exc ( ) )
bpy . utils . register_class ( i )
redraw_panel ( refresh_panel_classes )
bpy . app . handlers . depsgraph_update_post . append ( Refresh_UI )
# ======== Defining BMNFTs Data ======== #
2022-06-28 19:36:47 +00:00
@dataclass
2022-07-01 03:32:14 +00:00
class BMNFTData :
2022-06-28 19:36:47 +00:00
nftName : str
save_path : str
2022-07-14 12:35:48 +00:00
nftsPerBatch : int
2022-06-28 19:36:47 +00:00
batchToGenerate : int
collectionSize : int
Blend_My_NFTs_Output : str
batch_json_save_path : str
nftBatch_save_path : str
enableImages : bool
imageFileFormat : str
enableAnimations : bool
animationFileFormat : str
enableModelsBlender : bool
modelFileFormat : str
enableCustomFields : bool
cardanoMetaDataBool : bool
solanaMetaDataBool : bool
erc721MetaData : bool
cardano_description : str
solana_description : str
erc721_description : str
enableMaterials : bool
materialsFile : str
2022-07-01 00:09:20 +00:00
enableLogic : bool
2022-07-14 13:58:18 +00:00
enable_Logic_Json : bool
2022-07-14 12:35:48 +00:00
logicFile : str
enableRarity : bool
2022-07-01 00:09:20 +00:00
2022-08-11 13:48:01 +00:00
enableAutoShutdown : bool
specify_timeBool : bool
hours : int
minutes : int
emailNotificationBool : bool
sender_from : str
email_password : str
receiver_to : str
2022-08-24 12:56:10 +00:00
enable_debug : bool
2022-08-11 13:48:01 +00:00
2022-06-28 19:36:47 +00:00
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 = { }
2022-08-11 13:48:01 +00:00
2022-07-14 14:02:05 +00:00
def getBMNFTData ( ) :
_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 )
2022-08-11 13:48:01 +00:00
data = BMNFTData (
nftName = bpy . context . scene . input_tool . nftName ,
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 ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
enableRarity = bpy . context . scene . input_tool . enableRarity ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
Blend_My_NFTs_Output = _Blend_My_NFTs_Output ,
batch_json_save_path = _batch_json_save_path ,
nftBatch_save_path = _nftBatch_save_path ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
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 ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
enableImages = bpy . context . scene . input_tool . imageBool ,
imageFileFormat = bpy . context . scene . input_tool . imageEnum ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
enableAnimations = bpy . context . scene . input_tool . animationBool ,
animationFileFormat = bpy . context . scene . input_tool . animationEnum ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
enableModelsBlender = bpy . context . scene . input_tool . modelBool ,
modelFileFormat = bpy . context . scene . input_tool . modelEnum ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
enableCustomFields = bpy . context . scene . input_tool . enableCustomFields ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
cardanoMetaDataBool = bpy . context . scene . input_tool . cardanoMetaDataBool ,
solanaMetaDataBool = bpy . context . scene . input_tool . solanaMetaDataBool ,
erc721MetaData = bpy . context . scene . input_tool . erc721MetaData ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
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 ,
2022-07-14 14:02:05 +00:00
2022-08-11 13:48:01 +00:00
enableMaterials = bpy . context . scene . input_tool . enableMaterials ,
materialsFile = bpy . path . abspath ( bpy . context . scene . input_tool . materialsFile ) ,
2022-06-28 19:36:47 +00:00
2022-08-11 13:48:01 +00:00
enableAutoShutdown = bpy . context . scene . input_tool . enableAutoShutdown ,
2022-04-14 02:18:09 +00:00
2022-08-11 13:48:01 +00:00
specify_timeBool = bpy . context . scene . input_tool . specify_timeBool ,
hours = bpy . context . scene . input_tool . hours ,
minutes = bpy . context . scene . input_tool . minutes ,
2022-04-14 02:18:09 +00:00
2022-08-11 13:48:01 +00:00
emailNotificationBool = bpy . context . scene . input_tool . emailNotificationBool ,
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 ,
2022-08-24 12:56:10 +00:00
enable_debug = bpy . context . scene . input_tool . enable_debug
2022-04-14 02:18:09 +00:00
)
2022-08-11 13:48:01 +00:00
return data
2022-04-14 02:18:09 +00:00
# ======== Helper functions ======== #
def make_directories ( save_path ) :
""" Makes all Blend_My_NFTs Output folder directories from save_path input. """
Blend_My_NFTs_Output = os . path . join ( save_path , " Blend_My_NFTs Output " , " NFT_Data " )
batch_json_save_path = os . path . join ( Blend_My_NFTs_Output , " Batch_Data " )
nftBatch_save_path = os . path . join ( save_path , " Blend_My_NFTs Output " , " Generated NFT Batches " )
if not os . path . exists ( Blend_My_NFTs_Output ) :
os . makedirs ( Blend_My_NFTs_Output )
if not os . path . exists ( batch_json_save_path ) :
os . makedirs ( batch_json_save_path )
if not os . path . exists ( nftBatch_save_path ) :
os . makedirs ( nftBatch_save_path )
return Blend_My_NFTs_Output , batch_json_save_path , nftBatch_save_path
2022-04-17 20:42:47 +00:00
2022-04-14 02:18:09 +00:00
def runAsHeadless ( ) :
"""
For use when running from the command line .
"""
2022-08-11 13:48:01 +00:00
2022-06-29 21:59:31 +00:00
# force CUDA device usage with cycles renderer
cprefs = bpy . context . preferences . addons [ ' cycles ' ] . preferences
cprefs . compute_device_type = ' CUDA '
cprefs . get_devices ( )
print ( cprefs . devices . keys ( ) )
for key in cprefs . devices . keys ( ) :
2022-08-11 13:48:01 +00:00
cprefs . devices [ key ] . use = True
2022-06-29 21:59:31 +00:00
print ( ' Using {} devices for rendering! ' . format ( cprefs . get_num_gpu_devices ( ) ) )
2022-04-17 20:42:47 +00:00
2022-04-14 02:18:09 +00:00
def dumpSettings ( settings ) :
output = (
2022-08-11 13:48:01 +00:00
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 " batchToGenerate= { 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 "
2022-04-14 02:18:09 +00:00
)
print ( output )
args , parser = HeadlessUtil . getPythonArgs ( )
settings = bpy . context . scene . input_tool
# dumpSettings(settings)
with open ( args . config_path , ' r ' ) as f :
configs = [ line . strip ( ) for line in f . readlines ( ) if not ( line [ 0 ] == ' # ' or len ( line . strip ( ) ) < 1 ) ]
pairs = [ config . strip ( ) . split ( ' = ' ) for config in configs ]
# print(pairs)
2022-08-11 13:48:01 +00:00
settings . nftName = pairs [ 0 ] [ 1 ]
settings . collectionSize = int ( pairs [ 1 ] [ 1 ] )
settings . nftsPerBatch = int ( pairs [ 2 ] [ 1 ] )
settings . save_path = pairs [ 3 ] [ 1 ]
settings . enableRarity = pairs [ 4 ] [ 1 ] == ' True '
settings . enableLogic = 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 . cardano_description = pairs [ 16 ] [ 1 ]
settings . erc721MetaData = pairs [ 17 ] [ 1 ] == ' True '
settings . erc721_description = pairs [ 18 ] [ 1 ]
settings . solanaMetaDataBool = 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 ]
2022-04-14 02:18:09 +00:00
if args . save_path :
settings . save_path = args . save_path
if args . batch_number :
settings . batchToGenerate = args . batch_number
2022-07-14 14:02:05 +00:00
input = getBMNFTData ( )
2022-04-14 02:18:09 +00:00
2022-07-14 14:02:05 +00:00
if args . batch_data_path :
input . batch_json_save_path = args . batch_data_path
2022-07-14 12:35:48 +00:00
2022-07-01 04:44:15 +00:00
if args . operation == ' create-dna ' :
Intermediate . send_To_Record_JSON ( input )
2022-04-14 02:18:09 +00:00
2022-07-01 04:44:15 +00:00
elif args . operation == ' generate-nfts ' :
2022-07-14 17:19:32 +00:00
Intermediate . render_and_save_NFTs ( input )
2022-04-14 02:18:09 +00:00
2022-07-01 04:44:15 +00:00
elif args . operation == ' refactor-batches ' :
Refactorer . reformatNFTCollection ( input )
2022-04-14 02:18:09 +00:00
# ======== User input Property Group ======== #
class BMNFTS_PGT_Input_Properties ( bpy . types . PropertyGroup ) :
# Create NFT Data Panel:
2022-02-02 15:37:42 +00:00
nftName : bpy . props . StringProperty ( name = " NFT Name " )
2022-02-04 14:44:36 +00:00
collectionSize : bpy . props . IntProperty ( name = " NFT Collection Size " , default = 1 , min = 1 ) # max=(combinations - offset)
nftsPerBatch : bpy . props . IntProperty ( name = " NFTs Per Batch " , default = 1 , min = 1 ) # max=(combinations - offset)
2022-02-02 15:37:42 +00:00
2022-02-04 14:44:36 +00:00
save_path : bpy . props . StringProperty (
2022-04-17 20:42:47 +00:00
name = " Save Path " ,
description = " Save path for NFT files " ,
default = " " ,
maxlen = 1024 ,
subtype = " DIR_PATH "
2022-02-04 14:44:36 +00:00
)
2022-02-02 15:37:42 +00:00
enableRarity : bpy . props . BoolProperty ( name = " Enable Rarity " )
2022-04-14 02:18:09 +00:00
enableLogic : bpy . props . BoolProperty ( name = " Enable Logic " )
2022-04-20 01:04:17 +00:00
enable_Logic_Json : bpy . props . BoolProperty ( name = " Use Logic.json instead " )
2022-04-14 02:18:09 +00:00
logicFile : bpy . props . StringProperty (
2022-04-20 18:50:53 +00:00
name = " Logic File Path " ,
2022-04-17 20:42:47 +00:00
description = " Path where Logic.json is located. " ,
default = " " ,
maxlen = 1024 ,
subtype = " FILE_PATH "
)
enableMaterials : bpy . props . BoolProperty ( name = " Enable Materials " )
materialsFile : bpy . props . StringProperty (
name = " Materials File " ,
description = " Path where Materials.json is located. " ,
default = " " ,
maxlen = 1024 ,
subtype = " FILE_PATH "
2022-04-14 02:18:09 +00:00
)
# Generate NFTs Panel:
2022-02-02 15:37:42 +00:00
imageBool : bpy . props . BoolProperty ( name = " Image " )
imageEnum : bpy . props . EnumProperty (
2022-04-17 20:42:47 +00:00
name = " Image File Format " ,
description = " Select Image file format " ,
2022-02-02 15:37:42 +00:00
items = [
( ' PNG ' , " .PNG " , " Export NFT as PNG " ) ,
( ' JPEG ' , " .JPEG " , " Export NFT as JPEG " )
]
)
2022-04-14 02:18:09 +00:00
2022-02-02 15:37:42 +00:00
animationBool : bpy . props . BoolProperty ( name = " Animation " )
animationEnum : bpy . props . EnumProperty (
2022-04-17 20:42:47 +00:00
name = " Animation File Format " ,
description = " Select Animation file format " ,
2022-02-02 15:37:42 +00:00
items = [
2022-02-03 00:40:05 +00:00
( ' AVI_JPEG ' , ' .avi (AVI_JPEG) ' , ' Export NFT as AVI_JPEG ' ) ,
( ' AVI_RAW ' , ' .avi (AVI_RAW) ' , ' Export NFT as AVI_RAW ' ) ,
( ' FFMPEG ' , ' .mkv (FFMPEG) ' , ' Export NFT as FFMPEG ' ) ,
2022-05-31 05:28:01 +00:00
( ' MP4 ' , ' .mp4 ' , ' Export NFT as .mp4 ' ) ,
2022-05-31 12:03:52 +00:00
( ' PNG ' , ' .png ' , ' Export NFT as PNG ' ) ,
( ' TIFF ' , ' .tiff ' , ' Export NFT as TIFF ' )
2022-02-02 15:37:42 +00:00
]
)
modelBool : bpy . props . BoolProperty ( name = " 3D Model " )
modelEnum : bpy . props . EnumProperty (
2022-04-17 20:42:47 +00:00
name = " 3D Model File Format " ,
description = " Select 3D Model file format " ,
2022-02-02 15:37:42 +00:00
items = [
( ' GLB ' , ' .glb ' , ' Export NFT as .glb ' ) ,
2022-04-17 20:42:47 +00:00
( ' GLTF_SEPARATE ' , ' .gltf + .bin + textures ' ,
' Export NFT as .gltf with separated textures in .bin + textures. ' ) ,
2022-02-02 15:37:42 +00:00
( ' GLTF_EMBEDDED ' , ' .gltf ' , ' Export NFT as embedded .gltf file that contains textures. ' ) ,
( ' FBX ' , ' .fbx ' , ' Export NFT as .fbx ' ) ,
( ' OBJ ' , ' .obj ' , ' Export NFT as .obj ' ) ,
( ' X3D ' , ' .x3d ' , ' Export NFT as .x3d ' ) ,
2022-02-03 00:40:05 +00:00
( ' STL ' , ' .stl ' , ' Export NFT as .stl ' ) ,
2022-04-17 20:42:47 +00:00
( ' VOX ' , ' .vox (Experimental) ' ,
' Export NFT as .vox, requires the voxwriter add on: https://github.com/Spyduck/voxwriter ' )
2022-02-02 15:37:42 +00:00
]
)
2022-04-17 20:42:47 +00:00
batchToGenerate : bpy . props . IntProperty ( name = " Batch To Generate " , default = 1 ,
min = 1 )
2022-04-14 02:18:09 +00:00
# Refactor Batches & Create Metadata Panel:
2022-02-02 15:37:42 +00:00
cardanoMetaDataBool : bpy . props . BoolProperty ( name = " Cardano Cip " )
2022-04-14 02:18:09 +00:00
cardano_description : bpy . props . StringProperty ( name = " Cardano description " )
2022-02-02 15:37:42 +00:00
2022-04-14 02:18:09 +00:00
solanaMetaDataBool : bpy . props . BoolProperty ( name = " Solana Metaplex " )
solana_description : bpy . props . StringProperty ( name = " Solana description " )
2022-02-02 15:37:42 +00:00
2022-04-14 02:18:09 +00:00
erc721MetaData : bpy . props . BoolProperty ( name = " ERC721 " )
erc721_description : bpy . props . StringProperty ( name = " ERC721 description " )
2022-03-11 01:03:20 +00:00
enableCustomFields : bpy . props . BoolProperty ( name = " Enable Custom Metadata Fields " )
customfieldsFile : bpy . props . StringProperty (
2022-04-17 20:42:47 +00:00
name = " Custom Fields File " ,
description = " Path where Custom_Fields.json is located. " ,
default = " " ,
maxlen = 1024 ,
subtype = " FILE_PATH "
2022-03-08 03:21:25 +00:00
)
2022-08-11 13:48:01 +00:00
# TODO: Add 'Other' panel inputs to Headless functionality.
2022-04-14 02:18:09 +00:00
# Other Panel:
2022-08-11 13:48:01 +00:00
enableAutoSave : 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 ( name = " Auto Shutdown " ,
description = " Automatically shuts down your computer after a Batch is finished Generating " )
specify_timeBool : 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 " )
hours : bpy . props . IntProperty ( default = 0 , min = 0 )
minutes : bpy . props . IntProperty ( default = 0 , min = 0 )
emailNotificationBool : bpy . props . BoolProperty ( name = " Email Notifications " ,
description = " Receive Email Notifications from Blender once a batch is finished generating " )
sender_from : bpy . props . StringProperty ( name = " From " , default = " from@example.com " )
email_password : bpy . props . StringProperty ( name = " Password " , subtype = ' PASSWORD ' )
receiver_to : bpy . props . StringProperty ( name = " To " , default = " to@example.com " )
2022-03-11 01:03:20 +00:00
2022-08-24 12:56:10 +00:00
enable_debug : bpy . props . BoolProperty ( name = " Enable Debug Mode " , description = " Allows you to run Blend_My_NFTs without generating any content files and includes more console information. " )
2022-04-14 02:18:09 +00:00
# API Panel properties:
2022-08-24 12:56:10 +00:00
apiKey : bpy . props . StringProperty ( name = " API Key " , subtype = ' PASSWORD ' ) # Test code for future features
2022-02-03 00:40:05 +00:00
2022-03-26 03:47:54 +00:00
2022-04-14 02:18:09 +00:00
# ======== Main Operators ======== #
2022-02-02 15:37:42 +00:00
class createData ( bpy . types . Operator ) :
bl_idname = ' create.data '
bl_label = ' Create Data '
2022-05-10 12:14:53 +00:00
bl_description = ' Creates NFT Data. Run after any changes were made to scene. All previous data will be overwritten and cannot be recovered. '
2022-02-02 15:37:42 +00:00
bl_options = { " REGISTER " , " UNDO " }
2022-04-20 01:04:17 +00:00
reverse_order : BoolProperty (
default = False ,
name = " Reverse Order " )
2022-02-02 15:37:42 +00:00
def execute ( self , context ) :
2022-04-20 01:04:17 +00:00
# Handling Custom Fields UIList input:
2022-07-14 14:02:05 +00:00
input = getBMNFTData ( )
2022-04-20 01:04:17 +00:00
2022-07-14 14:02:05 +00:00
if input . enableLogic :
if input . enable_Logic_Json and not input . logicFile :
2022-08-11 13:48:01 +00:00
self . report ( { ' ERROR ' } ,
f " No Logic.json file path set. Please set the file path to your Logic.json file. " )
2022-04-20 01:04:17 +00:00
2022-07-14 14:02:05 +00:00
Intermediate . send_To_Record_JSON ( input )
2022-08-11 13:48:01 +00:00
2022-03-12 17:18:41 +00:00
self . report ( { ' INFO ' } , f " NFT Data created! " )
2022-02-02 15:37:42 +00:00
return { " FINISHED " }
2022-05-10 12:14:53 +00:00
def invoke ( self , context , event ) :
return context . window_manager . invoke_confirm ( self , event )
2022-04-17 20:42:47 +00:00
2022-02-02 15:37:42 +00:00
class exportNFTs ( bpy . types . Operator ) :
bl_idname = ' exporter.nfts '
bl_label = ' Export NFTs '
bl_description = ' Generate and export a given batch of NFTs. '
bl_options = { " REGISTER " , " UNDO " }
2022-05-10 12:14:53 +00:00
reverse_order : BoolProperty (
default = False ,
name = " Reverse Order " )
2022-02-02 15:37:42 +00:00
def execute ( self , context ) :
2022-07-14 14:02:05 +00:00
input = getBMNFTData ( )
2022-05-10 12:14:53 +00:00
# Handling Custom Fields UIList input:
2022-08-11 13:48:01 +00:00
2022-07-14 14:02:05 +00:00
Intermediate . render_and_save_NFTs ( input )
2022-03-12 17:18:41 +00:00
2022-05-10 12:14:53 +00:00
self . report ( { ' INFO ' } , f " All NFTs generated for batch { input . batchToGenerate } ! " )
2022-03-12 17:18:41 +00:00
2022-02-02 15:37:42 +00:00
return { " FINISHED " }
2022-04-17 20:42:47 +00:00
2022-03-26 03:47:54 +00:00
class resume_failed_batch ( 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? '
bl_options = { " REGISTER " , " UNDO " }
def execute ( self , context ) :
2022-06-28 19:39:57 +00:00
_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 )
2022-03-26 03:47:54 +00:00
2022-06-28 19:39:57 +00:00
_batchToGenerate = bpy . context . scene . input_tool . batchToGenerate
file_name = os . path . join ( _batch_json_save_path , " Batch {} .json " . format ( _batchToGenerate ) )
batchData = json . load ( open ( file_name ) )
2022-08-24 13:57:59 +00:00
_fail_state , _failed_batch , _failed_dna , _failed_dna_index = Helpers . check_FailedBatches ( _batch_json_save_path )
2022-03-26 03:47:54 +00:00
2022-08-11 14:26:16 +00:00
render_settings = batchData [ " Generation Save " ] [ - 1 ] [ " Render_Settings " ]
2022-08-11 13:48:01 +00:00
input = BMNFTData (
2022-08-11 14:26:16 +00:00
nftName = render_settings [ " nftName " ] ,
2022-08-11 13:48:01 +00:00
save_path = _save_path ,
2022-08-11 14:26:16 +00:00
nftsPerBatch = render_settings [ " nftsPerBatch " ] ,
batchToGenerate = render_settings [ " batchToGenerate " ] ,
collectionSize = render_settings [ " collectionSize " ] ,
2022-03-26 03:47:54 +00:00
2022-08-11 13:48:01 +00:00
Blend_My_NFTs_Output = _Blend_My_NFTs_Output ,
batch_json_save_path = _batch_json_save_path ,
2022-08-11 14:26:16 +00:00
nftBatch_save_path = render_settings [ " nftBatch_save_path " ] ,
enableImages = render_settings [ " enableImages " ] ,
imageFileFormat = render_settings [ " imageFileFormat " ] ,
enableAnimations = render_settings [ " enableAnimations " ] ,
animationFileFormat = render_settings [ " animationFileFormat " ] ,
enableModelsBlender = render_settings [ " enableModelsBlender " ] ,
modelFileFormat = render_settings [ " modelFileFormat " ] ,
2022-03-26 03:47:54 +00:00
2022-08-11 14:26:16 +00:00
enableCustomFields = render_settings [ " enableCustomFields " ] ,
2022-05-10 12:14:53 +00:00
2022-08-11 14:26:16 +00:00
cardanoMetaDataBool = render_settings [ " cardanoMetaDataBool " ] ,
solanaMetaDataBool = render_settings [ " solanaMetaDataBool " ] ,
erc721MetaData = render_settings [ " erc721MetaData " ] ,
2022-05-10 12:14:53 +00:00
2022-08-11 14:26:16 +00:00
cardano_description = render_settings [ " cardano_description " ] ,
solana_description = render_settings [ " solana_description " ] ,
erc721_description = render_settings [ " erc721_description " ] ,
2022-05-10 12:14:53 +00:00
2022-08-11 14:26:16 +00:00
enableMaterials = render_settings [ " enableMaterials " ] ,
materialsFile = render_settings [ " materialsFile " ] ,
2022-05-10 12:14:53 +00:00
2022-08-11 14:26:16 +00:00
enableLogic = render_settings [ " enableLogic " ] ,
enable_Logic_Json = render_settings [ " enable_Logic_Json " ] ,
logicFile = render_settings [ " logicFile " ] ,
2022-05-10 12:14:53 +00:00
2022-08-11 14:26:16 +00:00
enableRarity = render_settings [ " enableRarity " ] ,
2022-05-10 12:14:53 +00:00
2022-08-11 14:26:16 +00:00
enableAutoShutdown = render_settings [ " enableAutoShutdown " ] ,
specify_timeBool = render_settings [ " specify_timeBool " ] ,
hours = render_settings [ " hours " ] ,
minutes = render_settings [ " minutes " ] ,
emailNotificationBool = render_settings [ " emailNotificationBool " ] ,
sender_from = render_settings [ " sender_from " ] ,
email_password = render_settings [ " email_password " ] ,
receiver_to = render_settings [ " receiver_to " ] ,
2022-08-24 12:56:10 +00:00
enable_debug = render_settings [ " enable_debug " ] ,
2022-06-28 19:39:57 +00:00
2022-08-11 13:48:01 +00:00
fail_state = _fail_state ,
failed_batch = _failed_batch ,
failed_dna = _failed_dna ,
2022-08-11 14:26:16 +00:00
failed_dna_index = _failed_dna_index ,
custom_Fields = render_settings [ " custom_Fields " ] ,
2022-06-28 19:39:57 +00:00
)
2022-05-10 12:14:53 +00:00
Exporter . render_and_save_NFTs ( input )
2022-03-26 03:47:54 +00:00
self . report ( { ' INFO ' } , f " Resuming Failed Batch Generation! " )
return { " FINISHED " }
2022-04-17 20:42:47 +00:00
2022-02-02 15:37:42 +00:00
class refactor_Batches ( bpy . types . Operator ) :
2022-03-12 17:18:41 +00:00
""" Refactor your collection? This action cannot be undone. """
2022-02-02 15:37:42 +00:00
bl_idname = ' refactor.batches '
2022-02-03 23:57:23 +00:00
bl_label = ' Refactor your Batches? '
bl_description = ' This action cannot be undone. '
bl_options = { ' REGISTER ' , ' INTERNAL ' }
2022-04-18 15:06:04 +00:00
reverse_order : BoolProperty (
default = False ,
name = " Reverse Order " )
2022-02-02 15:37:42 +00:00
def execute ( self , context ) :
2022-04-18 15:06:04 +00:00
# Passing info to main functions for refactoring:
2022-07-14 14:02:05 +00:00
Refactorer . reformatNFTCollection ( getBMNFTData ( ) )
2022-02-03 23:48:52 +00:00
return { " FINISHED " }
2022-02-02 15:37:42 +00:00
2022-02-03 23:57:23 +00:00
def invoke ( self , context , event ) :
return context . window_manager . invoke_confirm ( self , event )
2022-04-17 20:42:47 +00:00
2022-04-14 02:18:09 +00:00
class export_settings ( bpy . types . Operator ) :
""" Export your settings into a configuration file. """
bl_idname = ' export.settings '
bl_label = ' Export Settings '
bl_description = ' Save your settings to a configuration file '
bl_options = { " REGISTER " , " UNDO " }
def execute ( self , context ) :
save_path = bpy . path . abspath ( bpy . context . scene . input_tool . save_path )
filename = " config.cfg "
settings = bpy . context . scene . input_tool
with open ( save_path + filename , ' w ' ) as config :
output = (
" #This file was auto-generated from the Blend_My_NFTs addon and is used \n "
" #when running Blend_My_NFTs in a headless environment. \n "
" \n "
" #The name of your nft project \n "
2022-08-11 13:48:01 +00:00
f " nftName= { settings . nftName } \n "
2022-04-14 02:18:09 +00:00
" \n "
" #NFT Collection Size \n "
2022-08-11 13:48:01 +00:00
f " collectionSize= { settings . collectionSize } \n "
2022-04-14 02:18:09 +00:00
" \n "
" #The number of NFTs to generate per batch \n "
2022-08-11 13:48:01 +00:00
f " nftsPerBatch= { str ( settings . nftsPerBatch ) } \n "
2022-04-14 02:18:09 +00:00
" \n "
" #Save path for your NFT files \n "
2022-08-11 13:48:01 +00:00
f " save_path= { settings . save_path } \n "
2022-04-14 02:18:09 +00:00
" \n "
" #Enable Rarity \n "
2022-08-11 13:48:01 +00:00
f " enableRarity= { ( settings . enableRarity ) } \n "
2022-04-14 02:18:09 +00:00
" \n "
" #Enable Logic \n "
2022-08-11 13:48:01 +00:00
f " enableLogic= { str ( settings . enableLogic ) } \n "
f " enableLogicJson= { str ( settings . enable_Logic_Json ) } \n "
f " logicFilePath= { settings . logicFile } \n "
2022-04-14 02:18:09 +00:00
" \n "
" #NFT Media output type(s): \n "
2022-08-11 13:48:01 +00:00
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 "
2022-04-14 02:18:09 +00:00
" \n "
" #Batch to generate \n "
2022-08-11 13:48:01 +00:00
f " batchToGenerate= { str ( settings . batchToGenerate ) } \n "
2022-04-14 02:18:09 +00:00
" \n "
" #Metadata Format \n "
2022-08-11 13:48:01 +00:00
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 "
2022-04-14 02:18:09 +00:00
" \n "
" #Enable Custom Fields \n "
2022-08-11 13:48:01 +00:00
f " enableCustomFields= { str ( settings . enableCustomFields ) } \n "
f " customfieldsFile= { settings . customfieldsFile } \n "
2022-04-17 20:42:47 +00:00
" \n "
" #Enable Materials \n "
2022-08-11 13:48:01 +00:00
f " enableMaterials= { str ( settings . enableMaterials ) } \n "
f " materialsFile= { settings . materialsFile } \n "
2022-04-14 02:18:09 +00:00
)
print ( output , file = config )
self . report ( { ' INFO ' } , f " Saved settings to: { save_path + filename } ! " )
return { " FINISHED " }
# ======== UI Panels ======== #
2022-02-04 14:44:36 +00:00
class BMNFTS_PT_CreateData ( bpy . types . Panel ) :
bl_label = " Create NFT Data "
bl_idname = " BMNFTS_PT_CreateData "
2022-02-02 15:37:42 +00:00
bl_space_type = ' VIEW_3D '
bl_region_type = ' UI '
bl_category = ' Blend_My_NFTs '
def draw ( self , context ) :
layout = self . layout
scene = context . scene
2022-04-14 02:18:09 +00:00
input_tool_scene = scene . input_tool
2022-02-02 15:37:42 +00:00
2022-02-04 14:44:36 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " nftName " )
2022-02-04 14:44:36 +00:00
2022-02-02 15:37:42 +00:00
row = layout . row ( )
2022-03-08 03:21:25 +00:00
layout . label ( text = f " Maximum Number Of NFTs: { combinations } " )
layout . label ( text = f " Recommended limit: { recommended_limit } " )
2022-02-02 15:37:42 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " collectionSize " )
2022-02-02 15:37:42 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " nftsPerBatch " )
2022-02-02 15:37:42 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " save_path " )
2022-02-02 15:37:42 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " enableRarity " )
2022-02-04 14:44:36 +00:00
2022-03-08 03:21:25 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " enableLogic " )
2022-03-08 03:21:25 +00:00
2022-04-20 01:04:17 +00:00
# Logic_UIList implementation:
2022-04-14 02:18:09 +00:00
if bpy . context . scene . input_tool . enableLogic :
2022-04-20 01:04:17 +00:00
layout = self . layout
scn = bpy . context . scene
rows = 2
2022-03-08 03:21:25 +00:00
row = layout . row ( )
2022-04-20 01:04:17 +00:00
row . template_list ( " CUSTOM_UL_logic_items " , " " , scn , " logic_fields " , scn ,
" logic_fields_index " , rows = rows )
col = row . column ( align = True )
col . operator ( " logic_uilist.logic_list_action " , icon = ' ZOOM_IN ' , text = " " ) . action = ' ADD '
col . operator ( " logic_uilist.logic_list_action " , icon = ' ZOOM_OUT ' , text = " " ) . action = ' REMOVE '
col . separator ( )
col . operator ( " logic_uilist.logic_list_action " , icon = ' TRIA_UP ' , text = " " ) . action = ' UP '
col . operator ( " logic_uilist.logic_list_action " , icon = ' TRIA_DOWN ' , text = " " ) . action = ' DOWN '
row = layout . row ( )
col = row . column ( align = True )
row = col . row ( align = True )
row . operator ( " logic_uilist.logic_clear_list " , icon = " X " )
row = col . row ( align = True )
row . label ( text = f " *Field Names must be unique. " )
row = layout . row ( )
row . prop ( input_tool_scene , " enable_Logic_Json " )
if bpy . context . scene . input_tool . enable_Logic_Json :
row = layout . row ( )
row . prop ( input_tool_scene , " logicFile " )
2022-03-08 03:21:25 +00:00
2022-04-17 20:42:47 +00:00
row = layout . row ( )
row . prop ( input_tool_scene , " enableMaterials " )
if bpy . context . scene . input_tool . enableMaterials :
row = layout . row ( )
row . prop ( input_tool_scene , " materialsFile " )
2022-02-04 14:44:36 +00:00
row = layout . row ( )
self . layout . operator ( " create.data " , icon = ' DISCLOSURE_TRI_RIGHT ' , text = " Create Data " )
2022-05-25 23:58:33 +00:00
row = layout . row ( )
layout . label ( text = f " { BMNFTS_VERSION } " )
2022-02-04 14:44:36 +00:00
2022-04-17 20:42:47 +00:00
2022-02-04 14:44:36 +00:00
class BMNFTS_PT_GenerateNFTs ( bpy . types . Panel ) :
2022-05-31 02:45:39 +00:00
bl_label = " Generate NFTs & Create Metadata "
2022-02-04 14:44:36 +00:00
bl_idname = " BMNFTS_PT_GenerateNFTs "
bl_space_type = ' VIEW_3D '
bl_region_type = ' UI '
bl_category = ' Blend_My_NFTs '
def draw ( self , context ) :
layout = self . layout
scene = context . scene
2022-04-14 02:18:09 +00:00
input_tool_scene = scene . input_tool
2022-02-02 15:37:42 +00:00
2022-03-08 03:21:25 +00:00
row = layout . row ( )
layout . label ( text = " NFT Media files: " )
2022-02-02 15:37:42 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " imageBool " )
if bpy . context . scene . input_tool . imageBool :
row . prop ( input_tool_scene , " imageEnum " )
2022-02-02 15:37:42 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " animationBool " )
if bpy . context . scene . input_tool . animationBool :
row . prop ( input_tool_scene , " animationEnum " )
2022-02-02 15:37:42 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " modelBool " )
if bpy . context . scene . input_tool . modelBool :
row . prop ( input_tool_scene , " modelEnum " )
2022-02-02 15:37:42 +00:00
row = layout . row ( )
layout . label ( text = " Meta Data format: " )
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " cardanoMetaDataBool " )
if bpy . context . scene . input_tool . cardanoMetaDataBool :
2022-03-11 01:03:20 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " cardano_description " )
2022-03-11 01:03:20 +00:00
row = layout . row ( )
row . operator ( " wm.url_open " , text = " Cardano Metadata Documentation " ,
icon = ' URL ' ) . url = " https://cips.cardano.org/cips/cip25/ "
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " solanaMetaDataBool " )
if bpy . context . scene . input_tool . solanaMetaDataBool :
2022-03-11 01:03:20 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " solana_description " )
2022-03-11 01:03:20 +00:00
row = layout . row ( )
row . operator ( " wm.url_open " , text = " Solana Metadata Documentation " ,
icon = ' URL ' ) . url = " https://docs.metaplex.com/token-metadata/specification "
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " erc721MetaData " )
if bpy . context . scene . input_tool . erc721MetaData :
2022-03-11 01:03:20 +00:00
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " erc721_description " )
2022-03-11 01:03:20 +00:00
row = layout . row ( )
row . operator ( " wm.url_open " , text = " ERC721 Metadata Documentation " ,
icon = ' URL ' ) . url = " https://docs.opensea.io/docs/metadata-standards "
row = layout . row ( )
2022-04-14 02:18:09 +00:00
row . prop ( input_tool_scene , " enableCustomFields " )
2022-04-18 15:06:04 +00:00
2022-04-20 01:04:17 +00:00
# Custom Metadata Fields UIList:
2022-04-14 02:18:09 +00:00
if bpy . context . scene . input_tool . enableCustomFields :
2022-04-18 15:06:04 +00:00
layout = self . layout
scn = bpy . context . scene
rows = 2
2022-03-11 01:03:20 +00:00
row = layout . row ( )
2022-08-11 13:48:01 +00:00
row . template_list ( " CUSTOM_UL_custom_metadata_fields_items " , " " , scn , " custom_metadata_fields " , scn ,
" custom_metadata_fields_index " , rows = rows )
2022-04-18 15:06:04 +00:00
col = row . column ( align = True )
2022-04-20 01:04:17 +00:00
col . operator ( " custom_metadata_fields_uilist.list_action " , icon = ' ZOOM_IN ' , text = " " ) . action = ' ADD '
col . operator ( " custom_metadata_fields_uilist.list_action " , icon = ' ZOOM_OUT ' , text = " " ) . action = ' REMOVE '
2022-04-18 15:06:04 +00:00
col . separator ( )
2022-04-20 01:04:17 +00:00
col . operator ( " custom_metadata_fields_uilist.list_action " , icon = ' TRIA_UP ' , text = " " ) . action = ' UP '
col . operator ( " custom_metadata_fields_uilist.list_action " , icon = ' TRIA_DOWN ' , text = " " ) . action = ' DOWN '
2022-04-18 15:06:04 +00:00
2022-03-11 01:03:20 +00:00
row = layout . row ( )
2022-04-18 15:06:04 +00:00
col = row . column ( align = True )
row = col . row ( align = True )
row . label ( text = f " *Field Names must be unique. " )
row = col . row ( align = True )
2022-04-20 01:04:17 +00:00
row . operator ( " custom_metadata_fields_uilist.clear_list " , icon = " X " )
2022-03-11 01:03:20 +00:00
2022-05-10 12:14:53 +00:00
row = layout . row ( )
row . prop ( input_tool_scene , " batchToGenerate " )
save_path = bpy . path . abspath ( bpy . context . scene . input_tool . save_path )
Blend_My_NFTs_Output = os . path . join ( save_path , " Blend_My_NFTs Output " , " NFT_Data " )
batch_json_save_path = os . path . join ( Blend_My_NFTs_Output , " Batch_Data " )
nftBatch_save_path = os . path . join ( save_path , " Blend_My_NFTs Output " , " Generated NFT Batches " )
2022-08-24 13:57:59 +00:00
fail_state , failed_batch , failed_dna , failed_dna_index = Helpers . check_FailedBatches ( batch_json_save_path )
2022-05-10 12:14:53 +00:00
if fail_state :
row = layout . row ( )
2022-05-31 02:45:39 +00:00
self . layout . operator ( " exporter.nfts " , icon = ' RENDER_RESULT ' , text = " Generate NFTs & Create Metadata " )
2022-05-10 12:14:53 +00:00
row = layout . row ( )
row . alert = True
row . operator ( " exporter.resume_nfts " , icon = ' ERROR ' , text = " Resume Failed Batch " )
if not fail_state :
row = layout . row ( )
2022-05-31 02:45:39 +00:00
self . layout . operator ( " exporter.nfts " , icon = ' RENDER_RESULT ' , text = " Generate NFTs & Create Metadata " )
2022-05-10 12:14:53 +00:00
class BMNFTS_PT_Refactor ( bpy . types . Panel ) :
2022-05-31 02:45:39 +00:00
bl_label = " Refactor Batches "
2022-05-10 12:14:53 +00:00
bl_idname = " BMNFTS_PT_Refactor "
bl_space_type = ' VIEW_3D '
bl_region_type = ' UI '
bl_category = ' Blend_My_NFTs '
def draw ( self , context ) :
layout = self . layout
scene = context . scene
input_tool_scene = scene . input_tool
row = layout . row ( )
layout . label ( text = " Ensure all batches have been created before refactoring. " )
layout . label ( text = " Refactoring combines all batches into one easy to manage folder. " )
2022-03-11 01:03:20 +00:00
row = layout . row ( )
2022-05-31 02:45:39 +00:00
self . layout . operator ( " refactor.batches " , icon = ' FOLDER_REDIRECT ' , text = " Refactor Batches " )
2022-02-02 15:37:42 +00:00
2022-04-17 20:42:47 +00:00
2022-04-14 02:18:09 +00:00
class BMNFTS_PT_Other ( bpy . types . Panel ) :
bl_label = " Other "
bl_idname = " BMNFTS_PT_Other "
2022-02-04 14:44:36 +00:00
bl_space_type = ' VIEW_3D '
bl_region_type = ' UI '
bl_category = ' Blend_My_NFTs '
def draw ( self , context ) :
layout = self . layout
scene = context . scene
2022-04-14 02:18:09 +00:00
input_tool_scene = scene . input_tool
2022-04-11 00:00:19 +00:00
2022-04-14 02:18:09 +00:00
"""
2022-08-11 13:48:01 +00:00
Other :
A place to store miscellaneous settings , features , and external links that the user may find useful but doesn ' t
want to get in the way of their work flow .
2022-04-14 02:18:09 +00:00
Export Settings :
This panel gives the user the option to export all settings from the Blend_My_NFTs addon into a config file . Settings
will be read from the config file when running heedlessly .
"""
2022-08-11 13:48:01 +00:00
row = layout . row ( )
row . prop ( input_tool_scene , " enableAutoSave " )
# Auto Shutdown:
row = layout . row ( )
row . prop ( input_tool_scene , " enableAutoShutdown " )
row . label ( text = " *Must Run Blender as Admin " )
if bpy . context . scene . input_tool . enableAutoShutdown :
row = layout . row ( )
row . prop ( input_tool_scene , " specify_timeBool " )
time_row1 = layout . row ( )
time_row1 . label ( text = f " Hours " )
time_row1 . prop ( input_tool_scene , " hours " , text = " " )
time_row2 = layout . row ( )
time_row2 . label ( text = f " Minutes " )
time_row2 . prop ( input_tool_scene , " minutes " , text = " " )
if not bpy . context . scene . input_tool . specify_timeBool :
time_row1 . enabled = False
time_row2 . enabled = False
else :
time_row1 . enabled = True
time_row2 . enabled = True
layout . separator ( )
row = layout . row ( )
row . prop ( input_tool_scene , " emailNotificationBool " )
row . label ( text = " *Windows 10+ only " )
if bpy . context . scene . input_tool . emailNotificationBool :
row = layout . row ( )
row . prop ( input_tool_scene , " sender_from " )
row = layout . row ( )
row . prop ( input_tool_scene , " email_password " )
layout . separator ( )
row = layout . row ( )
row . prop ( input_tool_scene , " receiver_to " )
layout . separator ( )
2022-04-14 02:18:09 +00:00
layout . label ( text = f " Running Blend_My_NFTs Headless: " )
2022-04-11 02:41:12 +00:00
2022-04-14 02:18:09 +00:00
save_path = bpy . path . abspath ( bpy . context . scene . input_tool . save_path )
2022-04-12 08:37:28 +00:00
2022-04-14 02:18:09 +00:00
if save_path and os . path . isdir ( save_path ) :
row = layout . row ( )
self . layout . operator ( " export.settings " , icon = ' FOLDER_REDIRECT ' , text = " Export BMNFTs Settings to a File " )
else :
row = layout . row ( )
layout . label ( text = f " **Set a Save Path in Create NFT Data to Export Settings " )
2022-04-11 02:41:12 +00:00
2022-08-24 12:56:10 +00:00
row = layout . row ( )
row . prop ( input_tool_scene , " enable_debug " )
2022-04-17 20:42:47 +00:00
row = layout . row ( )
row = layout . row ( )
layout . label ( text = f " Looking for help? " )
2022-04-14 02:18:09 +00:00
row = layout . row ( )
row . operator ( " wm.url_open " , text = " Blend_My_NFTs Documentation " ,
icon = ' URL ' ) . url = " https://github.com/torrinworx/Blend_My_NFTs "
2022-04-11 17:20:00 +00:00
2022-04-14 02:18:09 +00:00
row = layout . row ( )
row . operator ( " wm.url_open " , text = " YouTube Tutorials " ,
icon = ' URL ' ) . url = " https://www.youtube.com/watch?v=ygKJYz4BjRs&list=PLuVvzaanutXcYtWmPVKu2bx83EYNxLRsX "
2022-04-17 20:42:47 +00:00
row = layout . row ( )
row . operator ( " wm.url_open " , text = " Join Our Discord Community! " ,
icon = ' URL ' ) . url = " https://discord.gg/UpZt5Un57t "
2022-05-25 23:58:33 +00:00
row = layout . row ( )
layout . label ( text = f " { BMNFTS_VERSION } , { LAST_UPDATED } " )
2022-04-17 20:42:47 +00:00
2022-04-14 02:18:09 +00:00
# ======== Blender add-on register/unregister handling ======== #
2022-02-03 00:40:05 +00:00
classes = (
2022-08-11 13:48:01 +00:00
# Property Group Classes:
BMNFTS_PGT_Input_Properties ,
2022-02-04 14:44:36 +00:00
2022-08-11 13:48:01 +00:00
# Operator Classes:
createData ,
exportNFTs ,
resume_failed_batch ,
refactor_Batches ,
export_settings ,
2022-04-14 02:18:09 +00:00
2022-08-11 13:48:01 +00:00
# Panel Classes:
BMNFTS_PT_CreateData ,
BMNFTS_PT_GenerateNFTs ,
BMNFTS_PT_Refactor ,
BMNFTS_PT_Other ,
) + Custom_Metadata_UIList . classes_Custom_Metadata_UIList + Logic_UIList . classes_Logic_UIList
2022-02-02 15:37:42 +00:00
2022-04-17 20:42:47 +00:00
2022-02-02 15:37:42 +00:00
def register ( ) :
for cls in classes :
bpy . utils . register_class ( cls )
2022-04-14 02:18:09 +00:00
bpy . types . Scene . input_tool = bpy . props . PointerProperty ( type = BMNFTS_PGT_Input_Properties )
2022-02-02 15:37:42 +00:00
2022-08-11 13:48:01 +00:00
bpy . types . Scene . custom_metadata_fields = CollectionProperty (
type = Custom_Metadata_UIList . CUSTOM_custom_metadata_fields_objectCollection )
2022-04-20 01:04:17 +00:00
bpy . types . Scene . custom_metadata_fields_index = IntProperty ( )
bpy . types . Scene . logic_fields = CollectionProperty ( type = Logic_UIList . CUSTOM_logic_objectCollection )
bpy . types . Scene . logic_fields_index = IntProperty ( )
2022-04-17 20:42:47 +00:00
2022-08-11 13:48:01 +00:00
2022-02-02 15:37:42 +00:00
def unregister ( ) :
2022-04-18 15:06:04 +00:00
for cls in reversed ( classes ) :
2022-02-02 15:37:42 +00:00
bpy . utils . unregister_class ( cls )
2022-04-14 02:18:09 +00:00
del bpy . types . Scene . input_tool
2022-04-12 08:37:28 +00:00
2022-04-20 01:04:17 +00:00
del bpy . types . Scene . custom_metadata_fields
del bpy . types . Scene . custom_metadata_fields_index
del bpy . types . Scene . logic_fields
del bpy . types . Scene . logic_fields_index
2022-04-12 08:37:28 +00:00
2022-04-12 05:39:58 +00:00
2022-02-02 15:37:42 +00:00
if __name__ == ' __main__ ' :
register ( )
2022-04-14 02:18:09 +00:00
runAsHeadless ( )