forked from blender/blender
BLEN-368: Fixes in hydra.py #15
114
release/scripts/modules/bpy_hydra.py
Normal file
114
release/scripts/modules/bpy_hydra.py
Normal file
@ -0,0 +1,114 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
"""
|
||||
Implementation of class `HydraRenderEngine`.
|
||||
|
||||
Render Blender addon with Hydra render delegate should inherit `HydraRenderEngine`.
|
||||
Example:
|
||||
```
|
||||
import bpy_hydra
|
||||
|
||||
class CustomHydraRenderEngine(HydraRenderEngine):
|
||||
bl_idname = 'CustomHydraRenderEngine'
|
||||
bl_label = "Hydra: Custom"
|
||||
bl_info = "Hydra Custom render delegate"
|
||||
|
||||
delegate_id = 'HdCustomRendererPlugin'
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
super().register()
|
||||
|
||||
bpy_hydra.register_plugins(["/path/to/plugin")], ["/additional/system/path")])
|
||||
|
||||
def get_delegate_settings(self, engine_type):
|
||||
return {
|
||||
'setting1': 1,
|
||||
'setting2': "2",
|
||||
}
|
||||
```
|
||||
"""
|
||||
|
||||
__all__ = (
|
||||
"HydraRenderEngine",
|
||||
"export_mtlx",
|
||||
"register_plugins",
|
||||
"get_render_plugins",
|
||||
)
|
||||
|
||||
import bpy
|
||||
import _bpy_hydra
|
||||
|
||||
from _bpy_hydra import register_plugins, get_render_plugins
|
||||
|
||||
|
||||
class HydraRenderEngine(bpy.types.RenderEngine):
|
||||
""" Render addon with Hydra render delegate should inherit this class """
|
||||
|
||||
bl_use_shading_nodes_custom = False
|
||||
|
||||
delegate_id = ''
|
||||
engine_ptr = None
|
||||
|
||||
def __del__(self):
|
||||
if not self.engine_ptr:
|
||||
return
|
||||
|
||||
_bpy_hydra.engine_free(self.engine_ptr)
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
_bpy_hydra.init()
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
pass
|
||||
|
||||
def get_delegate_settings(self, engine_type):
|
||||
return {}
|
||||
|
||||
# final render
|
||||
def update(self, data, depsgraph):
|
||||
pass
|
||||
|
||||
def render(self, depsgraph):
|
||||
engine_type = 'PREVIEW' if self.is_preview else 'FINAL'
|
||||
|
||||
self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), engine_type, self.delegate_id)
|
||||
delegate_settings = self.get_delegate_settings(engine_type)
|
||||
|
||||
_bpy_hydra.engine_sync(self.engine_ptr, depsgraph.as_pointer(), bpy.context.as_pointer(), delegate_settings)
|
||||
_bpy_hydra.engine_render(self.engine_ptr, depsgraph.as_pointer())
|
||||
|
||||
# viewport render
|
||||
def view_update(self, context, depsgraph):
|
||||
if not self.engine_ptr:
|
||||
self.engine_ptr = _bpy_hydra.engine_create(self.as_pointer(), 'VIEWPORT', self.delegate_id)
|
||||
|
||||
delegate_settings = self.get_delegate_settings('VIEWPORT')
|
||||
_bpy_hydra.engine_sync(self.engine_ptr, depsgraph.as_pointer(), context.as_pointer(), delegate_settings)
|
||||
|
||||
def view_draw(self, context, depsgraph):
|
||||
if not self.engine_ptr:
|
||||
return
|
||||
|
||||
_bpy_hydra.engine_view_draw(self.engine_ptr, depsgraph.as_pointer(), context.as_pointer())
|
||||
|
||||
|
||||
def export_mtlx(material):
|
||||
""" Exports material to .mtlx file. It is called from Blender source code. """
|
||||
try:
|
||||
import materialx.utils as mx_utils
|
||||
|
||||
doc = mx_utils.export(material, None)
|
||||
if not doc:
|
||||
return ""
|
||||
|
||||
mtlx_file = mx_utils.get_temp_file(".mtlx", material.name)
|
||||
mx_utils.export_to_file(doc, mtlx_file, export_deps=True, copy_deps=False)
|
||||
return str(mtlx_file)
|
||||
|
||||
except ImportError:
|
||||
print("ERROR: no MaterialX addon available")
|
||||
|
||||
return ""
|
@ -1,85 +0,0 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Copyright 2011-2022 Blender Foundation
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
import traceback
|
||||
|
||||
import bpy
|
||||
import _hydra
|
||||
|
||||
from _hydra import register_plugins, get_render_plugins
|
||||
|
||||
|
||||
class HydraRenderEngine(bpy.types.RenderEngine):
|
||||
bl_use_preview = True
|
||||
bl_use_shading_nodes_custom = False
|
||||
|
||||
delegate_id = ''
|
||||
engine_ptr = None
|
||||
|
||||
def __del__(self):
|
||||
if not self.engine_ptr:
|
||||
return
|
||||
|
||||
_hydra.engine_free(self.engine_ptr)
|
||||
|
||||
@classmethod
|
||||
def register(cls):
|
||||
_hydra.init()
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
pass
|
||||
|
||||
def get_delegate_settings(self, engine_type):
|
||||
return {}
|
||||
|
||||
# final render
|
||||
def update(self, data, depsgraph):
|
||||
pass
|
||||
|
||||
def render(self, depsgraph):
|
||||
engine_type = 'PREVIEW' if self.is_preview else 'FINAL'
|
||||
|
||||
self.engine_ptr = _hydra.engine_create(self.as_pointer(), engine_type, self.delegate_id)
|
||||
delegate_settings = self.get_delegate_settings(engine_type)
|
||||
|
||||
_hydra.engine_sync(self.engine_ptr, depsgraph.as_pointer(), bpy.context.as_pointer(), delegate_settings)
|
||||
_hydra.engine_render(self.engine_ptr, depsgraph.as_pointer())
|
||||
|
||||
# viewport render
|
||||
def view_update(self, context, depsgraph):
|
||||
if not self.engine_ptr:
|
||||
self.engine_ptr = _hydra.engine_create(self.as_pointer(), 'VIEWPORT', self.delegate_id)
|
||||
|
||||
delegate_settings = self.get_delegate_settings('VIEWPORT')
|
||||
_hydra.engine_sync(self.engine_ptr, depsgraph.as_pointer(), context.as_pointer(), delegate_settings)
|
||||
|
||||
def view_draw(self, context, depsgraph):
|
||||
if not self.engine_ptr:
|
||||
return
|
||||
|
||||
_hydra.engine_view_draw(self.engine_ptr, depsgraph.as_pointer(), context.as_pointer())
|
||||
|
||||
|
||||
def export_mtlx(material_name):
|
||||
try:
|
||||
import materialx.utils as mx_utils
|
||||
|
||||
material = bpy.data.materials[material_name]
|
||||
doc = mx_utils.export(material, None)
|
||||
if not doc:
|
||||
return ""
|
||||
|
||||
mtlx_file = mx_utils.get_temp_file(".mtlx", material.name)
|
||||
mx_utils.export_to_file(doc, mtlx_file, export_deps=True, copy_deps=False)
|
||||
return str(mtlx_file)
|
||||
|
||||
except ImportError:
|
||||
print("ERROR: no MaterialX addon available")
|
||||
|
||||
except Exception as e:
|
||||
print("ERROR:", e, traceback.format_exc())
|
||||
|
||||
return ""
|
@ -256,8 +256,8 @@ static PyObject *CCL_initPython(void)
|
||||
#endif
|
||||
|
||||
#ifdef WITH_HYDRA
|
||||
/* defined in USD Hydra module */
|
||||
extern PyObject *Hydra_initPython(void);
|
||||
/* defined in render_hydra module */
|
||||
extern PyObject *BPyInit_hydra(void);
|
||||
#endif
|
||||
|
||||
static struct _inittab bpy_internal_modules[] = {
|
||||
@ -290,7 +290,7 @@ static struct _inittab bpy_internal_modules[] = {
|
||||
{"gpu", BPyInit_gpu},
|
||||
{"idprop", BPyInit_idprop},
|
||||
#ifdef WITH_HYDRA
|
||||
{"_hydra", Hydra_initPython},
|
||||
{"_bpy_hydra", BPyInit_hydra},
|
||||
#endif
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
@ -34,7 +34,9 @@ set(INC
|
||||
../../gpu
|
||||
../../gpu/opengl
|
||||
../../gpu/intern
|
||||
../../python/intern
|
||||
..
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna/intern
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
@ -266,7 +266,7 @@ static PyMethodDef methods[] = {
|
||||
|
||||
static struct PyModuleDef module = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_hydra",
|
||||
"_bpy_hydra",
|
||||
"Hydra render API",
|
||||
-1,
|
||||
methods,
|
||||
@ -282,7 +282,7 @@ static struct PyModuleDef module = {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
PyObject *Hydra_initPython(void)
|
||||
PyObject *BPyInit_hydra(void)
|
||||
{
|
||||
PyObject *mod = PyModule_Create(&blender::render::hydra::module);
|
||||
return mod;
|
||||
|
@ -12,6 +12,10 @@
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_material.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "RNA_blender_cpp.h"
|
||||
#include "bpy_rna.h"
|
||||
|
||||
#include "blender_scene_delegate.h"
|
||||
#include "material.h"
|
||||
#include "mtlx_hydra_adapter.h"
|
||||
@ -74,14 +78,26 @@ void MaterialData::export_mtlx()
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
PyObject *module, *dict, *func, *result;
|
||||
module = PyImport_ImportModule("hydra");
|
||||
module = PyImport_ImportModule("bpy_hydra");
|
||||
dict = PyModule_GetDict(module);
|
||||
func = PyDict_GetItemString(dict, "export_mtlx");
|
||||
result = PyObject_CallFunction(func, "s", name().c_str());
|
||||
|
||||
std::string path = PyUnicode_AsUTF8(result);
|
||||
PointerRNA materialptr;
|
||||
RNA_pointer_create(NULL, &RNA_Material, id, &materialptr);
|
||||
PyObject *material = pyrna_struct_CreatePyObject(&materialptr);
|
||||
|
||||
Py_DECREF(result);
|
||||
result = PyObject_CallFunction(func, "O", material);
|
||||
|
||||
Py_DECREF(material);
|
||||
|
||||
std::string path;
|
||||
if (result) {
|
||||
path = PyUnicode_AsUTF8(result);
|
||||
Py_DECREF(result);
|
||||
}
|
||||
else {
|
||||
PyErr_Print();
|
||||
}
|
||||
Py_DECREF(module);
|
||||
|
||||
PyGILState_Release(gstate);
|
||||
|
Loading…
Reference in New Issue
Block a user