You can have a look how I solved it in BlendLuxCore:
Similar to Blender, I have an “image user” class:
"use a different seed on each imagemap node)"
)
WRAP_NONE_DESC = (
"No wrapping is performed. If the image sequence does not contain enough "
"frames to cover the whole animation, some frames will be missing. "
"Only use this option if the sequence contains enough frames"
)
class LuxCoreImageUser(PropertyGroup):
"""
We can't use Blender's ImageUser class, so we have to create our own.
The ImageUser contains information about how an image is used by a datablock.
For example, the same image sequence can be used with offset 5 by a pointlight
and with offset 2 by an imagemap node, so the pointlight and the imagemap node
each have their own ImageUser instance that saves this information.
"""
# This image reference is just for internal bookkeeping
image = PointerProperty(type=bpy.types.Image)
In every place with an image pointer, I had to also add an imageuser instance, and link their update callbacks:
groundalbedo = FloatVectorProperty(name="Ground Albedo", default=(0.5, 0.5, 0.5),
min=0, max=1, subtype="COLOR",
description=GROUND_ALBEDO_DESC)
ground_enable = BoolProperty(name="Use Ground Color", default=False,
description=GROUND_ENABLE_DESC)
ground_color = FloatVectorProperty(name="Ground Color", default=(0.5, 0.5, 0.5),
min=0, max=1, subtype="COLOR",
description=GROUND_COLOR_DESC)
# infinite
def update_image(self, context):
self.image_user.update(self.image)
image = PointerProperty(name="Image", type=bpy.types.Image, update=update_image)
image_user = PointerProperty(type=LuxCoreImageUser)
gamma = FloatProperty(name="Gamma", default=1, min=0, description=GAMMA_DESCRIPTION)
sampleupperhemisphereonly = BoolProperty(name="Sample Upper Hemisphere Only", default=False,
description=SAMPLEUPPERHEMISPHEREONLY_DESCRIPTION)
rotation = FloatProperty(name="Z Axis Rotation", default=0,
subtype="ANGLE", unit="ROTATION")
On export, I use the image user to extract the required frame:
return cls._save_to_temp_file(image)
else:
try:
filepath = utils.get_abspath(image.filepath, library=image.library,
must_exist=True, must_be_existing_file=True)
return filepath
except OSError as error:
# Make the error message more precise
raise OSError('Could not find image "%s" at path "%s" (%s)'
% (image.name, image.filepath, error))
elif image.source == "SEQUENCE":
# Note: image sequences can never be packed
try:
frame = image_user.get_frame(scene)
except ValueError as error:
raise OSError(str(error))
indexed_filepaths = utils.image_sequence_resolve_all(image)
try:
if frame < 1:
raise IndexError
And then I use a function by Campbell Barton to resolve the filename:
https://github.com/LuxCoreRender/BlendLuxCore/blob/78329a35605ef2e5f67df620df6efadddcf449a4/utils/init .py#L579