2
# Copyright 2011, Blender Foundation.
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software Foundation,
16
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25
def osl_compile(input_path, report):
26
"""compile .osl file with given filepath to temporary .oso file"""
28
output_file = tempfile.NamedTemporaryFile(mode='w', suffix=".oso", delete=False)
29
output_path = output_file.name
32
ok = _cycles.osl_compile(input_path, output_path)
35
report({'INFO'}, "OSL shader compilation succeeded")
37
return ok, output_path
40
def update_script_node(node, report):
41
"""compile and update shader script node"""
46
if node.mode == 'EXTERNAL':
47
# compile external script file
48
script_path = bpy.path.abspath(node.filepath, library=node.id_data.library)
49
script_path_noext, script_ext = os.path.splitext(script_path)
51
if script_ext == ".oso":
52
# it's a .oso file, no need to compile
53
ok, oso_path = True, script_path
54
oso_file_remove = False
55
elif script_ext == ".osl":
57
ok, oso_path = osl_compile(script_path, report)
58
oso_file_remove = True
61
# copy .oso from temporary path to .osl directory
62
dst_path = script_path_noext + ".oso"
64
shutil.copy2(oso_path, dst_path)
66
report({'ERROR'}, "Failed to write .oso file next to external .osl file at " + dst_path)
67
elif os.path.dirname(node.filepath) == "":
68
# module in search path
69
oso_path = node.filepath
70
oso_file_remove = False
74
report({'ERROR'}, "External shader script must have .osl or .oso extension, or be a module name")
79
node.bytecode_hash = ""
81
elif node.mode == 'INTERNAL' and node.script:
82
# internal script, we will store bytecode in the node
84
osl_path = bpy.path.abspath(script.filepath, library=script.library)
86
if script.is_in_memory or script.is_dirty or script.is_modified or not os.path.exists(osl_path):
87
# write text datablock contents to temporary file
88
osl_file = tempfile.NamedTemporaryFile(mode='w', suffix=".osl", delete=False)
89
osl_file.write(script.as_string())
92
ok, oso_path = osl_compile(osl_file.name, report)
93
oso_file_remove = False
94
os.remove(osl_file.name)
96
# compile text datablock from disk directly
97
ok, oso_path = osl_compile(osl_path, report)
98
oso_file_remove = False
103
oso = open(oso_path, 'r')
104
node.bytecode = oso.read()
108
traceback.print_exc()
110
report({'ERROR'}, "Can't read OSO bytecode to store in node at %r" % oso_path)
114
report({'WARNING'}, "No text or file specified in node, nothing to compile")
118
# now update node with new sockets
119
ok = _cycles.osl_update_node(node.id_data.as_pointer(), node.as_pointer(), oso_path)
122
report({'ERROR'}, "OSL query failed to open " + oso_path)
124
report({'ERROR'}, "OSL script compilation failed, see console for errors")
126
# remove temporary oso file