def pyrpr_init(bindings_import_path, rprsdk_bin_path):
    log("pyrpr_init: bindings_path=%s, rpr_bin_path=%s" %
        (bindings_import_path, rprsdk_bin_path))

    if bindings_import_path not in sys.path:
        sys.path.append(bindings_import_path)

    try:
        import pyrpr
        import pyhybrid
        import pyrpr2

        rpr_version = utils.core_ver_str(full=True)

        log.info(f"RPR Core version: {rpr_version}")
        pyrpr.lib_wrapped_log_calls = config.pyrpr_log_calls
        pyrpr.init(logging.Log(tag='core'), rprsdk_bin_path=rprsdk_bin_path)

        import pyrpr_load_store
        pyrpr_load_store.init(rprsdk_bin_path)

        import pyrprimagefilters
        rif_version = utils.rif_ver_str(full=True)
        log.info(f"Image Filters version {rif_version}")
        pyrprimagefilters.lib_wrapped_log_calls = config.pyrprimagefilters_log_calls
        pyrprimagefilters.init(log, rprsdk_bin_path=rprsdk_bin_path)

        # import pyrprgltf
        # pyrprgltf.lib_wrapped_log_calls = config.pyrprgltf_log_calls
        # pyrprgltf.init(log, rprsdk_bin_path=rprsdk_bin_path)

    except:
        logging.critical(traceback.format_exc(), tag='')
        return False

    finally:
        sys.path.remove(bindings_import_path)

    return True
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
from . import render_engine
from . import context_hybrid

from rprblender.operators.world import FOG_KEY

from rprblender.utils import logging
log = logging.Log(tag='render_engine_hybrid')


class RenderEngine(render_engine.RenderEngine):
    _RPRContext = context_hybrid.RPRContext

    def sync(self, depsgraph):
        super().sync(depsgraph)

        depsgraph.scene.rpr.export_render_quality(self.rpr_context)
        log('Finish sync')

    def depsgraph_objects(self, depsgraph, with_camera=False):
        for obj in super().depsgraph_objects(depsgraph, with_camera):
            if obj.name == FOG_KEY:
                continue
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
"""
This module exports following blender object types: 'CURVE', 'FONT', 'SURFACE', 'META'.
It converts such blender object into blender mesh and exports it as mesh.
"""

import bpy

from . import object, mesh

from rprblender.utils import logging
log = logging.Log(tag='export.to_mesh')


def sync(rpr_context, obj: bpy.types.Object, **kwargs):
    """ Converts object into blender's mesh and exports it as mesh """

    try:
        # This operation adds new mesh into bpy.data.meshes, that's why it should be removed after usage.
        # obj.to_mesh() could also return None for META objects.
        new_mesh = obj.to_mesh()
        log("sync", obj, new_mesh)

        if new_mesh:
            mesh.sync(rpr_context, obj, mesh=new_mesh, **kwargs)
            return True
Example #4
0
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import numpy as np
import bpy

from . import object, light, mesh
from rprblender.utils import logging
log = logging.Log(tag='export.instance')


def key(instance: bpy.types.DepsgraphObjectInstance):
    return (object.key(instance.parent), instance.random_id)


def get_transform(instance: bpy.types.DepsgraphObjectInstance):
    return np.array(instance.matrix_world, dtype=np.float32).reshape(4, 4)


def sync(rpr_context, instance: bpy.types.DepsgraphObjectInstance, **kwargs):
    """ sync the blender instance """

    assert instance.is_instance  # expecting: instance.is_instance == True
Example #5
0
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import bpy
import pyrpr

from .engine import Engine
from rprblender.export import object, camera, particle, world

from rprblender.utils import logging
log = logging.Log(tag='PreviewEngine')

CONTEXT_LIFETIME = 300.0  # 5 minutes in seconds


class PreviewEngine(Engine):
    """ Render engine for preview material, lights, environment """

    TYPE = 'PREVIEW'

    rpr_context = None

    def __init__(self, rpr_engine):
        super().__init__(rpr_engine)

        self.is_synced = False
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import numpy as np
import functools

import pyrpr
from rprblender.config import hybrid_unsupported_log_warn

from rprblender.utils import logging

log = logging.Log(tag='hybrid')


def ignore_unsupported(function):
    """Function decorator which ignores UNSUPPORTED and INVALID_PARAMETER core errors"""
    @functools.wraps(function)
    def wrapper(*args, **kwargs):
        try:
            return function(*args, **kwargs)

        except pyrpr.CoreError as e:
            if e.status not in (pyrpr.ERROR_UNSUPPORTED,
                                pyrpr.ERROR_INVALID_PARAMETER):
                raise

            if hybrid_unsupported_log_warn:
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************

import numpy as np

import bpy

from . import mesh, light, camera, to_mesh, volume, openvdb, particle, hair
from rprblender.utils import logging
log = logging.Log(tag='export.object')


def key(obj: bpy.types.Object):
    return obj.name


def get_transform(obj: bpy.types.Object):
    return np.array(obj.matrix_world, dtype=np.float32).reshape(4, 4)


def sync(rpr_context, obj: bpy.types.Object, **kwargs):
    """ sync the object and any data attached """

    from rprblender.engine.render_engine import RenderEngine
Example #8
0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import numpy as np

import bpy
import mathutils

from . import mesh, material, object

from rprblender.utils import logging
log = logging.Log(tag='export.particle')


def key(p_sys: bpy.types.ParticleSystem, emitter: bpy.types.Object):
    return (object.key(emitter), p_sys.name)


def get_particle_system_material(rpr_context, p_sys, emitter):
    """Returns the material set for this particle system or None if none set or some other issue"""

    if len(emitter.material_slots) == 0:
        return None

    if (p_sys.settings.material - 1) < len(emitter.material_slots):
        slot = emitter.material_slots[p_sys.settings.material - 1]
    else:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import bpy

from rprblender.engine.context import RPRContext
from rprblender.nodes.blender_nodes import ShaderNodeOutputMaterial

from rprblender.utils import logging
log = logging.Log(tag='export.Material')


def key(material: bpy.types.Material, obj=None, input_socket_key='Surface'):
    mat_key = material.name_full
    obj_name = obj.name_full if obj is not None else ''

    return (mat_key, obj_name, input_socket_key)


def get_material_output_node(material):
    """ Finds output node in material tree and exports it """
    if not material.node_tree:
        # there could be a situation when node_tree is None
        return None
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
from . import viewport_engine
from . import context_hybrid

from rprblender.operators.world import FOG_KEY

from rprblender.utils import logging
log = logging.Log(tag='viewport_engine_hybrid')


class ViewportEngine(viewport_engine.ViewportEngine):
    _RPRContext = context_hybrid.RPRContext

    def __init__(self, rpr_engine):
        super().__init__(rpr_engine)

        self.render_image = None

    def sync(self, context, depsgraph):
        super().sync(context, depsgraph)

        depsgraph.scene.rpr.export_render_quality(self.rpr_context)
        log('Finish sync')
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import os
import sys

from rprblender import config
from rprblender import utils

from rprblender.utils import logging
log = logging.Log(tag='engine.init')

if utils.IS_DEBUG_MODE:
    project_root = utils.package_root_dir().parent.parent
    rpr_lib_dir = project_root / '.sdk/rpr/bin'
    rif_lib_dir = project_root / '.sdk/rif/bin'

    if utils.IS_WIN:
        os.environ['PATH'] = f"{rpr_lib_dir};{rif_lib_dir};" \
                             f"{os.environ.get('PATH', '')}"
    else:
        os.environ['LD_LIBRARY_PATH'] = f"{rpr_lib_dir}:{rif_lib_dir}:" \
                             f"{os.environ.get('LD_LIBRARY_PATH', '')}"

    sys.path.append(str(project_root / "src/bindings/pyrpr/.build"))
    sys.path.append(str(project_root / "src/bindings/pyrpr/src"))
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************

import sys
import traceback

from rprblender import config
from rprblender import utils

from rprblender.utils import logging
log = logging.Log(tag='engine.init')


def pyrpr_init(bindings_import_path, rprsdk_bin_path):
    log("pyrpr_init: bindings_path=%s, rpr_bin_path=%s" %
        (bindings_import_path, rprsdk_bin_path))

    if bindings_import_path not in sys.path:
        sys.path.append(bindings_import_path)

    try:
        import pyrpr
        import pyhybrid
        import pyrpr2

        rpr_version = utils.core_ver_str(full=True)
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
from dataclasses import dataclass
import numpy as np
import math

import bpy
import pyrpr

from rprblender.engine.context import RPRContext
from . import object

from rprblender.utils import logging

log = logging.Log(tag='export.camera')

# Core has issues with drawing faces in orthographic camera view with big
# ortho depth (far_clip_plane - near_clip_plane).
# Experimentally found quite suited value = 200
MAX_ORTHO_DEPTH = 200.0


@dataclass(init=False, eq=True)
class CameraData:
    """ Comparable dataclass which holds all camera settings """

    mode: int = None
    clip_plane: (float, float) = None
    focal_length: float = None
    sensor_size: (float, float) = None
Example #14
0
#********************************************************************
import os

import numpy as np
import math

import bpy

from rprblender.engine.context import RPRContext
from rprblender.properties.light import MAX_LUMINOUS_EFFICACY
from . import mesh, image, object
from rprblender.utils.conversion import convert_kelvins_to_rgb
from rprblender import utils

from rprblender.utils import logging
log = logging.Log(tag='export.light')


def get_radiant_power(light: bpy.types.Light, area=0.0):
    """ Return light radiant power depending of light type and selected units """

    rpr = light.rpr

    # calculating color intensity
    color = np.array(light.color)
    if rpr.use_temperature:
        color *= convert_kelvins_to_rgb(rpr.temperature)
    intensity = color * rpr.intensity
    default_intensity = color * light.energy

    # calculating radian power for core
#********************************************************************
import math

import bpy
from bpy.props import (
    BoolProperty,
    FloatProperty,
    PointerProperty,
    IntProperty,
    EnumProperty,
)
import pyrpr
from . import RPR_Properties

from rprblender.utils import logging
log = logging.Log(tag='properties.object')


class RPR_ObjectProperites(RPR_Properties):
    """ Properties for objects. Should be available only for meshes and area lights """

    # Visibility
    visibility_in_primary_rays: BoolProperty(
        name="Camera",
        description="This object will be visible in camera rays",
        default=True,
    )
    reflection_visibility: BoolProperty(
        name="Reflections",
        description="This object will be visible in reflections",
        default=True,
Example #16
0
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import numpy as np
import os
from pathlib import Path

import bpy
import bpy_extras

from rprblender import utils

from rprblender.utils import logging
from rprblender.utils import get_sequence_frame_file_path

log = logging.Log(tag='export.image')

UNSUPPORTED_IMAGES = ('.tiff', '.tif', '.exr')

# image format conversion for packed pixel/generated images
IMAGE_FORMATS = {
    'OPEN_EXR_MULTILAYER': ('OPEN_EXR', 'exr'),
    'OPEN_EXR': ('OPEN_EXR', 'exr'),
    'HDR': ('HDR', 'hdr'),
    # 'TIFF': ('TIFF', 'tiff'), # Seems tiff is not working properly in RPR
    'TARGA': ('TARGA', 'tga'),
    'TARGA_RAW': ('TARGA', 'tga'),
    # everything else will be stored as PNG
}
DEFAULT_FORMAT = ('PNG', 'png')
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import threading
import time

import pyrpr

from .render_engine import RenderEngine
from .context import RPRContext2

from rprblender.utils import logging
log = logging.Log(tag='RenderEngine2')


class RenderEngine2(RenderEngine):
    _RPRContext = RPRContext2

    def __init__(self, rpr_engine):
        super(RenderEngine2, self).__init__(rpr_engine)
        self.cryptomatte_allowed = True

    def _update_athena_data(self, data):
        data['Quality'] = "rpr2"

    def _render(self):
        resolve_event = threading.Event()
        is_finished = False
Example #18
0
import pyrpr
import pyhybrid
import pyrpr2

from bpy.props import (BoolProperty, FloatProperty, IntProperty,
                       PointerProperty, BoolVectorProperty, EnumProperty,
                       StringProperty, IntVectorProperty)
import platform

from rprblender import utils
from rprblender.utils.user_settings import get_user_settings, on_settings_changed
from . import RPR_Properties
from rprblender.engine import context

from rprblender.utils import logging
log = logging.Log(tag='properties.render')


class RPR_RenderLimits(bpy.types.PropertyGroup):
    """ Properties for render limits: 
        we use both a time and a max sample limit.
        if noise threshold > 0 then use adaptive sampling.
    """

    min_samples: IntProperty(
        name="Min Samples",
        description=
        "Minimum number of samples to render for each pixel. After this, adaptive "
        "sampling will stop sampling pixels where noise is less than threshold.",
        min=16,
        default=64,
import bpy
from bpy.props import (
    BoolProperty,
    FloatVectorProperty,
    FloatProperty,
    IntProperty,
    StringProperty,
    EnumProperty,
    PointerProperty,
)

from . import RPR_Properties

from rprblender.utils import logging
log = logging.Log(tag='properties.world')


class RPR_EnvironmentSunSky(bpy.types.PropertyGroup):

    type: EnumProperty(
        name="Sun & Sky System",
        items=(('ANALYTICAL', "Analytical Sky", "Analytical Sky"),
               ('DATE_TIME_LOCATION', "Date, Time and Location",
                "Date, Time and Location")),
        description="Sun & Sky System",
        default='ANALYTICAL',
    )

    # Analytical Sky
    azimuth: FloatProperty(
#********************************************************************
import math

import bpy
from bpy.props import (
    PointerProperty,
    EnumProperty,
    FloatProperty,
    BoolProperty,
    IntProperty,
    StringProperty,
)
from . import RPR_Properties

from rprblender.utils import logging
log = logging.Log(tag='properties.light')

MAX_LUMINOUS_EFFICACY = 683.0  # luminous efficacy of ideal monochromatic 555 nm source


class RPR_LightProperties(RPR_Properties):
    """ Light properties """

    # LIGHT INTENSITY
    intensity: FloatProperty(
        name="Intensity",
        description="Light Intensity",
        min=0.0,
        step=20,
        default=100.0,
    )
Example #21
0
# 
#     http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import math

import pyrpr
from rprblender.engine import context_hybrid

from rprblender.utils import logging
log = logging.Log(tag='export.node')


class NodeItem:
    ''' This class is a wrapper used for doing operations on material nodes.
        rpr_context is referenced to create new nodes 
        A Nodeitem can hold a float, vector, or Node value.  Node Items can then be simply 
        multiplied, divided, etc by using operator overloading.

        If the values are fixed, math operations will be applied, otherwise an 
        RPR arithmetic node will be created.

        NodeItems can retrieve their data with () operator, or index RGBA etc with []
        '''
    
    def __init__(self, rpr_context, data: [tuple, float, pyrpr.MaterialNode]):
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
from dataclasses import dataclass
import numpy as np

import bpy

from . import particle, object

from rprblender.utils import logging
log = logging.Log(tag='export.hair')


def key(p_sys, emitter):
    return particle.key(p_sys, emitter)


@dataclass(init=False)
class CurveData:
    points: np.array
    uvs: np.array
    points_radii: np.array

    @staticmethod
    def init(p_sys: bpy.types.ParticleSystem, obj: bpy.types.Object,
             use_final_settings: bool):
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import bpy
from bpy.props import (
    PointerProperty,
    IntProperty,
    StringProperty,
)

from . import RPR_Properties

from rprblender.utils import logging
log = logging.Log(tag='properties.mesh')


class RPR_MeshProperites(RPR_Properties):
    secondary_uv_layer_name: StringProperty(
        name="Secondary UV Map",
        description="Secondary UV Map",
        default="",
    )

    @property
    def primary_uv_layer(self):
        """ Get the mesh primary UV if present """
        uv_layers = self.id_data.uv_layers
        return next((uv for uv in uv_layers if uv.active_render), None)
# limitations under the License.
#********************************************************************
import os

import numpy as np

import bpy

import pyrpr
from rprblender.utils import helper_lib, IS_WIN, IS_MAC, is_zero
from rprblender.utils import get_sequence_frame_file_path

from . import mesh, object, material

from rprblender.utils import logging
log = logging.Log(tag='export.openvdb')


def key(obj: bpy.types.Object):
    return (object.key(obj), 'openvdb')


def get_transform(obj: bpy.types.Object):
    # creating bound transform matrix
    min_xyz = tuple(min(b[i] for b in obj.bound_box) for i in range(3))
    max_xyz = tuple(max(b[i] for b in obj.bound_box) for i in range(3))
    d = tuple(max_xyz[i] - min_xyz[i] for i in range(3))
    c = tuple((max_xyz[i] + min_xyz[i]) / 2 for i in range(3))

    bound_mat = np.array(
        (d[0], 0, 0, c[0], 0, d[1], 0, c[1], 0, 0, d[2], c[2], 0, 0, 0, 1),
import bgl
from gpu_extras.presets import draw_texture_2d
from bpy_extras import view3d_utils

import pyrpr
from .engine import Engine
from . import image_filter

from rprblender.export import camera, material, world, object, instance
from rprblender.export.mesh import assign_materials
from rprblender.utils import gl
from rprblender import utils
from rprblender.utils.user_settings import get_user_settings

from rprblender.utils import logging
log = logging.Log(tag='viewport_engine')

MIN_ADAPT_RATIO_DIFF = 0.2
MIN_ADAPT_RESOLUTION_RATIO_DIFF = 0.1


@dataclass(init=False, eq=True)
class ViewportSettings:
    """
    Comparable dataclass which holds render settings for ViewportEngine:
    - camera viewport settings
    - render resolution
    - screen resolution
    - render border
    """
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************

import numpy as np
import math

import bpy
from . import object, material
from rprblender.utils import BLENDER_VERSION, get_prop_array_data, is_zero

from rprblender.utils import logging
log = logging.Log(tag='export.volume')


def key(obj: bpy.types.Object, smoke_modifier):
    return (object.key(obj), smoke_modifier.name)


def get_transform(obj: bpy.types.Object):
    # Set volume transform. Note: it should be scaled by 2.0
    transform = object.get_transform(obj)
    scale = np.identity(4, dtype=np.float32)
    scale[0, 0], scale[1, 1], scale[2, 2] = 2.0, 2.0, 2.0
    return transform @ scale


def get_smoke_modifier(obj: bpy.types.Object):
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import pyrpr
import pyhybrid

from . import context
from rprblender.config import hybrid_unsupported_log_warn

from rprblender.utils import logging

log = logging.Log(tag='context_hybrid')


class RPRContext(context.RPRContext):
    """ Manager of pyhybrid and pyrpr calls """

    _Context = pyhybrid.Context
    _Scene = pyhybrid.Scene

    _MaterialNode = pyhybrid.MaterialNode

    _PointLight = pyhybrid.PointLight
    _SphereLight = pyhybrid.PointLight
    _DirectionalLight = pyhybrid.DirectionalLight
    _SpotLight = pyhybrid.SpotLight
    _DiskLight = pyhybrid.SpotLight
import weakref
import numpy as np

import bpy
import mathutils
import pyrpr

from .context import RPRContext
from rprblender.export import object, instance
from rprblender.properties.view_layer import RPR_ViewLayerProperites
from . import image_filter

from rprblender.utils import logging

log = logging.Log(tag='Engine')

ITERATED_OBJECT_TYPES = ('MESH', 'LIGHT', 'CURVE', 'FONT', 'SURFACE', 'META',
                         'VOLUME')


class Engine:
    """ This is the basic Engine class """

    TYPE = None

    # RPRContext class
    _RPRContext = RPRContext

    def __init__(self, rpr_engine):
        self.rpr_engine = weakref.proxy(rpr_engine)
from bpy.props import (
    BoolProperty,
    PointerProperty,
    BoolVectorProperty,
    EnumProperty,
    IntProperty,
    FloatProperty,
)

import pyrpr
from rprblender import utils

from rprblender.utils import logging
from . import RPR_Properties

log = logging.Log(tag='properties.view_layer')


class RPR_DenoiserProperties(RPR_Properties):
    """ Denoiser properties. This is a child property in RPR_ViewLayerProperties """
    enable: BoolProperty(
        description="Enable RPR Denoiser",
        default=False,
    )

    # only enable ML denoiser on windows
    items = (('BILATERAL', "Bilateral", "Bilateral", 0),
             ('LWR', "Local Weighted Regression", "Local Weighted Regression",
              1), ('EAW', "Edge Avoiding Wavelets", "Edge Avoiding Wavelets",
                   2), ('ML', "Machine Learning", "Machine Learning", 3))
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#********************************************************************
import bpy
from bpy.props import (
    PointerProperty,
    FloatProperty,
    BoolProperty,
)

from . import RPR_Properties

from rprblender.utils import logging
log = logging.Log(tag='properties.camera')


class RPR_CameraProperties(RPR_Properties):
    """ Camera properties """

    motion_blur_exposure: FloatProperty(
        name="Exposure",
        description="Camera motion blur exposure",
        min=0.0,
        soft_max=1.0,
        default=1.0,
    )

    @classmethod
    def register(cls):