like this:
![Image](http://s1.directupload.net/images/140726/temp/yz34e4lg.png)
Simply adding an image above label line[0] works perfectly well. Applying this to side_image brings up some issues.xela wrote:Tayruu ideas sound perfectly reasonable, what went wrong?
Code: Select all
define narrator = Character(" ", color="#000000", show_two_window=True, show_side_image=Image("character/side/narrator_side.png", xalign=0.02, yalign=1.07), ctc="ctc1", ctc_position="fixed")
Code: Select all
screen text_history:
default side_image = None
use transpar3
tag menu
if not current_line and len(readback_buffer) == 0:
$ lines_to_show = []
elif current_line and len(readback_buffer) == 0:
$ lines_to_show = [current_line]
elif current_line and not ( ( len(readback_buffer) == 3 and current_line == readback_buffer[-2]) or current_line == readback_buffer[-1]):
$ lines_to_show = readback_buffer + [current_line]
else:
$ lines_to_show = readback_buffer
$ adj = NewAdj(changed = store_yvalue, step = 300)
window:
style_group "readback"
side "c r":
frame:
has viewport:
mousewheel True
draggable True
yinitial yvalue
yadjustment adj
vbox:
null height 10
for line in lines_to_show:
if line[0] and line[0] != " ":
if side_image:
add side_image xpos 3.0
label line[0] # name
# if there's no voice just log a dialogue
if not line[2]:
text line[1]
# else, dialogue will be saved as a button of which plays voice when clicked
else:
textbutton line[1] action Play("voice", line[2] )
null height 25
text "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
null height 25
bar adjustment adj style 'vscrollbar'
textbutton _("Return") action Return() align (1.5, 0.95)
Try these out.xela wrote:I have no setup to test this with. Also, this depends on how you define the images themselves, maybe you can show images based on names of characters and their expressions.
Code: Select all
################################################################
#TEXT HISTORY
init 1 python:
style.vscrollbar_frame.background="#cc0"
style.vscrollbar.xmaximum = 30
style.vscrollbar.ymaximum = 520
style.vscrollbar.thumb_offset = 12
style.vscrollbar.xpos=430
style.vscrollbar.yalign = .5
init -4 python:
store.text_history_enabled = False
init -3 python:
style.readback_window.background = None
style.readback_window.xmaximum = 1366
style.readback_window.ymaximum = 768
style.readback_window.xalign = .5
style.readback_window.yalign = .2
style.readback_frame.left_padding = 30
style.readback_frame.right_padding = -250
style.readback_frame.top_padding = 40
style.readback_frame.bottom_padding = 40
style.readback_frame.xpos = 150
style.readback_frame.xsize = 1100
style.readback_frame.ysize = 600
style.readback_text.color = "#fff"
style.create("readback_button", "readback_text")
style.readback_button.top_padding = 20
style.readback_button.xpadding = 50
style.readback_button.bottom_padding = 20
#style.create("readback_button_text", "readback_text")
style.readback_button_text.selected_color = "#f12"
style.readback_button_text.hover_color = "#f12"
style.readback_label_text.bold = True
style.readback_text.size = 18
style.readback_label_text.size = 22
# starts adding new config variables
config.locked = False
# Configuration Variable for Text History
config.readback_buffer_length = 100 # number of lines stored
config.readback_full = True # True = completely replaces rollback, False = readback accessible from game menu only (dev mode)
config.readback_disallowed_tags = ["size"] # a list of tags that will be removed in the text history
config.readback_choice_prefix = ">> " # this is prefixed to the choices the user makes in readback
# ends adding new config variables
config.locked = True
init -2 python:
# Two custom characters that store what they said
class ReadbackADVCharacter(ADVCharacter):
def do_done(self, who, what):
store_say(who, what)
store.current_voice = ''
return
class ReadbackNVLCharacter(NVLCharacter):
def do_done(self, who, what):
store_say(who, what)
store.current_voice = ''
return
# this enables us to show the current line in readback without having to bother the buffer with raw shows
def say_wrapper(who, what, **kwargs):
store_current_line(who, what)
return renpy.show_display_say(who, what, **kwargs)
config.nvl_show_display_say = say_wrapper
adv = ReadbackADVCharacter(show_function=say_wrapper)
nvl = ReadbackNVLCharacter()
NVLCharacter = ReadbackNVLCharacter
# rewriting voice function to replay voice files when you clicked dialogues in text history screen
def voice(file, **kwargs):
if not config.has_voice:
return
_voice.play = file
store.current_voice = file
# overwriting standard menu handler
# Overwriting menu functions makes Text History log choice which users choose.
def menu(items, **add_input):
newitems = []
for label, val in items:
if val == None:
narrator(label, interact=False)
else:
newitems.append((label, val))
rv = renpy.display_menu(newitems, **add_input)
# logging menu choice label.
for label, val in items:
if rv == val:
store.current_voice = ''
store_say(None, config.readback_choice_prefix + label)
return rv
def nvl_screen_dialogue():
"""
Returns widget_properties and dialogue for the current NVL
mode screen.
"""
widget_properties = { }
dialogue = [ ]
for i, entry in enumerate(nvl_list):
if not entry:
continue
who, what, kwargs = entry
if i == len(nvl_list) - 1:
who_id = "who"
what_id = "what"
window_id = "window"
else:
who_id = "who%d" % i
what_id = "what%d" % i
window_id = "window%d" % i
widget_properties[who_id] = kwargs["who_args"]
widget_properties[what_id] = kwargs["what_args"]
widget_properties[window_id] = kwargs["window_args"]
dialogue.append((who, what, who_id, what_id, window_id))
return widget_properties, dialogue
# Overwriting nvl menu function
def nvl_menu(items):
renpy.mode('nvl_menu')
if nvl_list is None:
store.nvl_list = [ ]
screen = None
if renpy.has_screen("nvl_choice"):
screen = "nvl_choice"
elif renpy.has_screen("nvl"):
screen = "nvl"
if screen is not None:
widget_properties, dialogue = nvl_screen_dialogue()
rv = renpy.display_menu(
items,
widget_properties=widget_properties,
screen=screen,
scope={ "dialogue" : dialogue },
window_style=style.nvl_menu_window,
choice_style=style.nvl_menu_choice,
choice_chosen_style=style.nvl_menu_choice_chosen,
choice_button_style=style.nvl_menu_choice_button,
choice_chosen_button_style=style.nvl_menu_choice_chosen_button,
type="nvl",
)
for label, val in items:
if rv == val:
store.current_voice = ''
store_say(None, config.readback_choice_prefix + label)
return rv
# Traditional version.
ui.layer("transient")
ui.clear()
ui.close()
ui.window(style=__s(style.nvl_window))
ui.vbox(style=__s(style.nvl_vbox))
for i in nvl_list:
if not i:
continue
who, what, kw = i
rv = renpy.show_display_say(who, what, **kw)
renpy.display_menu(items, interact=False,
window_style=__s(style.nvl_menu_window),
choice_style=__s(style.nvl_menu_choice),
choice_chosen_style=__s(style.nvl_menu_choice_chosen),
choice_button_style=__s(style.nvl_menu_choice_button),
choice_chosen_button_style=__s(style.nvl_menu_choice_chosen_button),
)
ui.close()
roll_forward = renpy.roll_forward_info()
rv = ui.interact(roll_forward=roll_forward)
renpy.checkpoint(rv)
for label, val in items:
if rv == val:
store.current_voice = ''
store_say(None, config.readback_choice_prefix + label)
return rv
## readback
readback_buffer = []
current_line = None
current_voice = None
def store_say(who, what):
global readback_buffer, current_voice
if preparse_say_for_store(what):
new_line = (preparse_say_for_store(who), preparse_say_for_store(what), current_voice)
readback_buffer = readback_buffer + [new_line]
readback_prune()
def store_current_line(who, what):
global current_line, current_voice
current_line = (preparse_say_for_store(who), preparse_say_for_store(what), current_voice)
# remove text tags from dialogue lines
disallowed_tags_regexp = ""
for tag in config.readback_disallowed_tags:
if disallowed_tags_regexp != "":
disallowed_tags_regexp += "|"
disallowed_tags_regexp += "{"+tag+"=.*?}|{"+tag+"}|{/"+tag+"}"
import re
remove_tags_expr = re.compile(disallowed_tags_regexp) # remove tags undesirable in readback
def preparse_say_for_store(input):
global remove_tags_expr
if input:
return re.sub(remove_tags_expr, "", input)
def readback_prune():
global readback_buffer
while len(readback_buffer) > config.readback_buffer_length:
del readback_buffer[0]
# keymap overriding to show text_history.
def readback_catcher():
ui.add(renpy.Keymap(rollback=If(store.text_history_enabled,[ SetVariable("yvalue", 1.0), ShowMenu("text_history")])))
ui.add(renpy.Keymap(rollforward=ui.returns(None)))
if config.readback_full:
config.rollback_enabled = False
config.overlay_functions.append(readback_catcher)
init python:
yvalue = 1.0
class NewAdj(renpy.display.behavior.Adjustment):
def change(self,value):
if value > self._range and self._value == self._range:
return Return()
else:
return renpy.display.behavior.Adjustment.change(self, value)
def store_yvalue(y):
global yvalue
yvalue = int(y)
screen text_history:
default side_image = None
use transpar3
tag menu
if not current_line and len(readback_buffer) == 0:
$ lines_to_show = []
elif current_line and len(readback_buffer) == 0:
$ lines_to_show = [current_line]
elif current_line and not ( ( len(readback_buffer) == 3 and current_line == readback_buffer[-2]) or current_line == readback_buffer[-1]):
$ lines_to_show = readback_buffer + [current_line]
else:
$ lines_to_show = readback_buffer
$ adj = NewAdj(changed = store_yvalue, step = 300)
window:
style_group "readback"
side "c r":
frame:
has viewport:
mousewheel True
draggable True
yinitial yvalue
yadjustment adj
vbox:
null height 10
for line in lines_to_show:
hbox:
if line[0] and line[0] != " ":
if side_image:
add side_image xpos 3.0
label line[0] # name
null width 10
if line[1]:
# if there's no voice just log a dialogue
if not line[2]:
text line[1]
# else, dialogue will be saved as a button of which plays voice when clicked
else:
textbutton line[1] action Play("voice", line[2] )
null height 25
text "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
null height 25
bar adjustment adj style 'vscrollbar'
textbutton _("Return") action Return() align (1.5, 0.95)
Code: Select all
define narrator = Character(" ", color="#000000", show_two_window=True, show_side_image=Image("narrator_side.png", xalign=0.02, yalign=1.07), ctc="ctc1", ctc_position="fixed")
Code: Select all
screen say:
default side_image = None
default two_window = True
default quick_menu = True
default quickmap = True
if not two_window:
window:
id "window"
has vbox:
style "say_vbox"
if who:
text who id "who"
text what id "what"
else:
use quick_menu
use quickmap
if side_image:
add side_image
else:
add SideImage() xalign 0.0 yalign 1.0
vbox:
style "say_two_window_vbox"
if who:
window:
style "say_who_window"
text who:
id "who"
window:
id "window"
has vbox:
style "say_vbox"
text what id "what"
Code: Select all
def SideImage(prefix_tag="side"):
"""
:doc: side_image_function
Returns the side image associated with the currently speaking character,
or a Null displayable if no such side image exists.
"""
name = renpy.get_side_image(prefix_tag, image_tag=config.side_image_tag, not_showing=config.side_image_only_not_showing)
if name is None:
return Null()
else:
return ImageReference(name)
Code: Select all
NameList = {"Eileen": "eileen.png"
"Lucy" : "lucy.png"}
def HistoryImage(name = None):
if name in NameList:
return NameList[name]
else:
return Null()
Code: Select all
if line[0] and line[0] != " ":
add HistoryImage( line[0] ) #Add this line
text line[0]
Code: Select all
if h.who: #If the character speaking is not narrator, add image
add "images/[h.who]_side.png" #Be sure to include the file directory and correct image type
Code: Select all
text what:
if h.who: # Makes room for the side image
xsize 900
xpos 245
else: # Moves text to where side image would be so theres no weird empty space
xpos 70
xsize 1000
substitute False
Code: Select all
init python:
def history_tag_attributes_callback(h):
h.mood = renpy.get_attributes(h.image_tag)
config.history_callbacks.append(history_tag_attributes_callback)
init python:
def get_string_for_list(list_obj):
renpy.notify('call')
if not isinstance(list_obj, (list, tuple, set)):
raise TypeError, "Input parameter must be list, set or tuple"
return "".join( [
"{0}{1}".format(
v,
{ len(list_obj)-1 : '', len(list_obj)-2 : ' and ' }.get( i, ', ' )
) for i,v in enumerate(list_obj) ]
)
class SimpleObj(object):
def __init__(self, *args, **kwargs):
self.__dict__.update(kwargs)
def __repr__(self):
return ", ".join( [
getattr(self, k)
for k in self.__dict__
if k not in object.__dict__ ] )
Code: Select all
add "[h.who]/[h.who]_[h.mood[0]].png"
Code: Select all
#anywhere.rpy
define jevil = Character("Jevil", image = "jevil")
#in screens.rpy
add "[h.image_tag]/[h.image_tag]_[h.mood[0]].png"
Code: Select all
init python:
def history_tag_attributes_callback(h):
h.mood = renpy.get_attributes(h.image_tag)
config.history_callbacks.append(history_tag_attributes_callback)
init python:
def get_string_for_list(list_obj):
renpy.notify('call')
if not isinstance(list_obj, (list, tuple, set)):
raise TypeError, "Input parameter must be list, set or tuple"
return "".join( [
"{0}{1}".format(
v,
{ len(list_obj)-1 : '', len(list_obj)-2 : ' and ' }.get( i, ', ' )
) for i,v in enumerate(list_obj) ]
)
class SimpleObj(object):
def __init__(self, *args, **kwargs):
self.__dict__.update(kwargs)
def __repr__(self):
return ", ".join( [
getattr(self, k)
for k in self.__dict__
if k not in object.__dict__ ] )
screen history():
tag menu
## Avoid predicting this screen, as it can be very large.
predict False
use game_menu(_("History"), scroll=("vpgrid" if gui.history_height else "viewport"), yinitial=1.0):
style_prefix "history"
for h in _history_list:
window:
## This lays things out properly if history_height is None.
has fixed:
yfit True
if h.who:
add "[h.image_tag]/[h.image_tag] side [h.mood[0]].png"
# Label who is the name of the character who talked
# It is optional if you want it to show up alongside the images
# label h.who:
#if "color" in h.who_args:
#text_color h.who_args["color"]
$ what = renpy.filter_text_tags(h.what, allow=gui.history_allow_tags)
text what:
if h.who: # Makes room for the side image
xsize 900
xpos 245
else: # Moves text to where side image would be so theres no weird empty space
xpos 70
xsize 1000
substitute False
if not _history_list:
label _("The dialogue history is empty.")
Code: Select all
label start:
scene bg
show jevil smile
jevil "IT'S FINALLY OVER!!!"
jevil sad "...I can't believe this thread sat dormant for 8 years..."
jevil laugh "BUT WHO USES THE HISTORY SCREEN ANYWAY?!"
Code: Select all
show jevil
## or
jevil "Gosh, I sure do hope that Ren'py doesn't give me an error!"
Code: Select all
show jevil default
## or
jevil default "I can't believe Ren'py said there was an error!"
jevil "I'm expecting it to happen again now."
Wow! Could you upload a little example so that users like me can try it out? I'm not firm with python classes but I can imagine that there is a solution not to always write default. Perhaps this can even be solved in the callback function. But I need to fiddle with it
Users browsing this forum: Ocelot