Example #1
0
    def execute(self, context):

        debug = context.debug

        screen = renpy.ui.screen

        cache = context.cache.get(self.serial, None)

        if cache is None:
            context.cache[self.serial] = cache = SLCache()

        copy_on_change = cache.copy_on_change

        if debug:
            self.debug_line()

            if cache.constant:
                profile_log.write("    reused constant displayable")

        if cache.constant:

            for i in cache.constant_uses_scope:
                if copy_on_change:
                    if i._scope(context.scope, False):
                        cache.constant = None
                        break
                else:
                    i._scope(context.scope, True)

            else:
                context.children.append(cache.constant)
                screen.widgets.update(cache.constant_widgets)
                return

        # Create the context.
        ctx = SLContext(context)

        # True if we encountered an exception that we're recovering from
        # due to being in prediction mode.
        fail = False

        # The main displayable we're predicting.
        main = None

        # True if we're using an imagemap.
        imagemap = False

        try:
            # Evaluate the positional arguments.
            positional_values = self.positional_values
            positional_exprs = self.positional_exprs

            if positional_values and positional_exprs:
                values = eval(positional_exprs, context.globals, context.scope)
                positional = [ b if (a is use_expression) else a for a, b in zip(positional_values, values) ]
            elif positional_values:
                positional = positional_values
            elif positional_exprs:
                positional = eval(positional_exprs, context.globals, context.scope)
            else:
                positional = [ ]

            keywords = ctx.keywords = self.default_keywords.copy()

            if self.constant:
                if ctx.uses_scope is None:
                    ctx.uses_scope = [ ]
                if ctx.widgets is None:
                    ctx.widgets = { }

            SLBlock.keywords(self, ctx)

            # Get the widget id and transform, if any.
            widget_id = keywords.pop("id", None)
            transform = keywords.pop("at", None)

            # If we don't know the style, figure it out.
            if ("style" not in keywords) and self.style:
                keywords["style"] = ctx.style_prefix + self.style

            if widget_id and (widget_id in screen.widget_properties):
                keywords.update(screen.widget_properties[widget_id])

            old_d = cache.displayable
            if old_d:
                old_main = old_d._main or old_d
            else:
                old_main = None

            reused = False

            if debug:
                self.report_arguments(cache, positional, keywords, transform)

            if old_d and (positional == cache.positional) and (keywords == cache.keywords):
                reused = True
                d = old_d

                # The main displayable, if d is a composite displayable. (This is
                # the one that gets the scope, and gets children added to it.)
                main = old_main

                if widget_id:
                    screen.widgets[widget_id] = main

                if self.scope and main.uses_scope:
                    if copy_on_change:
                        if main._scope(ctx.scope, False):
                            reused = False
                    else:
                        main._scope(ctx.scope, True)

            if reused and cache.imagemap:
                imagemap = True
                cache.imagemap.reuse()
                renpy.ui.imagemap_stack.append(cache.imagemap)

            if not reused:
                cache.positional = positional
                cache.keywords = keywords.copy()

                # This child creation code is copied below, for the copy_on_change
                # case.
                if self.scope:
                    keywords["scope"] = ctx.scope

                if self.replaces:
                    keywords['replaces'] = old_main

                # Pass the context
                if self.pass_context:
                    keywords['context'] = ctx

                d = self.displayable(*positional, **keywords)
                main = d._main or d

                main._location = self.location

                if widget_id:
                    screen.widgets[widget_id] = main
                # End child creation code.

                imagemap = self.imagemap

                cache.copy_on_change = False # We no longer need to copy on change.
                cache.children = None # Re-add the children.

            if debug:
                if reused:
                    profile_log.write("    reused displayable")
                elif self.constant:
                    profile_log.write("    created constant displayable")
                else:
                    profile_log.write("    created displayable")

        except:
            if not context.predicting:
                raise
            fail = True

        ctx.children = [ ]
        stack = renpy.ui.stack
        stack.append(ctx)

        try:

            # Evaluate children. (Inlined SLBlock.execute)
            for i in self.children:
                try:
                    i.execute(ctx)
                except:
                    if not context.predicting:
                        raise
                    fail = True

        finally:

            stack.pop()

            if imagemap:
                cache.imagemap = renpy.ui.imagemap_stack.pop()
                cache.imagemap.cache.finish()

        # If a failure occurred during prediction, predict main (if known),
        # and ctx.children, and return.
        if fail:
            predict_displayable(main)

            for i in ctx.children:
                predict_displayable(i)

            return

        if ctx.children != cache.children:

            if reused and copy_on_change:

                # This is a copy of the child creation code from above.
                if self.scope:
                    keywords["scope"] = ctx.scope

                if self.replaces:
                    keywords['replaces'] = old_main

                if self.pass_context:
                    keywords['context'] = ctx

                d = self.displayable(*positional, **keywords)
                main = d._main or d

                main._location = self.location

                if widget_id:
                    screen.widgets[widget_id] = main
                # End child creation code.

                cache.copy_on_change = False
                reused = False

            if reused:
                main._clear()

            if self.child_or_fixed and len(ctx.children) != 1:
                f = Fixed()

                for i in ctx.children:
                    f.add(i)

                main.add(f)

            else:
                for i in ctx.children:
                    main.add(i)

        # Migrate grabs.
        if old_main and (renpy.display.focus.grab is old_main):
            renpy.display.focus.new_grab = main

        cache.displayable = d
        cache.children = ctx.children

        if transform is not None:
            if reused and (transform == cache.raw_transform):
                d = cache.transform
            else:
                cache.raw_transform = transform

                if isinstance(transform, Transform):
                    d = transform(child=d)
                elif isinstance(transform, list_or_tuple):
                    for t in transform:
                        if isinstance(t, Transform):
                            d = t(child=d)
                        else:
                            d = t(d)
                else:
                    d = transform(d)

                if isinstance(d, Transform):
                    if cache.transform is not None:
                        d.take_state(cache.transform)
                        d.take_execution_state(cache.transform)

            cache.transform = d

        else:
            cache.transform = None
            cache.raw_transform = None

        context.children.append(d)

        if self.constant:
            cache.constant = d

            if widget_id is not None:
                ctx.widgets[widget_id] = main

            if self.scope and main.uses_scope:
                ctx.uses_scope.append(main)

            if context.widgets is None:
                cache.constant_widgets = ctx.widgets

            if context.uses_scope is None:
                cache.constant_uses_scope = ctx.uses_scope
Example #2
0
    def execute(self, context):

        screen = renpy.ui.screen

        cache = context.cache.get(self.serial, None)
        if cache is None:
            context.cache[self.serial] = cache = SLCache()

        if cache.constant:
            context.children.append(cache.constant)
            screen.widgets.update(cache.constant_widgets)

            for i in cache.constant_uses_scope:
                i._scope(context.scope)

            return

        stack = renpy.ui.stack

        # Evaluate the positional arguments.
        positional_values = self.positional_values
        positional_exprs = self.positional_exprs

        if positional_values and positional_exprs:
            values = eval(positional_exprs, context.globals, context.scope)
            positional = [ b if (a is use_expression) else a for a, b in zip(positional_values, values) ]
        elif positional_values:
            positional = positional_values
        elif positional_exprs:
            positional = eval(positional_exprs, context.globals, context.scope)
        else:
            positional = [ ]

        # Create the context.
        ctx = SLContext(context)
        keywords = ctx.keywords = { }

        if self.constant:
            if ctx.uses_scope is None:
                ctx.uses_scope = [ ]
            if ctx.widgets is None:
                ctx.widgets = { }

        SLBlock.keywords(self, ctx)

        # Get the widget id and transform, if any.
        widget_id = keywords.pop("id", None)
        transform = keywords.pop("at", None)

        # If we don't know the style, figure it out.
        if ("style" not in keywords) and self.style:
            keywords["style"] = ctx.style_prefix + self.style

        if widget_id and (widget_id in screen.widget_properties):
            keywords.update(screen.widget_properties[widget_id])

        if (positional == cache.positional) and (keywords == cache.keywords):
            d = cache.displayable
            reused = True

            if cache.imagemap:
                renpy.ui.imagemap_stack.append(cache.imagemap)

            # The main displayable, if d is a composite displayable. (This is
            # the one that gets the scope, and gets children added to it.)
            main = d._main or d

            if self.scope and main.uses_scope:
                main._scope(ctx.scope)

        else:
            cache.positional = positional
            cache.keywords = keywords.copy()

            # This child creation code is copied below, for the copy_on_change
            # case.
            if self.scope:
                keywords["scope"] = ctx.scope

            if self.replaces:
                old_d = cache.displayable

                if old_d is not None:
                    old_d = old_d._main or old_d

                    keywords['replaces'] = old_d

            # Pass the context
            if self.pass_context:
                keywords['context'] = ctx

            d = self.displayable(*positional, **keywords)
            main = d._main or d
            # End copy.

            reused = False

            cache.children = None # Re-add the children.

        main._location = self.location

        if widget_id:
            screen.widgets[widget_id] = main

        ctx.children = [ ]
        stack.append(ctx)

        try:

            # Evaluate children. (Inlined SLBlock.execute)
            for i in self.children:
                i.execute(ctx)

        finally:

            stack.pop()

            if self.imagemap:
                cache.imagemap = renpy.ui.imagemap_stack.pop()

        if ctx.children != cache.children:

            if reused and cache.copy_on_change:

                # This is a copy of the child creation code from above.
                if self.scope:
                    keywords["scope"] = ctx.scope

                if self.replaces:
                    old_d = cache.displayable

                    if old_d is not None:
                        old_d = old_d._main or old_d

                        keywords['replaces'] = old_d

                if self.pass_context:
                    keywords['context'] = ctx

                d = self.displayable(*positional, **keywords)
                main = d._main or d
                # End child creation code.

                cache.copy_on_change = False
                reused = False

            if reused:
                main._clear()

            if self.child_or_fixed and len(self.children) != 1:
                f = Fixed()

                for i in ctx.children:
                    f.add(i)

                main.add(f)

            else:
                for i in ctx.children:
                    main.add(i)

        cache.displayable = d
        cache.children = ctx.children

        if transform is not None:
            if reused and (transform == cache.raw_transform):
                d = cache.transform
            else:
                cache.raw_transform = transform


                if isinstance(transform, Transform):
                    d = transform(child=d)
                elif isinstance(transform, list_or_tuple):
                    for t in transform:
                        if isinstance(t, Transform):
                            d = t(child=d)
                        else:
                            d = t(d)
                else:
                    d = transform(d)

                if isinstance(d, Transform):
                    if cache.transform is not None:
                        d.take_state(cache.transform)
                        d.take_execution_state(cache.transform)

            cache.transform = d

        else:
            cache.transform = None
            cache.raw_transform = None

        context.children.append(d)

        if self.constant:
            cache.constant = d

            if widget_id is not None:
                ctx.widgets[widget_id] = main

            if self.scope and main.uses_scope:
                ctx.uses_scope.append(main)

            if context.widgets is None:
                cache.constant_widgets = ctx.widgets

            if context.uses_scope is None:
                cache.constant_uses_scope = ctx.uses_scope