Skip to content

Commit 0bc6289

Browse files
authored
Add files via upload
1 parent e15b54f commit 0bc6289

3 files changed

Lines changed: 214 additions & 17 deletions

File tree

1.49 MB
Binary file not shown.

fast_pbr_viewport_render/__init__.py

Lines changed: 207 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,85 @@
33
from typing import TYPE_CHECKING
44

55
import bpy
6-
# from "C:/Program Files/Blender Foundation/blender-3.0.0-alpha+master.2b64b4d90d67-windows.amd64-release/3.0/scripts/addons/fast_pbr_viewport_render/fileRenamer.py" import moveImages
7-
import os
8-
from .fileRenamer import *
9-
import glob
6+
7+
import bpy
8+
import subprocess
9+
import sys
1010

1111
bl_info = {
1212
"name": "Fast PBR Viewport Render",
1313
"blender": (3, 00, 0),
1414
"category": "Object",
1515
}
1616

17-
pathToStoreImagesIn = "C:/FromFastPBR/"
1817

18+
# installPackage('PILLOW')
19+
# installPackage('numpy')
1920
__name__ # This is the name of the folder that the __init__.py is in. I think
2021
addonName: str = bl_info["name"]
2122
addonNameShort: str = "Fast PBR"
2223

24+
import importlib
25+
def putTextInBox(text):
26+
lines = text.splitlines()
27+
width = max(len(s) for s in lines)
28+
res = ['┌' + '─' * width + '┐']
29+
for s in lines:
30+
res.append('│' + (s + ' ' * width)[:width] + '│')
31+
res.append('└' + '─' * width + '┘')
32+
return '\n'.join(res)
33+
def installPackage(package: str):
34+
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
35+
36+
# Running installPackage is a slow operation, therefore we want to make sure that we only run it when necessary, hence this function to speed up registration/activation time of the addon SIGNIFICANTLY (like by 5-10 seconds).
37+
def attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist(packageName, moduleName):
38+
print("Attempting")
39+
try:
40+
importlib.import_module(moduleName)
41+
# from PIL import Image
42+
except Exception as error:
43+
print(putTextInBox(f"{addonName}Error: ---\n{error}\n---\nwhen attempting to import {moduleName}, we're assuming that you dont have {packageName} installed and will try to install it for you!"))
44+
installPackage(packageName)
45+
importlib.import_module(moduleName) # Doesnt actually work?
46+
ListOfModulesToAttemptToImportAndInstallItIfItIfTheCorespondingPackageDoesntExist = [['PILLOW', 'PIL'], ['numpy']]
47+
attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist('PILLOW', 'PIL')
48+
import PIL
49+
attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist('numpy', 'numpy')
50+
import numpy
51+
# import pi
52+
# attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist('PILLOW', 'PIL')
53+
# attemptToImportModuleAndInstallItIfItIfTheCorespondingPackageDoesntExist('numpy', 'numpy')
54+
# from PIL import Images
55+
# if TYPE_CHECKING: # Importing packages just for intellisense as our import function wont run through VS Codes intellisense engine.
56+
57+
# import numpy
58+
# print(help(numpy))
59+
60+
61+
# materialToReplaceTo = ""
62+
# materialToReplaceFrom = ""
63+
64+
# bpy.ops.ed.undo_push()
65+
66+
# for object in bpy.context.scene.objects:
67+
# object: bpy.types.Object
68+
# for materialSlot in object.material_slots:
69+
# materialSlot: bpy.types.MaterialSlot
70+
# if materialSlot.material.name_full == materialToReplaceFrom:
71+
# materialSlot.material = bpy.data.materials.get(materialToReplaceTo)
72+
73+
74+
75+
# from "C:/Program Files/Blender Foundation/blender-3.0.0-alpha+master.2b64b4d90d67-windows.amd64-release/3.0/scripts/addons/fast_pbr_viewport_render/fileRenamer.py" import moveImages
76+
import os
77+
from .fileRenamer import *
78+
import glob
79+
80+
81+
pathToStoreImagesIn = "C:/FromFastPBR/"
82+
83+
84+
2385

2486

2587
classesToRegister = list()
@@ -33,12 +95,26 @@
3395
disableRestore = True # Set to true for debugging
3496

3597
# addonNameShort = "Fast PBR"
36-
98+
import pathlib
99+
pathToAddonDirectory = str(pathlib.Path(__file__).parent.resolve())
100+
nameOfAssetsFileWithoutPath = 'FastPBRAssets.blend'
101+
pathToAssetsFile = pathToAddonDirectory + '/' + nameOfAssetsFileWithoutPath
102+
#
37103

38104
#############################
39105
##### Utility functions #####
40106
#############################
41107
# @bookmark Utility functions
108+
def appendAssetFromAssetsBlendFile(dataBlockToAppend: str, blendFileDataCategory: str):
109+
"""
110+
dataBlockToAppend is the name of the object/material/whatever you want to append.
111+
blendFileDataCategory is the type of data you want to append, if you go into the outliner > display mode > Data API you will see all these categories. Example values: "Material", "Object", "Node Groups" (etc). For some reason, the "s" at the end of some categories displayed in that list is not supposed to be included, which is rather confusing :)
112+
"""
113+
bpy.ops.wm.append(filename=dataBlockToAppend, directory=pathToAssetsFile + '\\' + blendFileDataCategory + '\\')
114+
115+
print("filepath:", nameOfAssetsFileWithoutPath)
116+
print("directory:", pathToAssetsFile + '\\' + blendFileDataCategory)
117+
print("filename:", dataBlockToAppend)
42118

43119
def containsLowerCase(string):
44120
# string: str = ""
@@ -92,14 +168,6 @@ def insertSpaceAfterCapital(string):
92168
return outputString
93169

94170

95-
def putTextInBox(text):
96-
lines = text.splitlines()
97-
width = max(len(s) for s in lines)
98-
res = ['┌' + '─' * width + '┐']
99-
for s in lines:
100-
res.append('│' + (s + ' ' * width)[:width] + '│')
101-
res.append('└' + '─' * width + '┘')
102-
return '\n'.join(res)
103171

104172
############################
105173
# End of Utility functions #
@@ -1149,6 +1217,11 @@ def draw(cls, context):
11491217
# cls.layout.label(text=f"{cls.bl_label}First Sub Panel of Panel 1.")
11501218
# print("LOOK HERE ", f'{cls.settings.enable_pass=}'.split('=')[0].split('.')[-1])
11511219
cls.layout.prop(retrieveSettings(cls), f'{cls.settings.enable_pass=}'.split('=')[0].split('.')[-1])
1220+
cls.draw_pass_specific_ui_elements(context)
1221+
1222+
1223+
def draw_pass_specific_ui_elements(cls, context):
1224+
pass
11521225

11531226
##########
11541227
# UI END #
@@ -1193,7 +1266,8 @@ def save_to_disk(self):
11931266
# image.save_render(pathToStoreImagesIn, "test")
11941267
# image.filepath_raw = 'C:\FastPBRViewportRender'
11951268
# image.file_format = 'PNG'
1196-
pathToStoreImageInIncludingFileNameAndFileExtension = 'C:/FastPBRViewportRender/'
1269+
# pathToStoreImageInIncludingFileNameAndFileExtension = 'C:/FastPBRViewportRender/'
1270+
pathToStoreImageInIncludingFileNameAndFileExtension = pathToStoreImagesIn
11971271
pathToStoreImageInIncludingFileNameAndFileExtension = pathToStoreImageInIncludingFileNameAndFileExtension + self.passName + ".png"
11981272
# bpy.context.scene.render.__format__
11991273
# image = bpy.data.images.new("Sprite", alpha=True, width=16, height=16)
@@ -1212,17 +1286,79 @@ def save_to_disk(self):
12121286
# bpy.ops.image.save_as(save_as_render=True, copy=True, filepath="//..\\..\\untitled321.png", relative_path=True, show_multiview=False, use_multiview=False)
12131287
# bpy.ops.image.
12141288

1289+
@classmethod
1290+
def perform_post_process(self):
1291+
"""Runs after save_to_disk"""
1292+
pass
12151293

12161294
@classmethod
12171295
def prepare_render_and_save(self):
12181296
self.prepare_to_render()
12191297
if retrieveSettingsUsing__name__insteadOfbl_idname(self).enable_pass:
12201298
self.render()
12211299
self.save_to_disk()
1300+
self.perform_post_process()
12221301

12231302
# classesToRegister.append(classesToRegister.append(RenderPass))
12241303
# @bookmark Normal pass
12251304

1305+
1306+
class RenderAppendedMaterialTypeRenderPass(RenderPass): # A base class for render passes that are supposed to render a specific material only
1307+
f"""To use this class, assign the literal name of the material in our assets file that you want to render to the materialToRender variable.
1308+
1309+
Children of this class are typically found towards the bottom of the render pass section as its rendered in Eeevee."""
1310+
1311+
materialToRender = 'FastPBRNormal'
1312+
"""This is the literal name of the material in our assets file that you want to render!"""
1313+
1314+
@classmethod
1315+
def prepare_to_render(self):
1316+
bpy.context.space_data.shading.render_pass = 'DIFFUSE_COLOR'
1317+
bpy.context.scene.render.engine = 'BLENDER_EEVEE'
1318+
# bpy.context
1319+
# bpy.context.scene.render.engine = 'RENDER'
1320+
# Switch viewport view to rendered, rather than solid or wire or whatever.
1321+
bpy.context.space_data.shading.type = 'RENDERED'
1322+
1323+
1324+
print("File path:", pathlib.Path(__file__).parent.resolve())
1325+
1326+
if bpy.data.materials.find(self.materialToRender) < 0:
1327+
appendAssetFromAssetsBlendFile(self.materialToRender, 'Material')
1328+
for object in bpy.data.objects:
1329+
object: bpy.types.Object
1330+
for materialSlot in object.material_slots:
1331+
materialSlot: bpy.types.MaterialSlot
1332+
# materialSlot.link = 'FastPBRNormal'
1333+
materialSlot.material = bpy.data.materials.get(self.materialToRender)
1334+
1335+
@classmethod
1336+
def perform_post_process(self):
1337+
pathToStoreImageInIncludingFileNameAndFileExtension = pathToStoreImagesIn
1338+
fileToPerformPostProcessOn = pathToStoreImageInIncludingFileNameAndFileExtension + self.passName + ".png"
1339+
1340+
print("hello from post process")
1341+
# from PIL import Image
1342+
# import numpy
1343+
1344+
im = Image.open(fileToPerformPostProcessOn)
1345+
im = im.convert('RGBA')
1346+
1347+
data = numpy.array(im) # "data" is a height x width x 4 numpy array
1348+
red, green, blue, alpha = data.T # Temporarily unpack the bands for readability
1349+
1350+
# Replace white with red... (leaves alpha values alone...)
1351+
white_areas = (red < 3) & (blue < 3) & (green < 3)
1352+
data[..., :-1][white_areas.T] = (128, 128, 255) # Transpose back needed
1353+
# white_areas = (red == 1) & (blue == 1) & (green == 1)
1354+
# data[..., :-1][white_areas.T] = (128, 128, 255) # Transpose back needed
1355+
1356+
im2 = Image.fromarray(data)
1357+
im2 = im2.convert('RGB')
1358+
im2.save(fileToPerformPostProcessOn)
1359+
im2.show()
1360+
print("Second hello")
1361+
12261362
@renderPassDecorator
12271363
class RenderNormalPassWithWorkbench(RenderPass):
12281364
passName = "normal"
@@ -1420,6 +1556,13 @@ def prepare_to_render(self):
14201556
bpy.context.scene.display.shading.single_color = (999, 999, 999)
14211557

14221558

1559+
1560+
@renderPassDecorator
1561+
class RenderNormalFromAppendedMaterial(RenderAppendedMaterialTypeRenderPass):
1562+
passName = "normal"
1563+
materialToRender = 'FastPBRNormal'
1564+
def draw_pass_specific_ui_elements(cls, context):
1565+
label_multiline(f"""Compared to rendering the normal pass with workbench, this pass has the advantage of that it totally ignores whether faces are pointing the wrong direction or not, they will always appear like as if they were pointing towards the camera, or a direction that has a maximum of a 90 degree angle from the camera. A downside of this pass is that it might not be able to replace the material of all objects if you have objects from other files linked in your blend.""",context,cls.layout)
14231566

14241567

14251568
###################################################################################
@@ -1481,6 +1624,8 @@ class FastPBRViewportRender(OperatorBaseClass):
14811624
# bl_label = "Fast PBR viewport render" # Display name in the interface.
14821625
# bl_options = {'REGISTER', 'UNDO'} # Enable undo for the operator.
14831626

1627+
1628+
14841629
def test(self):
14851630
print("wot")
14861631
def execute(self, context): # execute() is called when running the operator.
@@ -1494,6 +1639,53 @@ def execute(self, context): # execute() is called when running the operat
14941639
# renderNormalPassWithWorkbench.prepare_render_and_save()
14951640
BackupPrepareAndRestore.backupSettingsAndPrepareForRender()
14961641

1642+
# bpy.ops.wm.append(
1643+
# filepath="cube.blend",
1644+
# directory="/home/lucas/Desktop/cube.blend\\Object\\",
1645+
# filename="Cube")
1646+
1647+
##################################################
1648+
# import pathlib
1649+
# pathToAddonDirectory = str(pathlib.Path(__file__).parent.resolve())
1650+
# nameOfAssetsFileWithoutPath = 'FastPBRAssets.blend'
1651+
# pathToAssetsFile = pathToAddonDirectory + '/' + nameOfAssetsFileWithoutPath
1652+
# #
1653+
# def appendAssetFromAssetsBlendFile(dataBlockToAppend: str, blendFileDataCategory: str):
1654+
# """
1655+
# dataBlockToAppend is the name of the object/material/whatever you want to append.
1656+
1657+
# blendFileDataCategory is the type of data you want to append, if you go into the outliner > display mode > Data API you will see all these categories. Example values: "Material", "Object", "Node Groups" (etc). For some reason, the "s" at the end of some categories displayed in that list is not supposed to be included, which is rather confusing :)
1658+
# """
1659+
# bpy.ops.wm.append(filename=dataBlockToAppend, directory=pathToAssetsFile + '\\' + blendFileDataCategory + '\\')
1660+
1661+
# print("filepath:", nameOfAssetsFileWithoutPath)
1662+
# print("directory:", pathToAssetsFile + '\\' + blendFileDataCategory)
1663+
# print("filename:", dataBlockToAppend)
1664+
1665+
# pathToNormalAssetsFile = pathToAddonDirectory + '/' + 'FastPBRAssets.blend'
1666+
# print("File path:", pathlib.Path(__file__).parent.resolve())
1667+
1668+
# if bpy.data.materials.find('FastPBRNormal') < 0:
1669+
# appendAssetFromAssetsBlendFile('FastPBRNormal', 'Material')
1670+
# for object in bpy.data.objects:
1671+
# object: bpy.types.Object
1672+
# for materialSlot in object.material_slots:
1673+
# materialSlot: bpy.types.MaterialSlot
1674+
# # materialSlot.link = 'FastPBRNormal'
1675+
# materialSlot.material = bpy.data.materials.get('FastPBRNormal')
1676+
# materialSlot
1677+
################################################
1678+
1679+
# print("File path:", pathlib.Path(__file__).parent.resolve())
1680+
# bpy.ops.wm.append(
1681+
# filepath="cube.blend",
1682+
# directory=pathToAssetsFile,
1683+
# filename="Cube")
1684+
# bpy.ops.wm.append(
1685+
# filepath="cube.blend",
1686+
# directory="C:/Program Files/Blender Foundation/blender-3.0.0-alpha+master.2b64b4d90d67-windows.amd64-release/3.0/scripts/addons/fast_pbr_viewport_render/FastPBRAssets.blend\\Object",
1687+
# filename="Cube")
1688+
# return {'FINISHED'}
14971689

14981690
# print("IMPORTANTEEE" + getGlobalAddonProperties().target_directory)
14991691

fast_pbr_viewport_render/fileRenamer.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import subprocess
2+
import sys
3+
4+
5+
16
import shutil
27
import os
38
import glob
@@ -260,8 +265,8 @@ def moveImages(sourceDirectory, targetDirectory, replacementDictionary, removeOr
260265
while replaceFrom in preparedTargetDirectoryAndFileNameWithExtension:
261266
preparedTargetDirectoryAndFileNameWithExtension = preparedTargetDirectoryAndFileNameWithExtension.replace(replaceFrom, str(replaceTo))
262267
# print(targetDirectory, "--", replaceFrom, "--", replaceTo)
263-
if not targetDirectory.__contains__('.'):
264-
ShowMessageBox("The target directory must include the file name and its extension!", "Fast PBR", 'ERROR')
268+
if not preparedTargetDirectoryAndFileNameWithExtension.__contains__('.'):
269+
ShowMessageBox(f"The target directory {targetDirectory} must include the file name and its extension!", "Fast PBR", 'ERROR')
265270
return {'FINISHED'}
266271

267272

0 commit comments

Comments
 (0)