Interactive Director: Layered Image Proxies give errors... Workaround?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
Jackkel Dragon
Veteran
Posts: 283
Joined: Mon Mar 31, 2014 7:17 pm
Organization: Nightshade, Team Despair
itch: jackkel-dragon
Location: USA
Contact:

Interactive Director: Layered Image Proxies give errors... Workaround?

#1 Post by Jackkel Dragon »

Whenever I try to use images that are proxies of layered images with the Interactive Director, I end up with the error that I posted below. In the past I've tried to just avoid using the director, but lately it's becoming annoying to me to switch between coding methods for scenes and so I'd like to know if there's a way I can avoid the error. (For instance, another way of duplicating an image besides proxies or tags, since neither work with the director right now.)

I spent an hour or so trying to figure out the error, and the best I can tell is that the _list_attributes of a layered image returns a list, while it returns a tuple from a proxy (since it goes through filter_attributes, which forces the data into a tuple). Since the function the director uses needs lists rather than tuples, this seems to be where the error happens.

Below I've posted the BBCode error message that I keep getting. Hopefully it can help someone in explaining why these proxies are causing me so much trouble...

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/akomi.rpy", line 962, in script
    akomi "I'll see you later, then."
  File "renpy/common/00director.rpy", line 1861, in execute
    screen director():
  File "renpy/common/00director.rpy", line 1861, in execute
    screen director():
  File "renpy/common/00director.rpy", line 1869, in execute
    frame:
  File "renpy/common/00director.rpy", line 1878, in execute
    has fixed:
  File "renpy/common/00director.rpy", line 1881, in execute
    if state.mode == "lines":
  File "renpy/common/00director.rpy", line 1888, in execute
    use director_attributes(state)
  File "renpy/common/00director.rpy", line 1747, in execute
    screen director_attributes(state):
  File "renpy/common/00director.rpy", line 1747, in execute
    screen director_attributes(state):
  File "renpy/common/00director.rpy", line 1749, in execute
    vbox:
  File "renpy/common/00director.rpy", line 1754, in execute
    use director_choices(_("Attributes:")):
  File "renpy/common/00director.rpy", line 1688, in execute
    screen director_choices(title):
  File "renpy/common/00director.rpy", line 1688, in execute
    screen director_choices(title):
  File "renpy/common/00director.rpy", line 1692, in execute
    frame:
  File "renpy/common/00director.rpy", line 1696, in execute
    viewport:
  File "renpy/common/00director.rpy", line 1703, in execute
    hbox:
  File "renpy/common/00director.rpy", line 1707, in execute
    transclude
  File "renpy/common/00director.rpy", line 1754, in execute
    use director_choices(_("Attributes:")):
  File "renpy/common/00director.rpy", line 1756, in execute
    for t in director.get_attributes():
  File "renpy/common/00director.rpy", line 1756, in <module>
    for t in director.get_attributes():
  File "renpy/common/00director.rpy", line 638, in get_attributes
    return renpy.get_ordered_image_attributes(state.tag, [ ], component_key)
TypeError: can only concatenate list (not "tuple") to list

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/akomi.rpy", line 962, in script
    akomi "I'll see you later, then."
  File "renpy/ast.py", line 721, in execute
    renpy.exports.say(who, what, *args, **kwargs)
  File "renpy/exports.py", line 1419, in say
    who(what, *args, **kwargs)
  File "renpy/character.py", line 1249, in __call__
    self.do_display(who, what, cb_args=self.cb_args, dtt=dtt, **display_args)
  File "renpy/character.py", line 901, in do_display
    **display_args)
  File "renpy/character.py", line 647, in display_say
    rv = renpy.ui.interact(mouse='say', type=type, roll_forward=roll_forward)
  File "renpy/ui.py", line 298, in interact
    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
  File "renpy/display/core.py", line 3325, in interact
    repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, pause=pause, pause_start=pause_start, **kwargs)
  File "renpy/display/core.py", line 3737, in interact_core
    root_widget.visit_all(lambda i : i.per_interact())
  File "renpy/display/core.py", line 568, in visit_all
    d.visit_all(callback, seen)
  File "renpy/display/core.py", line 568, in visit_all
    d.visit_all(callback, seen)
  File "renpy/display/core.py", line 568, in visit_all
    d.visit_all(callback, seen)
  File "renpy/display/screen.py", line 436, in visit_all
    callback(self)
  File "renpy/display/core.py", line 3737, in <lambda>
    root_widget.visit_all(lambda i : i.per_interact())
  File "renpy/display/screen.py", line 447, in per_interact
    self.update()
  File "renpy/display/screen.py", line 637, in update
    self.screen.function(**self.scope)
  File "renpy/common/00director.rpy", line 1861, in execute
    screen director():
  File "renpy/common/00director.rpy", line 1861, in execute
    screen director():
  File "renpy/common/00director.rpy", line 1869, in execute
    frame:
  File "renpy/common/00director.rpy", line 1878, in execute
    has fixed:
  File "renpy/common/00director.rpy", line 1881, in execute
    if state.mode == "lines":
  File "renpy/common/00director.rpy", line 1888, in execute
    use director_attributes(state)
  File "renpy/common/00director.rpy", line 1747, in execute
    screen director_attributes(state):
  File "renpy/common/00director.rpy", line 1747, in execute
    screen director_attributes(state):
  File "renpy/common/00director.rpy", line 1749, in execute
    vbox:
  File "renpy/common/00director.rpy", line 1754, in execute
    use director_choices(_("Attributes:")):
  File "renpy/common/00director.rpy", line 1688, in execute
    screen director_choices(title):
  File "renpy/common/00director.rpy", line 1688, in execute
    screen director_choices(title):
  File "renpy/common/00director.rpy", line 1692, in execute
    frame:
  File "renpy/common/00director.rpy", line 1696, in execute
    viewport:
  File "renpy/common/00director.rpy", line 1703, in execute
    hbox:
  File "renpy/common/00director.rpy", line 1707, in execute
    transclude
  File "renpy/common/00director.rpy", line 1754, in execute
    use director_choices(_("Attributes:")):
  File "renpy/common/00director.rpy", line 1756, in execute
    for t in director.get_attributes():
  File "renpy/common/00director.rpy", line 1756, in <module>
    for t in director.get_attributes():
  File "renpy/common/00director.rpy", line 638, in get_attributes
    return renpy.get_ordered_image_attributes(state.tag, [ ], component_key)
  File "renpy/display/image.py", line 175, in get_ordered_image_attributes
    sequence = list(attrs) + la(tag, [ i for i in attributes if i not in attrs ])
TypeError: can only concatenate list (not "tuple") to list

Windows-10-10.0.19041
Ren'Py 7.4.11.2266
Eldritch Academy 3.0
Fri Jan 14 16:57:37 2022
Main Website
Includes information about and links to many of my current and past projects.

Major Game Projects
[Nightshade] Eldritch Academy, Eldritch University, Blooming Nightshade, Flowering Nightshade, Life as Designed
[Team Despair] Corpse Party D2 series

User avatar
Jackkel Dragon
Veteran
Posts: 283
Joined: Mon Mar 31, 2014 7:17 pm
Organization: Nightshade, Team Despair
itch: jackkel-dragon
Location: USA
Contact:

Re: Interactive Director: Layered Image Proxies give errors... Workaround?

#2 Post by Jackkel Dragon »

I've made a temporary workaround, potentially. I made a copy of the proxy class and had it run in the init phase right after the default version (-99) to override it, and so far it SEEMS to work nice with the director...

At any rate, here's the modded class. The actual changes were to filter_attributes and _choose_attributes. Would there be any issues with having these changes as part of the official build? I'm not sure why filter was forcing the values to tuples, so I don't know what the side effects might be...

(Also, I'm still curious if there will ever be official support for negative attributes for layered images in the director. I have my hacked-together version that I use, and Python 3 support clearly has priority when it comes to development, but I wondered if there was any idea of how to do such a thing in a more elegant way than mine.)

Code: Select all

    class LayeredImageProxy(object):

        def __init__(self, name, transform=None):

            self.name = name

            if "[" not in self.name:
                if renpy.get_registered_image(name) is None:
                        raise Exception("{!r} is not a registered image name.".format(self.name))

            if transform is None:
                self.transform = [ ]

            elif isinstance(transform, list):
                self.transform = transform

            else:
                self.transform = [ transform ]

        @property
        def image(self):

            name = self.name

            if "[" in name:
                name = renpy.substitute(name, translate=False)

            image = renpy.get_registered_image(name)

            if image is None:
                raise Exception("{!r} is not a registered image name, in LayeredImageProxy.".format(name))

            return image

        def _duplicate(self, args):

            rv = self.image._duplicate(args)

            for i in self.transform:
                rv = i(rv)

            return rv

        def filter_attributes(self, attributes):

            if attributes is None:
                return None

            name = self.name

            if "[" in name:
                name = renpy.substitute(name, translate=False)

            name = name.split()

            return [i for i in attributes if i not in name[1:]]

        def _choose_attributes(self, tag, attributes, optional):
            return tuple(self.filter_attributes(self.image._choose_attributes(tag, attributes, optional)))

        def _list_attributes(self, tag, attributes):
            return self.filter_attributes(self.image._list_attributes(tag, attributes))
Main Website
Includes information about and links to many of my current and past projects.

Major Game Projects
[Nightshade] Eldritch Academy, Eldritch University, Blooming Nightshade, Flowering Nightshade, Life as Designed
[Team Despair] Corpse Party D2 series

Post Reply

Who is online

Users browsing this forum: Google [Bot]