Compare commits
99 Commits
start-7.2
...
7.1.2.1029
| Author | SHA1 | Date | |
|---|---|---|---|
| b159a34e44 | |||
| 63efa20467 | |||
| 17b943693c | |||
| 8e09177b6e | |||
| ddaf9f3de3 | |||
| 8900d6f3df | |||
| 2e2f2ea460 | |||
| adb928e234 | |||
| 53261a7a52 | |||
| 2e6f61e673 | |||
| 1392cd9dad | |||
| c2be31d5de | |||
| e419711493 | |||
| c734c5cda1 | |||
| bde048b359 | |||
| 9878ccec4b | |||
| 30d8911abf | |||
| d9ab291a68 | |||
| 1bc29461d1 | |||
| f2e62c571c | |||
| 0208328307 | |||
| 3ee71e9b0d | |||
| d83788fa23 | |||
| 3c2cebacef | |||
| 834b9fa1d1 | |||
| 9dd55e7b66 | |||
| 857a8a65a2 | |||
| dc58e6e8c8 | |||
| 7f8101e2ee | |||
| f7b389a5bc | |||
| c2895f465c | |||
| 075ba4bc49 | |||
| c6dd267772 | |||
| 06443a5f2e | |||
| ed564397d2 | |||
| 66ef5ba2cf | |||
| fed3430d76 | |||
| cca4bf016c | |||
| 432ba06a48 | |||
| 92fb4098b2 | |||
| a4340f7798 | |||
| 80ec5ad31e | |||
| df4d653b86 | |||
| bcfa6d126b | |||
| 92bd507781 | |||
| b6966bdc21 | |||
| 6f5c8975b6 | |||
| 35b60303ff | |||
| 969e269f4d | |||
| 291af49bc9 | |||
| ffa33a8f29 | |||
| 10e3acf760 | |||
| 93a9b9deee | |||
| 37604894e4 | |||
| 67717ef9b7 | |||
| 43534a758c | |||
| bf8e70485d | |||
| b3af65d7ab | |||
| 6b7260fe39 | |||
| 4809c16cd9 | |||
| df0e0086c7 | |||
| abd01eb734 | |||
| 4818e43632 | |||
| a3ed117153 | |||
| f73acbdf9f | |||
| 0b0c97e2ec | |||
| ffbe373dbb | |||
| 3f0e21b174 | |||
| d521e79b46 | |||
| f725485412 | |||
| e7015b9b88 | |||
| 4b74d34580 | |||
| 9ca2db8869 | |||
| 274934d356 | |||
| 56fe28955a | |||
| ba06e9538b | |||
| e117adb219 | |||
| 27aa12a5f0 | |||
| 25c39eebf9 | |||
| 4b4aa38455 | |||
| c468f8c60e | |||
| 1d8643045a | |||
| 51e79498f0 | |||
| 06590beca2 | |||
| 496d5d1c14 | |||
| 96a6f9556c | |||
| 1ae6255301 | |||
| 207c9ad79b | |||
| 788ee0399a | |||
| ee1027a8da | |||
| b3a528ddcc | |||
| 19204d0f82 | |||
| 1789b5a2ca | |||
| bc121ac0cc | |||
| a2e8a536b4 | |||
| a6a97a3f4f | |||
| 715899ade4 | |||
| d829d1ab2f | |||
| 2069612eff |
@@ -212,6 +212,7 @@ define gui.choice_button_text_size = gui.text_size
|
||||
define gui.choice_button_text_xalign = 0.5
|
||||
define gui.choice_button_text_idle_color = "#cccccc"
|
||||
define gui.choice_button_text_hover_color = "#ffffff"
|
||||
define gui.choice_button_text_insensitive_color = "#444444"
|
||||
|
||||
|
||||
## File Slot Buttons ###########################################################
|
||||
|
||||
+10
-13
@@ -1421,16 +1421,18 @@ screen quick_menu():
|
||||
|
||||
zorder 100
|
||||
|
||||
hbox:
|
||||
style_prefix "quick"
|
||||
if quick_menu:
|
||||
|
||||
xalign 0.5
|
||||
yalign 1.0
|
||||
hbox:
|
||||
style_prefix "quick"
|
||||
|
||||
textbutton _("Back") action Rollback()
|
||||
textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
|
||||
textbutton _("Auto") action Preference("auto-forward", "toggle")
|
||||
textbutton _("Menu") action ShowMenu()
|
||||
xalign 0.5
|
||||
yalign 1.0
|
||||
|
||||
textbutton _("Back") action Rollback()
|
||||
textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
|
||||
textbutton _("Auto") action Preference("auto-forward", "toggle")
|
||||
textbutton _("Menu") action ShowMenu()
|
||||
|
||||
|
||||
style window:
|
||||
@@ -1512,8 +1514,3 @@ style slider_pref_vbox:
|
||||
style slider_pref_slider:
|
||||
variant "small"
|
||||
xsize gui.scale(600)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+23
-16
@@ -23,24 +23,32 @@ label add_file:
|
||||
|
||||
python hide:
|
||||
import os
|
||||
import codecs
|
||||
filename = ""
|
||||
while True:
|
||||
filename = interface.input(
|
||||
_("FILENAME"),
|
||||
_("Enter the name of the script file to create."),
|
||||
allow=interface.FILENAME_LETTERS,
|
||||
cancel=Jump("navigation"),
|
||||
default=filename,
|
||||
)
|
||||
filename = filename.strip()
|
||||
if not filename:
|
||||
interface.error(_("The file name may not be empty."), label=None)
|
||||
continue
|
||||
|
||||
filename = interface.input(_("FILENAME"), _("Enter the name of the script file to create."), filename="withslash", cancel=Jump("navigation"))
|
||||
if "." in filename and not filename.endswith(".rpy"):
|
||||
interface.error(_("The filename must have the .rpy extension."), label=None)
|
||||
continue
|
||||
elif "." not in filename:
|
||||
filename += ".rpy"
|
||||
|
||||
if "." in filename and not filename.endswith(".rpy"):
|
||||
interface.error(_("The filename must have the .rpy extension."), label="navigation")
|
||||
elif "." not in filename:
|
||||
filename += ".rpy"
|
||||
path = os.path.join(project.current.gamedir, filename)
|
||||
dir = os.path.dirname(path)
|
||||
|
||||
path = os.path.join(project.current.gamedir, filename)
|
||||
dir = os.path.dirname(path)
|
||||
|
||||
if os.path.exists(path):
|
||||
interface.error(_("The file already exists."), label="navigation")
|
||||
|
||||
contents = u"\uFEFF"
|
||||
contents += _("# Ren'Py automatically loads all script files ending with .rpy. To use this\n# file, define a label and jump to it from another file.\n")
|
||||
contents += "\n"
|
||||
if os.path.exists(path):
|
||||
interface.error(_("The file already exists."), label=None)
|
||||
continue
|
||||
|
||||
try:
|
||||
os.makedirs(dir)
|
||||
@@ -54,4 +62,3 @@ label add_file:
|
||||
f.write(contents.encode("utf-8"))
|
||||
|
||||
jump navigation_refresh
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ init python:
|
||||
ANDROID_OK = 5
|
||||
|
||||
NO_RAPT_TEXT = _("To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher.")
|
||||
NO_JDK_TEXT = _("A Java 8 Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html}download and install the JDK{/a}, then restart the Ren'Py launcher.")
|
||||
NO_JDK_TEXT = _("A 64-bit/x64 Java 8 Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html}download and install the JDK{/a}, then restart the Ren'Py launcher.")
|
||||
NO_SDK_TEXT = _("RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this.")
|
||||
NO_KEY_TEXT = _("RAPT has been installed, but a key hasn't been configured. Please create a new key, or restore android.keystore.")
|
||||
NO_CONFIG_TEXT = _("The current project has not been configured. Use \"Configure\" to configure it before building.")
|
||||
|
||||
+28
-30
@@ -327,25 +327,6 @@ label new_gui_project:
|
||||
|
||||
python:
|
||||
gui_new = True
|
||||
|
||||
project_name = interface.input(
|
||||
_("PROJECT NAME"),
|
||||
_("Please enter the name of your project:"),
|
||||
filename=True,
|
||||
cancel=Jump("front_page"))
|
||||
|
||||
project_name = project_name.strip()
|
||||
if not project_name:
|
||||
interface.error(_("The project name may not be empty."))
|
||||
|
||||
project_dir = os.path.join(persistent.projects_directory, project_name)
|
||||
|
||||
if project.manager.get(project_name) is not None:
|
||||
interface.error(_("[project_name!q] already exists. Please choose a different project name."), project_name=project_name)
|
||||
|
||||
if os.path.exists(project_dir):
|
||||
interface.error(_("[project_dir!q] already exists. Please choose a different project name."), project_dir=project_dir)
|
||||
|
||||
gui_replace_images = True
|
||||
gui_replace_code = True
|
||||
gui_update_code = True
|
||||
@@ -369,20 +350,37 @@ label gui_project_size:
|
||||
|
||||
if gui_size == "custom":
|
||||
|
||||
gui_width = ""
|
||||
while True:
|
||||
gui_width = interface.input(
|
||||
_("WIDTH"),
|
||||
_("Please enter the width of your game, in pixels."),
|
||||
cancel=Jump("front_page"),
|
||||
allow=interface.DIGITS_LETTERS,
|
||||
)
|
||||
|
||||
gui_width = interface.input(_("WIDTH"), _("Please enter the width of your game, in pixels."), cancel=Jump("front_page"))
|
||||
try:
|
||||
gui_width = int(gui_width)
|
||||
except:
|
||||
interface.error(_("The width must be a number."), label=None)
|
||||
continue
|
||||
break
|
||||
|
||||
try:
|
||||
gui_width = int(gui_width)
|
||||
except:
|
||||
interface.error(_("The width must be a number."))
|
||||
gui_height = ""
|
||||
while True:
|
||||
gui_height = interface.input(
|
||||
_("HEIGHT"),
|
||||
_("Please enter the height of your game, in pixels."),
|
||||
cancel=Jump("front_page"),
|
||||
allow=interface.DIGITS_LETTERS,
|
||||
)
|
||||
|
||||
gui_height = interface.input(_("HEIGHT"), _("Please enter the height of your game, in pixels."), cancel=Jump("front_page"))
|
||||
|
||||
try:
|
||||
gui_height = int(gui_height)
|
||||
except:
|
||||
interface.error(_("The height must be a number."))
|
||||
try:
|
||||
gui_height = int(gui_height)
|
||||
except:
|
||||
interface.error(_("The height must be a number."), label=None)
|
||||
continue
|
||||
break
|
||||
|
||||
gui_size = (gui_width, gui_height)
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import os
|
||||
from renpy.store import config
|
||||
import renpy.display
|
||||
|
||||
|
||||
class ImageGenerator(object):
|
||||
|
||||
def __init__(self, parameters):
|
||||
@@ -199,7 +200,6 @@ class ImageGenerator(object):
|
||||
|
||||
self.generate_image("textbox", X, Y, self.boring_color.opacity(.8))
|
||||
|
||||
|
||||
YSIZE = 240
|
||||
YBORDER = 5
|
||||
|
||||
@@ -237,7 +237,6 @@ class ImageGenerator(object):
|
||||
(YSIZE, 1.0),
|
||||
]
|
||||
|
||||
|
||||
self.generate_image("nvl", X, Y, self.boring_color.opacity(.8))
|
||||
|
||||
X = [
|
||||
@@ -252,8 +251,6 @@ class ImageGenerator(object):
|
||||
|
||||
self.generate_image("phone/nvl", X, Y, self.boring_color.opacity(.8))
|
||||
|
||||
|
||||
|
||||
def generate_choice_button(self):
|
||||
XSIZE = 790
|
||||
XINSIDE = 100
|
||||
@@ -277,6 +274,8 @@ class ImageGenerator(object):
|
||||
|
||||
self.generate_image("button/choice_idle_background", X, Y, self.boring_color.opacity(.8))
|
||||
self.generate_image("button/choice_hover_background", X, Y, self.accent_color.opacity(.95))
|
||||
self.generate_image("phone/button/choice_idle_background", X, Y, self.boring_color.opacity(.8))
|
||||
self.generate_image("phone/button/choice_hover_background", X, Y, self.accent_color.opacity(.95))
|
||||
|
||||
def generate_overlay(self):
|
||||
|
||||
@@ -288,7 +287,6 @@ class ImageGenerator(object):
|
||||
|
||||
line_width = self.scale_int(3)
|
||||
|
||||
|
||||
if self.p.light:
|
||||
opacity = 0.9
|
||||
else:
|
||||
@@ -332,7 +330,6 @@ class ImageGenerator(object):
|
||||
s.subsurface((border, border, width - 2 * border, height - 2 * border)).fill(self.boring_color)
|
||||
self.save(s, "frame")
|
||||
|
||||
|
||||
def generate_quick_buttons(self):
|
||||
width = self.scale_int(100)
|
||||
height = self.scale_int(30)
|
||||
@@ -379,7 +376,6 @@ class ImageGenerator(object):
|
||||
|
||||
self.generate_image("notify", X, Y, self.boring_color.opacity(.8))
|
||||
|
||||
|
||||
def generate_icon(self):
|
||||
|
||||
icon_fn = os.path.join(config.renpy_base, "launcher", "game", "gui7", "icon.png")
|
||||
@@ -406,7 +402,6 @@ class ImageGenerator(object):
|
||||
|
||||
self.save(surf, "window_icon", overwrite=False)
|
||||
|
||||
|
||||
def generate_menus(self):
|
||||
s = self.make_surface(self.width, self.height)
|
||||
s.fill(self.menu_color)
|
||||
@@ -414,7 +409,6 @@ class ImageGenerator(object):
|
||||
self.save(s, "main_menu", overwrite=False)
|
||||
self.save(s, "game_menu", overwrite=False)
|
||||
|
||||
|
||||
def generate_all(self):
|
||||
self.generate_textbox()
|
||||
self.generate_choice_button()
|
||||
@@ -427,6 +421,7 @@ class ImageGenerator(object):
|
||||
self.generate_menus()
|
||||
self.generate_icon()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import argparse
|
||||
|
||||
@@ -439,5 +434,3 @@ if __name__ == "__main__":
|
||||
args = ap.parse_args()
|
||||
|
||||
ImageGenerator(args.prefix, args.width, args.height).generate_all()
|
||||
|
||||
|
||||
|
||||
@@ -251,7 +251,12 @@ screen launcher_input:
|
||||
|
||||
add SPACER
|
||||
|
||||
input style "l_default" value ScreenVariableInputValue("value", returnable=True) size 24 xalign 0.5 color INPUT_COLOR
|
||||
input style "l_default":
|
||||
value ScreenVariableInputValue("value", returnable=True)
|
||||
size 24
|
||||
xalign 0.5
|
||||
color INPUT_COLOR
|
||||
allow allow
|
||||
|
||||
if filename:
|
||||
add SPACER
|
||||
@@ -384,7 +389,13 @@ init python in interface:
|
||||
yield
|
||||
store._ignore_action = Jump("front_page")
|
||||
|
||||
def input(title, message, filename=False, sanitize=True, cancel=None, default=""):
|
||||
import string
|
||||
DIGITS_LETTERS = string.digits
|
||||
PROJECT_LETTERS = DIGITS_LETTERS + string.ascii_letters + " _"
|
||||
FILENAME_LETTERS = PROJECT_LETTERS + "\\/"
|
||||
TRANSLATE_LETTERS = string.ascii_letters + "_"
|
||||
|
||||
def input(title, message, filename=False, sanitize=True, cancel=None, allow=None, default=""):
|
||||
"""
|
||||
Requests typewritten input from the user.
|
||||
"""
|
||||
@@ -393,7 +404,15 @@ init python in interface:
|
||||
|
||||
while True:
|
||||
|
||||
rv = renpy.call_screen("launcher_input", title=title, message=message, filename=filename, cancel=cancel, default=rv)
|
||||
rv = renpy.call_screen(
|
||||
"launcher_input",
|
||||
title=title,
|
||||
message=message,
|
||||
filename=filename or (allow in [PROJECT_LETTERS, FILENAME_LETTERS]),
|
||||
allow=allow,
|
||||
cancel=cancel,
|
||||
default=rv
|
||||
)
|
||||
|
||||
if sanitize:
|
||||
if ("[" in rv) or ("{" in rv):
|
||||
@@ -507,6 +526,3 @@ init python in interface:
|
||||
"""
|
||||
|
||||
return common(_("CHOICE"), store.QUESTION_COLOR, message, choices=choices, selected=selected, **kwargs)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -62,28 +62,52 @@ label new_project:
|
||||
if persistent.projects_directory is None:
|
||||
$ interface.error(_("The projects directory could not be set. Giving up."))
|
||||
|
||||
if not persistent.legacy:
|
||||
python:
|
||||
if persistent.legacy:
|
||||
|
||||
python:
|
||||
check_language_support()
|
||||
|
||||
gui_kind = interface.choice(
|
||||
_("Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."),
|
||||
[ ( 'new_gui_project', _("New GUI Interface") ), ( 'new_theme_project', _("Legacy Theme Interface")) ],
|
||||
"new_gui_project",
|
||||
cancel=Jump("front_page"),
|
||||
)
|
||||
else:
|
||||
new_project_language = (_preferences.language or "english").title()
|
||||
gui_kind = "new_gui_project"
|
||||
|
||||
# When translating this, feel free to replace [new_project_language] with the translation of your language.
|
||||
$ interface.info(_("You will be creating an [new_project_language] language project. Change the launcher language in preferences to create a project in another language."))
|
||||
|
||||
jump new_gui_project
|
||||
# When translating this, feel free to replace [new_project_language] with the translation of your language.
|
||||
interface.info(_("You will be creating an [new_project_language]{#this substitution may be localized} language project. Change the launcher language in preferences to create a project in another language."))
|
||||
|
||||
python:
|
||||
|
||||
check_language_support()
|
||||
|
||||
gui_kind = interface.choice(
|
||||
_("Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."),
|
||||
[ ( 'new_gui_project', _("New GUI Interface") ), ( 'new_theme_project', _("Legacy Theme Interface")) ],
|
||||
"new_gui_project",
|
||||
cancel=Jump("front_page"),
|
||||
project_name = ""
|
||||
while True:
|
||||
project_name = interface.input(
|
||||
_("PROJECT NAME"),
|
||||
_("Please enter the name of your project:"),
|
||||
allow=interface.PROJECT_LETTERS,
|
||||
cancel=Jump("front_page"),
|
||||
default=project_name,
|
||||
)
|
||||
|
||||
renpy.jump(gui_kind)
|
||||
project_name = project_name.strip()
|
||||
if not project_name:
|
||||
interface.error(_("The project name may not be empty."), label=None)
|
||||
continue
|
||||
|
||||
project_dir = os.path.join(persistent.projects_directory, project_name)
|
||||
|
||||
if project.manager.get(project_name) is not None:
|
||||
interface.error(_("[project_name!q] already exists. Please choose a different project name."), project_name=project_name, label=None)
|
||||
continue
|
||||
|
||||
if os.path.exists(project_dir):
|
||||
interface.error(_("[project_dir!q] already exists. Please choose a different project name."), project_dir=project_dir, label=None)
|
||||
continue
|
||||
break
|
||||
|
||||
jump expression gui_kind
|
||||
|
||||
screen select_template:
|
||||
|
||||
@@ -125,25 +149,6 @@ screen select_template:
|
||||
label new_theme_project:
|
||||
|
||||
python hide:
|
||||
|
||||
project_name = interface.input(
|
||||
_("PROJECT NAME"),
|
||||
_("Please enter the name of your project:"),
|
||||
filename=True,
|
||||
cancel=Jump("front_page"))
|
||||
|
||||
project_name = project_name.strip()
|
||||
if not project_name:
|
||||
interface.error(_("The project name may not be empty."))
|
||||
|
||||
project_dir = os.path.join(persistent.projects_directory, project_name)
|
||||
|
||||
if project.manager.get(project_name) is not None:
|
||||
interface.error(_("[project_name!q] already exists. Please choose a different project name."), project_name=project_name)
|
||||
|
||||
if os.path.exists(project_dir):
|
||||
interface.error(_("[project_dir!q] already exists. Please choose a different project name."), project_dir=project_dir)
|
||||
|
||||
if len(project.manager.templates) == 1:
|
||||
template = project.manager.templates[0]
|
||||
else:
|
||||
|
||||
@@ -267,7 +267,7 @@ init python in distribute:
|
||||
|
||||
def mkdir(self, path):
|
||||
if not os.path.isdir(path):
|
||||
os.mkdir(path, 0755)
|
||||
os.makedirs(path, 0755)
|
||||
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
@@ -278,8 +278,7 @@ init python in distribute:
|
||||
|
||||
# If this is not a directory, ensure all parent directories
|
||||
# have been created
|
||||
if not os.path.isdir(os.path.dirname(fn)):
|
||||
os.makedirs(os.path.dirname(fn), 0755)
|
||||
self.mkdir(os.path.dirname(fn))
|
||||
shutil.copy2(path, fn)
|
||||
|
||||
if xbit:
|
||||
|
||||
@@ -7,7 +7,7 @@ translate german strings:
|
||||
|
||||
# about.rpy:43
|
||||
old "View license"
|
||||
new "Lizenz ansehen"
|
||||
new "Lizenz anzeigen"
|
||||
|
||||
# add_file.rpy:28
|
||||
old "FILENAME"
|
||||
@@ -15,7 +15,7 @@ translate german strings:
|
||||
|
||||
# add_file.rpy:28
|
||||
old "Enter the name of the script file to create."
|
||||
new "Geben Sie den Namen der Script-Datei ein, um sie zu erstellen."
|
||||
new "Geben Sie den Namen der zu erstellenden Script-Datei ein."
|
||||
|
||||
# add_file.rpy:31
|
||||
old "The filename must have the .rpy extension."
|
||||
@@ -235,7 +235,7 @@ translate german strings:
|
||||
|
||||
# distribute.rpy:443
|
||||
old "Scanning project files..."
|
||||
new "Projektdateien werden geprüft …"
|
||||
new "Projektdateien werden geprüft..."
|
||||
|
||||
# distribute.rpy:459
|
||||
old "Building distributions failed:\n\nThe build.directory_name variable may not include the space, colon, or semicolon characters."
|
||||
@@ -247,7 +247,7 @@ translate german strings:
|
||||
|
||||
# distribute.rpy:516
|
||||
old "Scanning Ren'Py files..."
|
||||
new "Ren’Py-Dateien werden geprüft …"
|
||||
new "Ren’Py-Dateien werden geprüft..."
|
||||
|
||||
# distribute.rpy:569
|
||||
old "All packages have been built.\n\nDue to the presence of permission information, unpacking and repacking the Linux and Macintosh distributions on Windows is not supported."
|
||||
@@ -255,7 +255,7 @@ translate german strings:
|
||||
|
||||
# distribute.rpy:752
|
||||
old "Archiving files..."
|
||||
new "Dateien werden archiviert …"
|
||||
new "Dateien werden archiviert..."
|
||||
|
||||
# distribute.rpy:1050
|
||||
old "Unpacking the Macintosh application for signing..."
|
||||
@@ -335,7 +335,7 @@ translate german strings:
|
||||
|
||||
# distribute_gui.rpy:242
|
||||
old "Force Recompile"
|
||||
new "Force Recompile"
|
||||
new "Neu kompilieren"
|
||||
|
||||
# distribute_gui.rpy:246
|
||||
old "Build"
|
||||
@@ -409,6 +409,10 @@ translate german strings:
|
||||
old "Open [text] directory."
|
||||
new "Open [text] directory."
|
||||
|
||||
# front_page.rpy:91
|
||||
old "PROJECTS:"
|
||||
new "PROJEKTE:"
|
||||
|
||||
# front_page.rpy:93
|
||||
old "refresh"
|
||||
new "Aktualisieren"
|
||||
@@ -469,6 +473,10 @@ translate german strings:
|
||||
old "All script files"
|
||||
new "Alle Dateien"
|
||||
|
||||
# front_page.rpy:221
|
||||
old "Actions"
|
||||
new "Aktionen"
|
||||
|
||||
# front_page.rpy:223
|
||||
old "Navigate Script"
|
||||
new "Skript navigieren"
|
||||
@@ -479,7 +487,7 @@ translate german strings:
|
||||
|
||||
# front_page.rpy:237
|
||||
old "Change/Update GUI"
|
||||
new "Change/Update GUI"
|
||||
new "GUI anpassen/aktualisieren"
|
||||
|
||||
# front_page.rpy:239
|
||||
old "Change Theme"
|
||||
@@ -487,7 +495,7 @@ translate german strings:
|
||||
|
||||
# front_page.rpy:242
|
||||
old "Delete Persistent"
|
||||
new "Persistent-Dateien löschen"
|
||||
new "Persistenz-Dateien löschen"
|
||||
|
||||
# front_page.rpy:251
|
||||
old "Build Distributions"
|
||||
@@ -511,11 +519,11 @@ translate german strings:
|
||||
|
||||
# front_page.rpy:272
|
||||
old "Checking script for potential problems..."
|
||||
new "Überprüft Script auf potentielle Probleme …"
|
||||
new "Überprüfe Script auf potentielle Probleme..."
|
||||
|
||||
# front_page.rpy:287
|
||||
old "Deleting persistent data..."
|
||||
new "Löscht Persistent-Dateien …"
|
||||
new "Lösche Persistent-Dateien..."
|
||||
|
||||
# front_page.rpy:295
|
||||
old "Recompiling all rpy files into rpyc files..."
|
||||
@@ -879,7 +887,7 @@ translate german strings:
|
||||
|
||||
# preferences.rpy:94
|
||||
old "Projects directory: [text]"
|
||||
new "Projects directory: [text]"
|
||||
new "Projektverzeichnis: [text]"
|
||||
|
||||
# preferences.rpy:96
|
||||
old "Not Set"
|
||||
@@ -891,7 +899,7 @@ translate german strings:
|
||||
|
||||
# preferences.rpy:117
|
||||
old "Text editor: [text]"
|
||||
new "Text editor: [text]"
|
||||
new "Texteditor: [text]"
|
||||
|
||||
# preferences.rpy:133
|
||||
old "Update Channel:"
|
||||
@@ -923,11 +931,15 @@ translate german strings:
|
||||
|
||||
# preferences.rpy:174
|
||||
old "Show edit file section"
|
||||
new "Show edit file section"
|
||||
new "'Dateien bearbeiten' anzeigen"
|
||||
|
||||
# preferences.rpy:175
|
||||
old "Large fonts"
|
||||
new "Large fonts"
|
||||
new "Große Schriftarten"
|
||||
|
||||
# preferences.rpy:182
|
||||
old "Sponsor message"
|
||||
new "Sponsoren-Hinweis"
|
||||
|
||||
# preferences.rpy:178
|
||||
old "Console output"
|
||||
@@ -967,7 +979,7 @@ translate german strings:
|
||||
|
||||
# project.rpy:242
|
||||
old "Ren'Py is scanning the project..."
|
||||
new "Ren’Py scannt das Projekt …"
|
||||
new "Ren’Py scannt das Projekt..."
|
||||
|
||||
# project.rpy:568
|
||||
old "Launching"
|
||||
@@ -1031,7 +1043,7 @@ translate german strings:
|
||||
|
||||
# translations.rpy:224
|
||||
old "Ren'Py is generating translations...."
|
||||
new "Ren’Py erstellt Übersetzungen …"
|
||||
new "Ren’Py erstellt Übersetzungen..."
|
||||
|
||||
# translations.rpy:235
|
||||
old "Ren'Py has finished generating [language] translations."
|
||||
@@ -1087,7 +1099,7 @@ translate german strings:
|
||||
|
||||
# translations.rpy:374
|
||||
old "Ren'Py is extracting dialogue...."
|
||||
new "Ren’Py extrahiert Dialoge …"
|
||||
new "Ren’Py extrahiert Dialoge..."
|
||||
|
||||
# translations.rpy:378
|
||||
old "Ren'Py has finished extracting dialogue. The extracted dialogue can be found in dialogue.[persistent.dialogue_format] in the base directory."
|
||||
|
||||
@@ -1253,7 +1253,7 @@ translate indonesian strings:
|
||||
new "Navigasi: [project.current.display_name!q]"
|
||||
|
||||
# new_project.rpy:71
|
||||
old "You will be creating an [new_project_language] language project. Change the launcher language in preferences to create a project in another language."
|
||||
old "You will be creating an [new_project_language]{#this substitution may be localized} language project. Change the launcher language in preferences to create a project in another language."
|
||||
new "Kamu akan membuat bahasa proyek : [new_project_language]. Ganti bahasa launcher di pengaturan untuk membuat proyek dalam bahasa lain."
|
||||
|
||||
# preferences.rpy:187
|
||||
@@ -1271,4 +1271,3 @@ translate indonesian strings:
|
||||
# translations.rpy:343
|
||||
old "Extract Dialogue: [project.current.display_name!q]"
|
||||
new "Extrak Dialog: [project.current.display_name!q]"
|
||||
|
||||
|
||||
@@ -1221,7 +1221,7 @@ translate japanese strings:
|
||||
new "ナビゲーション: [project.current.display_name!q]"
|
||||
|
||||
# new_project.rpy:71
|
||||
old "You will be creating an [new_project_language] language project. Change the launcher language in preferences to create a project in another language."
|
||||
old "You will be creating an [new_project_language]{#this substitution may be localized} language project. Change the launcher language in preferences to create a project in another language."
|
||||
new "日本語のプロジェクトを作成します。別の言語のプロジェクトを作成するには、設定でランチャーの言語を変更してください。"
|
||||
|
||||
# preferences.rpy:187
|
||||
@@ -1321,4 +1321,3 @@ translate japanese strings:
|
||||
# front_page.rpy:221
|
||||
old "Actions"
|
||||
new "アクション"
|
||||
|
||||
|
||||
@@ -913,7 +913,7 @@
|
||||
new "Direktori projek tidak boleh ditetapkan. Putus asa."
|
||||
|
||||
# new_project.rpy:71
|
||||
old "You will be creating an [new_project_language] language project. Change the launcher language in preferences to create a project in another language."
|
||||
old "You will be creating an [new_project_language]{#this substitution may be localized} language project. Change the launcher language in preferences to create a project in another language."
|
||||
new "Anda akan mencipta projek bahasa [new_project_language]. Tukar bahasa pelancar dalam menu keutamaan untuk mencipta projek dalam bahasa yang lain."
|
||||
|
||||
# new_project.rpy:79
|
||||
@@ -1263,4 +1263,3 @@
|
||||
# updater.rpy:201
|
||||
old "Proceed"
|
||||
new "Teruskan"
|
||||
|
||||
|
||||
@@ -1130,7 +1130,7 @@ translate piglatin strings:
|
||||
new "Hetay rojectspay irectoryday ouldcay otnay ebay etsay. Ivinggay upay."
|
||||
|
||||
# new_project.rpy:71
|
||||
old "You will be creating an [new_project_language] language project. Change the launcher language in preferences to create a project in another language."
|
||||
old "You will be creating an [new_project_language]{#this substitution may be localized} language project. Change the launcher language in preferences to create a project in another language."
|
||||
new "Ouyay illway ebay reatingcay anay [new_project_language] anguagelay rojectpay. Hangecay hetay auncherlay anguagelay inay referencespay otay reatecay aay rojectpay inay anotheray anguagelay."
|
||||
|
||||
# new_project.rpy:79
|
||||
@@ -1484,4 +1484,3 @@ translate piglatin strings:
|
||||
# updater.rpy:188
|
||||
old "Fetching the list of update channels"
|
||||
new "Etchingfay hetay istlay ofay updateay annelschay"
|
||||
|
||||
|
||||
@@ -813,3 +813,10 @@ translate russian strings:
|
||||
old "return"
|
||||
new "вернуться"
|
||||
|
||||
# _developer\developer.rpym:154
|
||||
old "Hide deleted"
|
||||
new "Скрыть удалённые"
|
||||
|
||||
# _developer\developer.rpym:154
|
||||
old "Show deleted"
|
||||
new "Показать удалённые"
|
||||
|
||||
@@ -21,6 +21,10 @@ translate russian strings:
|
||||
old "The filename must have the .rpy extension."
|
||||
new "Имя должно иметь расширение .rpy."
|
||||
|
||||
# add_file.rpy:37
|
||||
old "The file name may not be empty."
|
||||
new "Имя файла не может быть пустым."
|
||||
|
||||
# add_file.rpy:39
|
||||
old "The file already exists."
|
||||
new "Файл уже существует."
|
||||
@@ -31,11 +35,11 @@ translate russian strings:
|
||||
|
||||
# android.rpy:30
|
||||
old "To build Android packages, please download RAPT, unzip it, and place it into the Ren'Py directory. Then restart the Ren'Py launcher."
|
||||
new "Чтобы построить Android-пакет, пожалуйста, загрузите RAPT, разархивируйте его и поместить в директорию Ren'Py. Затем перезагрузите лаунчер Ren'Py."
|
||||
new "Чтобы построить Android-пакет, пожалуйста, загрузите RAPT, разархивируйте его, и поместите в директорию Ren'Py. Затем перезагрузите лаунчер Ren'Py."
|
||||
|
||||
# android.rpy:31
|
||||
old "A Java 8 Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
|
||||
new "Чтобы построить Android-пакеты на Windows требуется инструментарий разработки Java 8. JDK отличен от JRE, и возможно, у вас есть Java без JDK.\n\nПожалуйста, {a=http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html}загрузите и установите JDK{/a}, и перезапустите лаунчер Ren'Py."
|
||||
old "A 64-bit/x64 Java 8 Development Kit is required to build Android packages on Windows. The JDK is different from the JRE, so it's possible you have Java without having the JDK.\n\nPlease {a=http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html}download and install the JDK{/a}, then restart the Ren'Py launcher."
|
||||
new "Чтобы построить Android-пакеты на Windows требуется 64-битный инструментарий разработки Java 8. JDK отличен от JRE, и возможно, у вас есть Java без JDK.\n\nПожалуйста, {a=http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html}загрузите и установите JDK{/a}, и перезапустите лаунчер Ren'Py."
|
||||
|
||||
# android.rpy:32
|
||||
old "RAPT has been installed, but you'll need to install the Android SDK before you can build Android packages. Choose Install SDK to do this."
|
||||
@@ -215,7 +219,7 @@ translate russian strings:
|
||||
|
||||
# androidstrings.rpy:17
|
||||
old "The build seems to have failed."
|
||||
new "Ой, ошибка со сборкой приключилась..."
|
||||
new "Похоже, сборка провалилась."
|
||||
|
||||
# androidstrings.rpy:18
|
||||
old "Launching app."
|
||||
@@ -225,6 +229,10 @@ translate russian strings:
|
||||
old "The build seems to have succeeded."
|
||||
new "Кажется, сборка прошла успешно!"
|
||||
|
||||
# androidstrings.rpy:20
|
||||
old "The armeabi-v7a version works on most phones on tablets, while the x86_64 version works on the simulator and chromebooks."
|
||||
new "Версия armeabi-v7a работает на большинстве смартфонов и планшетов, а версия x86_64 требуется для симуляторов и хромбуков."
|
||||
|
||||
# androidstrings.rpy:20
|
||||
old "What is the full name of your application? This name will appear in the list of installed applications."
|
||||
new "Каким будет полное имя вашего приложения? Это имя будет представлено в списке установленных приложений."
|
||||
@@ -367,7 +375,7 @@ translate russian strings:
|
||||
|
||||
# androidstrings.rpy:55
|
||||
old "Do you accept the Android SDK Terms and Conditions?"
|
||||
new "Вы принимаете условияя и положения пользования Android SDK?"
|
||||
new "Вы принимаете условия и положения пользования Android SDK?"
|
||||
|
||||
# androidstrings.rpy:56
|
||||
old "I'm downloading the Android SDK. This might take a while."
|
||||
@@ -1146,8 +1154,8 @@ translate russian strings:
|
||||
new "Директория проектов не может быть установлена. Сдаюсь."
|
||||
|
||||
# new_project.rpy:71
|
||||
old "You will be creating an [new_project_language] language project. Change the launcher language in preferences to create a project in another language."
|
||||
new "Вы создаёте проект на языке [new_project_language]. Чтобы создать проект на другом языке, измените язык лаунчера."
|
||||
old "You will be creating an [new_project_language]{#this substitution may be localized} language project. Change the launcher language in preferences to create a project in another language."
|
||||
new "Вы создаёте проект на русском языке. Чтобы создать проект на другом языке, измените язык лаунчера."
|
||||
|
||||
# new_project.rpy:79
|
||||
old "Which interface would you like to use? The new GUI has a modern look, supports wide screens and mobile devices, and is easier to customize. Legacy themes might be necessary to work with older example code.\n\n[language_support!t]\n\nIf in doubt, choose the new GUI, then click Continue on the bottom-right."
|
||||
|
||||
@@ -898,7 +898,7 @@ translate simplified_chinese strings:
|
||||
new "传统主题界面"
|
||||
|
||||
# new_project.rpy:71
|
||||
old "You will be creating an [new_project_language] language project. Change the launcher language in preferences to create a project in another language."
|
||||
old "You will be creating an [new_project_language]{#this substitution may be localized} language project. Change the launcher language in preferences to create a project in another language."
|
||||
new "您将创建一个 [new_project_language] 语言的工程。要创建其他语言的工程,请在设置里更改启动器语言。"
|
||||
|
||||
# new_project.rpy:90
|
||||
@@ -1248,4 +1248,3 @@ translate simplified_chinese strings:
|
||||
# dmgcheck.rpy:50
|
||||
old "This is probably because Ren'Py is running directly from a Macintosh drive image. To fix this, quit this launcher, copy the entire %s folder somewhere else on your computer, and run Ren'Py again."
|
||||
new "这可能是由于 Ren'Py 直接从 Macintosh 磁盘镜像中运行导致的。要修复此问题,退出启动器,复制整个 %s 文件夹到您计算机的其他任意位置,并重新运行 Ren'Py。"
|
||||
|
||||
|
||||
@@ -914,7 +914,7 @@ translate spanish strings:
|
||||
new "No se puede establecer el directorio de proyectos. Abandonando."
|
||||
|
||||
# new_project.rpy:71
|
||||
old "You will be creating an [new_project_language] language project. Change the launcher language in preferences to create a project in another language."
|
||||
old "You will be creating an [new_project_language]{#this substitution may be localized} language project. Change the launcher language in preferences to create a project in another language."
|
||||
new "Vas a crear un proyecto en idioma [new_project_language]. Cambia el idioma del lanzador en preferencias para crear un proyecto en otro idioma."
|
||||
|
||||
# new_project.rpy:79
|
||||
|
||||
@@ -116,7 +116,7 @@ screen translate:
|
||||
value FieldInputValue(persistent, "translate_language")
|
||||
size 24
|
||||
color INPUT_COLOR
|
||||
|
||||
allow interface.TRANSLATE_LETTERS
|
||||
# Left side.
|
||||
frame:
|
||||
style "l_indent"
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#define png_voidp voidp
|
||||
#endif
|
||||
|
||||
int IMG_SavePNG(const char *file, SDL_Surface *surf,int compression){
|
||||
int renpy_IMG_SavePNG(const char *file, SDL_Surface *surf,int compression){
|
||||
SDL_RWops *fp;
|
||||
int ret;
|
||||
|
||||
@@ -44,7 +44,7 @@ int IMG_SavePNG(const char *file, SDL_Surface *surf,int compression){
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ret=IMG_SavePNG_RW(fp,surf,compression);
|
||||
ret=renpy_IMG_SavePNG_RW(fp,surf,compression);
|
||||
SDL_RWclose(fp);
|
||||
return ret;
|
||||
}
|
||||
@@ -54,12 +54,12 @@ static void png_write_data(png_structp png_ptr,png_bytep data, png_size_t length
|
||||
SDL_RWwrite(rp,data,1,length);
|
||||
}
|
||||
|
||||
int IMG_SavePNG_RW(SDL_RWops *src, SDL_Surface *surf,int compression){
|
||||
int renpy_IMG_SavePNG_RW(SDL_RWops *src, SDL_Surface *surf,int compression){
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
SDL_PixelFormat *fmt=NULL;
|
||||
SDL_Surface *tempsurf=NULL;
|
||||
int ret,funky_format;
|
||||
int ret;
|
||||
unsigned int i;
|
||||
png_colorp palette;
|
||||
Uint8 *palette_alpha=NULL;
|
||||
|
||||
@@ -36,14 +36,14 @@ extern "C" {
|
||||
* Takes a filename, a surface to save, and a compression level. The
|
||||
* compression level can be 0(min) through 9(max), or -1(default).
|
||||
*/
|
||||
DECLSPEC int SDLCALL IMG_SavePNG(const char *file,
|
||||
DECLSPEC int SDLCALL renpy_IMG_SavePNG(const char *file,
|
||||
SDL_Surface *surf,
|
||||
int compression);
|
||||
/**
|
||||
* Takes a SDL_RWops pointer, a surface to save, and a compression level.
|
||||
* compression can be 0(min) through 9(max), or -1(default).
|
||||
*/
|
||||
DECLSPEC int SDLCALL IMG_SavePNG_RW(SDL_RWops *src,
|
||||
DECLSPEC int SDLCALL renpy_IMG_SavePNG_RW(SDL_RWops *src,
|
||||
SDL_Surface *surf,
|
||||
int compression);
|
||||
#ifdef __cplusplus
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ void save_png_core(PyObject *pysurf, SDL_RWops *rw, int compress) {
|
||||
surf = PySurface_AsSurface(pysurf);
|
||||
|
||||
/* Can't release GIL, since we're not using threaded RWops. */
|
||||
IMG_SavePNG_RW(rw, surf, compress);
|
||||
renpy_IMG_SavePNG_RW(rw, surf, compress);
|
||||
}
|
||||
|
||||
/* This pixellates a 32-bit RGBA pygame surface to a destination
|
||||
|
||||
@@ -12,17 +12,17 @@
|
||||
*
|
||||
* Copyright (C) 2004 Sharif FarsiWeb, Inc.
|
||||
* Copyright (C) 2001,2002 Behdad Esfahbod
|
||||
*
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library, in a file named COPYING; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
@@ -127,7 +127,7 @@ typedef FRIBIDI_UINT16 fribidi_uint16;
|
||||
typedef FRIBIDI_UINT32 fribidi_uint32;
|
||||
typedef FRIBIDI_BOOLEAN fribidi_boolean;
|
||||
|
||||
typedef FRIBIDI_UNICHAR FriBidiChar;
|
||||
typedef FRIBIDI_UINT32 FriBidiChar;
|
||||
typedef FRIBIDI_STR_INDEX FriBidiStrIndex;
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
|
||||
#define RENPY_GLES_2
|
||||
|
||||
#elif defined EMSCRIPTEN
|
||||
|
||||
#define RENPY_GLES_2
|
||||
|
||||
#elif defined RASPBERRY_PI
|
||||
|
||||
#define RENPY_GLES_2
|
||||
|
||||
+6
-2
@@ -55,7 +55,7 @@ setup_env("LD")
|
||||
setup_env("CXX")
|
||||
|
||||
import setuplib
|
||||
from setuplib import android, ios, raspi, include, library, cython, cmodule, copyfile, find_unnecessary_gen
|
||||
from setuplib import android, ios, emscripten, raspi, include, library, cython, cmodule, copyfile, find_unnecessary_gen
|
||||
|
||||
# These control the level of optimization versus debugging.
|
||||
setuplib.extra_compile_args = [ "-Wno-unused-function" ]
|
||||
@@ -189,6 +189,10 @@ if (android or ios):
|
||||
glew_libs = [ 'GLESv2', 'z', 'm' ]
|
||||
gl2_only = True
|
||||
egl = "egl_none.c"
|
||||
elif emscripten:
|
||||
glew_libs = []
|
||||
gl2_only = True
|
||||
egl = "egl_none.c"
|
||||
elif raspi:
|
||||
glew_libs = [ 'SDL2', 'GLESv2', 'EGL', 'z', 'm' ]
|
||||
gl2_only = True
|
||||
@@ -212,7 +216,7 @@ cython("renpy.gl.glenviron_limited", libs=glew_libs, compile_if=not gl2_only)
|
||||
cython("renpy.gl.glrtt_copy", libs=glew_libs)
|
||||
cython("renpy.gl.glrtt_fbo", libs=glew_libs)
|
||||
|
||||
if not (android or ios):
|
||||
if not (android or ios or emscripten):
|
||||
# renpy.angle
|
||||
def anglecopy(fn):
|
||||
copyfile("renpy/gl/" + fn, "renpy/angle/" + fn, "DEF ANGLE = False", "DEF ANGLE = True")
|
||||
|
||||
+5
-2
@@ -39,6 +39,9 @@ ios = "RENPY_IOS" in os.environ
|
||||
# True of we're building on raspberry pi.
|
||||
raspi = "RENPY_RASPBERRY_PI" in os.environ
|
||||
|
||||
# True of we're building with emscripten.
|
||||
emscripten = "RENPY_EMSCRIPTEN" in os.environ
|
||||
|
||||
# Is coverage enabled?
|
||||
coverage = "RENPY_COVERAGE" in os.environ
|
||||
|
||||
@@ -92,7 +95,7 @@ def include(header, directory=None, optional=True):
|
||||
If given, returns False rather than abandoning the process.
|
||||
"""
|
||||
|
||||
if android or ios:
|
||||
if android or ios or emscripten:
|
||||
return True
|
||||
|
||||
for i in install:
|
||||
@@ -131,7 +134,7 @@ def library(name, optional=False):
|
||||
rather than reporting an error.
|
||||
"""
|
||||
|
||||
if android or ios:
|
||||
if android or ios or emscripten:
|
||||
return True
|
||||
|
||||
for i in install:
|
||||
|
||||
+5
-2
@@ -41,7 +41,7 @@ except ImportError:
|
||||
vc_version = 0
|
||||
|
||||
# The tuple giving the version number.
|
||||
version_tuple = (7, 2, 0, vc_version)
|
||||
version_tuple = (7, 1, 2, vc_version)
|
||||
|
||||
# The name of this version.
|
||||
version_name = "On the road again."
|
||||
@@ -70,6 +70,7 @@ macintosh = False
|
||||
linux = False
|
||||
android = False
|
||||
ios = False
|
||||
emscripten = False
|
||||
|
||||
# Should we enable experimental features and debugging?
|
||||
experimental = "RENPY_EXPERIMENTAL" in os.environ
|
||||
@@ -121,11 +122,13 @@ elif platform.mac_ver()[0]:
|
||||
macintosh = True
|
||||
elif "ANDROID_PRIVATE" in os.environ:
|
||||
android = True
|
||||
elif sys.platform == 'emscripten':
|
||||
emscripten = True
|
||||
else:
|
||||
linux = True
|
||||
|
||||
# A flag that's true if we're on a smartphone or tablet-like platform.
|
||||
mobile = android or ios
|
||||
mobile = android or ios or emscripten
|
||||
|
||||
# A flag that's set to true if the game directory is bundled inside a mac app.
|
||||
macapp = False
|
||||
|
||||
+3
-1
@@ -767,7 +767,6 @@ class Label(Node):
|
||||
rollback = "force"
|
||||
|
||||
translation_relevant = True
|
||||
|
||||
__slots__ = [
|
||||
'name',
|
||||
'parameters',
|
||||
@@ -1409,6 +1408,9 @@ class Call(Node):
|
||||
args, kwargs = self.arguments.evaluate()
|
||||
renpy.store._args = args
|
||||
renpy.store._kwargs = kwargs
|
||||
else:
|
||||
renpy.store._args = None
|
||||
renpy.store._kwargs = None
|
||||
|
||||
def predict(self):
|
||||
|
||||
|
||||
@@ -335,7 +335,7 @@ class Channel(object):
|
||||
"""
|
||||
|
||||
# Update the channel volume.
|
||||
vol = self.chan_volume * renpy.game.preferences.volumes[self.mixer]
|
||||
vol = self.chan_volume * renpy.game.preferences.volumes.get(self.mixer, 1.0)
|
||||
|
||||
if vol != self.actual_volume:
|
||||
renpysound.set_volume(self.number, vol)
|
||||
@@ -343,7 +343,7 @@ class Channel(object):
|
||||
|
||||
# This should be set from something that checks to see if our
|
||||
# mixer is muted.
|
||||
force_stop = self.context.force_stop or (renpy.game.preferences.mute[self.mixer] and self.stop_on_mute)
|
||||
force_stop = self.context.force_stop or (renpy.game.preferences.mute.get(self.mixer, False) and self.stop_on_mute)
|
||||
|
||||
if self.playing and force_stop:
|
||||
renpysound.stop(self.number)
|
||||
|
||||
@@ -58,8 +58,8 @@ set_mixer = renpy.audio.music.set_mixer
|
||||
set_queue_empty_callback = renpy.audio.music.set_queue_empty_callback
|
||||
|
||||
|
||||
def set_volume(volume, channel="sound"):
|
||||
renpy.audio.music.set_volume(volume, 0, channel=channel)
|
||||
def set_volume(volume, delay=0, channel="sound"):
|
||||
renpy.audio.music.set_volume(volume, delay, channel=channel)
|
||||
|
||||
|
||||
def set_pan(pan, delay, channel="sound"):
|
||||
|
||||
@@ -157,6 +157,26 @@ init -1600 python:
|
||||
|
||||
return cs.scope[self.name] == self.value
|
||||
|
||||
# Not pure.
|
||||
def SetLocalVariable(name, value):
|
||||
"""
|
||||
:doc: data_action
|
||||
|
||||
Causes the variable `name` to be set to `value` in the current
|
||||
local context.
|
||||
|
||||
This function is only useful in a screen that has been use by
|
||||
another scene, as it provides a way of setting the value of a
|
||||
variable inside the used screen. In all other cases,
|
||||
:func:`SetScreenVariable` should be preferred, as it allows more
|
||||
of the screen to be cached.
|
||||
|
||||
This must be created in the context that the variable is set
|
||||
in - it can't be passed in from somewhere else.
|
||||
"""
|
||||
|
||||
return SetDict(sys._getframe(1).f_locals, name, value)
|
||||
|
||||
|
||||
@renpy.pure
|
||||
class ToggleField(Action, FieldEquality):
|
||||
@@ -224,9 +244,9 @@ init -1600 python:
|
||||
|
||||
|
||||
`true_value`
|
||||
If not None, then this is the true value we use.
|
||||
If not None, then this is the true value used.
|
||||
`false_value`
|
||||
If not None, then this is the false value we use.
|
||||
If not None, then this is the false value used.
|
||||
"""
|
||||
|
||||
return ToggleField(store, variable, true_value=true_value, false_value=false_value, kind="variable")
|
||||
@@ -241,9 +261,9 @@ init -1600 python:
|
||||
value when the action is performed.
|
||||
|
||||
`true_value`
|
||||
If not None, then this is the true value we use.
|
||||
If not None, then this is the true value used.
|
||||
`false_value`
|
||||
If not None, then this is the false value we use.
|
||||
If not None, then this is the false value used.
|
||||
"""
|
||||
|
||||
identity_fields = [ "dict", ]
|
||||
@@ -283,6 +303,29 @@ init -1600 python:
|
||||
|
||||
return rv
|
||||
|
||||
# Not pure.
|
||||
def ToggleLocalVariable(name, true_value=None, false_value=None):
|
||||
"""
|
||||
:doc: data_action
|
||||
|
||||
Toggles the value of `name` in the current local context.
|
||||
|
||||
This function is only useful in a screen that has been use by
|
||||
another scene, as it provides a way of setting the value of a
|
||||
variable inside the used screen. In all other cases,
|
||||
:func:`ToggleScreenVariable` should be preferred, as it allows more
|
||||
of the screen to be cached.
|
||||
|
||||
This must be created in the context that the variable is set
|
||||
in - it can't be passed in from somewhere else.
|
||||
|
||||
`true_value`
|
||||
If not None, then this is the true value used.
|
||||
`false_value`
|
||||
If not None, then this is the false value used.
|
||||
"""
|
||||
|
||||
return ToggleDict(sys._getframe(1).f_locals, name, true_value=true_value, false_value=false_value)
|
||||
|
||||
@renpy.pure
|
||||
class ToggleScreenVariable(Action, FieldEquality):
|
||||
@@ -292,9 +335,9 @@ init -1600 python:
|
||||
Toggles the value of the variable `name` in the current screen.
|
||||
|
||||
`true_value`
|
||||
If not None, then this is the true value we use.
|
||||
If not None, then this is the true value used.
|
||||
`false_value`
|
||||
If not None, then this is the false value we use.
|
||||
If not None, then this is the false value used.
|
||||
"""
|
||||
|
||||
equality_fields = [ "name", "true_value", "false_value" ]
|
||||
|
||||
@@ -748,26 +748,35 @@ init -1500 python:
|
||||
|
||||
class FilePageNext(Action, DictEquality):
|
||||
"""
|
||||
:doc: file_action
|
||||
:doc: file_action
|
||||
|
||||
Goes to the next file page.
|
||||
Goes to the next file page.
|
||||
|
||||
`max`
|
||||
If set, this should be an integer that gives the number of
|
||||
the maximum file page we can go to.
|
||||
`max`
|
||||
If set, this should be an integer that gives the number of
|
||||
the maximum file page we can go to.
|
||||
|
||||
`wrap`
|
||||
If true, we can go to the first page when on the last file page if max is set.
|
||||
"""
|
||||
`wrap`
|
||||
If true, we can go to the first page when on the
|
||||
last file page if `max` is set.
|
||||
|
||||
`auto`
|
||||
If true and wrap is set, this can bring the player to
|
||||
the page of automatic saves.
|
||||
|
||||
`quick`
|
||||
If true and wrap is set, this can bring the player to
|
||||
the page of automatic saves.
|
||||
"""
|
||||
|
||||
alt = _("Next file page.")
|
||||
|
||||
def __init__(self, max=None, wrap=False):
|
||||
def __init__(self, max=None, wrap=False, auto=True, quick=True):
|
||||
|
||||
page = persistent._file_page
|
||||
|
||||
if page == "auto":
|
||||
if config.has_quicksave:
|
||||
if config.has_quicksave and quick:
|
||||
page = "quick"
|
||||
else:
|
||||
page = "1"
|
||||
@@ -781,9 +790,9 @@ init -1500 python:
|
||||
if max is not None:
|
||||
if page > max:
|
||||
if wrap:
|
||||
if config.has_autosave:
|
||||
if config.has_autosave and auto:
|
||||
page = "auto"
|
||||
elif config.has_quicksave:
|
||||
elif config.has_quicksave and quick:
|
||||
page = "quick"
|
||||
else:
|
||||
page = "1"
|
||||
@@ -815,40 +824,48 @@ init -1500 python:
|
||||
|
||||
Goes to the previous file page, if possible.
|
||||
|
||||
`max`
|
||||
If set, this should be an integer that gives the number of
|
||||
the maximum file page we can go to. This is required to enable
|
||||
wrap.
|
||||
`max`
|
||||
If set, this should be an integer that gives the number of
|
||||
the maximum file page we can go to. This is required to enable
|
||||
wrap.
|
||||
|
||||
`wrap`
|
||||
If true, we can go to the last page when on the first file page if max is set.
|
||||
|
||||
`auto`
|
||||
If true, this can bring the player to
|
||||
the page of automatic saves.
|
||||
|
||||
`quick`
|
||||
If true, this can bring the player to
|
||||
the page of automatic saves.
|
||||
|
||||
`wrap`
|
||||
If true, we can go to the last page when on the first file page if max is set.
|
||||
"""
|
||||
|
||||
alt = _("Previous file page.")
|
||||
|
||||
def __init__(self, max=None, wrap=False):
|
||||
def __init__(self, max=None, wrap=False, auto=True, quick=True):
|
||||
|
||||
if wrap and max is not None:
|
||||
max = str(max)
|
||||
else:
|
||||
max = None
|
||||
|
||||
|
||||
page = persistent._file_page
|
||||
|
||||
if page == "auto":
|
||||
page = max
|
||||
|
||||
elif page == "quick":
|
||||
if config.has_autosave:
|
||||
if config.has_autosave and auto:
|
||||
page = "auto"
|
||||
else:
|
||||
page = max
|
||||
|
||||
elif page == "1":
|
||||
if config.has_quicksave:
|
||||
if config.has_quicksave and quick:
|
||||
page = "quick"
|
||||
elif config.has_autosave:
|
||||
elif config.has_autosave and auto:
|
||||
page = "auto"
|
||||
else:
|
||||
page = max
|
||||
|
||||
@@ -180,6 +180,9 @@ init -1900 python:
|
||||
config.window_auto_show = [ "say" ]
|
||||
config.window_auto_hide = [ "scene", "call screen" ]
|
||||
|
||||
if vesion <= (7, 1, 1):
|
||||
config.menu_actions = False
|
||||
|
||||
# The version of Ren'Py this script is intended for, or
|
||||
# None if it's intended for the current version.
|
||||
config.script_version = None
|
||||
|
||||
@@ -36,7 +36,7 @@ init -1500 python:
|
||||
config.default_afm_enable = False
|
||||
|
||||
# If not None, the default language to use.
|
||||
config.default_language = None
|
||||
config.default_language = "russian"
|
||||
|
||||
# If not None, the default value of wait_voice
|
||||
config.default_wait_for_voice = True
|
||||
@@ -76,6 +76,13 @@ init 1500 python hide:
|
||||
if config.default_afm_time is not None:
|
||||
_preferences.afm_time = config.default_afm_time
|
||||
|
||||
if config.enable_language_autodetect:
|
||||
locale, region = renpy.translation.detect_user_locale()
|
||||
if locale is not None:
|
||||
lang_name = config.locale_to_language_function(locale, region)
|
||||
if lang_name is not None:
|
||||
config.default_language = lang_name
|
||||
|
||||
if config.default_language is not None:
|
||||
_preferences.language = config.default_language
|
||||
|
||||
@@ -115,6 +122,18 @@ init 1500 python hide:
|
||||
renpy.persistent.save()
|
||||
raise Exception(error)
|
||||
|
||||
init -1500 python:
|
||||
def _locale_to_language_function(locale, region):
|
||||
lang_name = renpy.translation.locales.get(region)
|
||||
if lang_name is not None and lang_name in renpy.known_languages():
|
||||
return lang_name
|
||||
|
||||
lang_name = renpy.translation.locales.get(locale)
|
||||
if lang_name is not None and lang_name in renpy.known_languages():
|
||||
return lang_name
|
||||
|
||||
config.locale_to_language_function = _locale_to_language_function
|
||||
|
||||
init -1500 python:
|
||||
def _imagemap_auto_function(auto_param, variant):
|
||||
rv = auto_param % variant
|
||||
@@ -203,3 +222,5 @@ init -1500:
|
||||
image text = renpy.ParameterizedText(style="centered_text")
|
||||
image vtext = renpy.ParameterizedText(style="centered_vtext")
|
||||
|
||||
# Set _version to the version when the game was first started.
|
||||
default _version = config.version
|
||||
|
||||
@@ -352,7 +352,7 @@ init -1400:
|
||||
|
||||
define irisout = CropMove(1.0, "irisout")
|
||||
define irisin = CropMove(1.0, "irisin")
|
||||
|
||||
|
||||
# Various uses of PushMove.
|
||||
define pushright = PushMove(1.0, "pushright")
|
||||
define pushleft = PushMove(1.0, "pushleft")
|
||||
@@ -375,6 +375,8 @@ init -1400:
|
||||
|
||||
# The default narrator.
|
||||
define _narrator = Character(None, kind=adv, what_style='say_thought')
|
||||
define centered = Character(None, what_style="centered_text", window_style="centered_window")
|
||||
define vcentered = Character(None, what_style="centered_vtext", window_style="centered_window")
|
||||
|
||||
init 1400 python:
|
||||
if not hasattr(store, 'narrator'):
|
||||
@@ -383,14 +385,6 @@ init 1400 python:
|
||||
renpy.pure('narrator')
|
||||
renpy.pure('name_only')
|
||||
|
||||
if not hasattr(store, 'centered'):
|
||||
centered = Character(None, what_style="centered_text", window_style="centered_window")
|
||||
if not hasattr(store, 'vcentered'):
|
||||
vcentered = Character(None, what_style="centered_vtext", window_style="centered_window")
|
||||
|
||||
renpy.pure('centered')
|
||||
renpy.pure('vcentered')
|
||||
|
||||
# This is necessary to ensure that config.default_transform works.
|
||||
if config.default_transform:
|
||||
config.default_transform._show()
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
# This is kind of a catch-all file for things that are defined in the library,
|
||||
# but don't merit their own files.
|
||||
|
||||
init -9999:
|
||||
init 9999:
|
||||
# Re-run the errorhandling setup, so we can adjust the styles to the new size
|
||||
# of the screen.
|
||||
call _errorhandling
|
||||
|
||||
@@ -79,8 +79,10 @@ init 1600:
|
||||
|
||||
else:
|
||||
for i, m in enumerate(mixers):
|
||||
|
||||
renpy.sound.set_mixer(i, m, default=True)
|
||||
if m == 'music':
|
||||
|
||||
if i >= 3:
|
||||
renpy.music.set_music(i, True, default=True)
|
||||
else:
|
||||
renpy.music.set_music(i, False, default=True)
|
||||
|
||||
@@ -30,7 +30,7 @@ screen _developer:
|
||||
modal True
|
||||
|
||||
frame:
|
||||
style_group ""
|
||||
style_prefix ""
|
||||
|
||||
has side "t c b":
|
||||
spacing gui._scale(10)
|
||||
@@ -74,7 +74,7 @@ screen _developer:
|
||||
screen _image_attributes():
|
||||
|
||||
frame:
|
||||
style_group ""
|
||||
style_prefix ""
|
||||
right_padding 0
|
||||
|
||||
has side "c b":
|
||||
@@ -110,13 +110,19 @@ label _image_attributes:
|
||||
|
||||
return
|
||||
|
||||
screen _variable_viewer(entries):
|
||||
screen _variable_viewer(all_entries, deleted_entries):
|
||||
|
||||
zorder 1010
|
||||
modal True
|
||||
default show_deleted = True
|
||||
python:
|
||||
if show_deleted:
|
||||
entries = all_entries
|
||||
else:
|
||||
entries = [(n, v) for n, v in all_entries if n not in deleted_entries]
|
||||
|
||||
frame:
|
||||
style_group ""
|
||||
style_prefix ""
|
||||
right_padding 0
|
||||
|
||||
has side "t c b":
|
||||
@@ -144,6 +150,9 @@ screen _variable_viewer(entries):
|
||||
|
||||
textbutton _(u"Return"):
|
||||
action Return(True)
|
||||
if all_entries and deleted_entries:
|
||||
textbutton (_(u"Hide deleted") if show_deleted else _(u"Show deleted")):
|
||||
action ToggleScreenVariable("show_deleted")
|
||||
|
||||
|
||||
label _debugger_screen:
|
||||
@@ -157,6 +166,7 @@ label _debugger_screen:
|
||||
aRepr.maxstring = 120
|
||||
|
||||
entries = [ ]
|
||||
deleted_entries = set()
|
||||
|
||||
for sn, d in renpy.python.store_dicts.items():
|
||||
|
||||
@@ -181,11 +191,14 @@ label _debugger_screen:
|
||||
|
||||
name = (sn + "." + vn)[6:]
|
||||
|
||||
if vn not in d:
|
||||
deleted_entries.add(name)
|
||||
|
||||
entries.append((name, value))
|
||||
|
||||
entries.sort(key=lambda e : e[0])
|
||||
|
||||
renpy.call_screen("_variable_viewer", entries=entries)
|
||||
renpy.call_screen("_variable_viewer", all_entries=entries, deleted_entries=deleted_entries)
|
||||
|
||||
return
|
||||
|
||||
@@ -477,7 +490,7 @@ screen _image_location_picker(image_files):
|
||||
default filter = ""
|
||||
|
||||
frame:
|
||||
style_group ""
|
||||
style_prefix ""
|
||||
|
||||
has side "t c b":
|
||||
spacing gui._scale(10)
|
||||
@@ -651,4 +664,3 @@ init python:
|
||||
config.underlay.append(renpy.Keymap(
|
||||
image_load_log = ToggleScreen("_image_load_log")
|
||||
))
|
||||
|
||||
|
||||
@@ -241,33 +241,35 @@ init label _errorhandling:
|
||||
color "#405060"
|
||||
hover_color Color("#048")
|
||||
|
||||
# Early hyperlink support.
|
||||
python hide:
|
||||
def hyperlink_styler(target):
|
||||
return style._hyperlink
|
||||
|
||||
def hyperlink_function(target):
|
||||
if target.startswith("http:") or target.startswith("https:"):
|
||||
try:
|
||||
import webbrowser
|
||||
webbrowser.open(target)
|
||||
except:
|
||||
pass
|
||||
|
||||
if target.startswith("edit:"):
|
||||
prefix, line, filename = target.split(":", 2)
|
||||
line = int(line)
|
||||
|
||||
renpy.launch_editor([ filename ], line)
|
||||
|
||||
style._default.hyperlink_functions = (hyperlink_styler, hyperlink_function, None)
|
||||
|
||||
return
|
||||
|
||||
# Invokes _errorhanding when this is first loaded.
|
||||
init:
|
||||
call _errorhandling
|
||||
|
||||
# Early hyperlink support.
|
||||
init python:
|
||||
|
||||
def _error_hyperlink_styler(target):
|
||||
return style._hyperlink
|
||||
|
||||
def _error_hyperlink_function(target):
|
||||
if target.startswith("http:") or target.startswith("https:"):
|
||||
try:
|
||||
import webbrowser
|
||||
webbrowser.open(target)
|
||||
except:
|
||||
pass
|
||||
|
||||
if target.startswith("edit:"):
|
||||
prefix, line, filename = target.split(":", 2)
|
||||
line = int(line)
|
||||
|
||||
renpy.launch_editor([ filename ], line)
|
||||
|
||||
style._default.hyperlink_functions = (_error_hyperlink_styler, _error_hyperlink_function, None)
|
||||
|
||||
|
||||
init python:
|
||||
|
||||
# The keymap we use before the real keymap is defined.
|
||||
|
||||
@@ -27,6 +27,7 @@ from __future__ import print_function
|
||||
|
||||
import collections
|
||||
import os
|
||||
import renpy
|
||||
|
||||
# Can we add more config variables?
|
||||
locked = False
|
||||
@@ -719,6 +720,12 @@ translate_files = [ ]
|
||||
# translated.
|
||||
translate_comments = [ ]
|
||||
|
||||
# Should we trying detect user locale on first launch?
|
||||
enable_language_autodetect = False
|
||||
|
||||
# A function from (locale, region) -> existing language.
|
||||
locale_to_language_function = None
|
||||
|
||||
# Should we pass the full argument list to the say screen?
|
||||
old_say_args = False
|
||||
|
||||
@@ -806,6 +813,8 @@ fast_skipping_callbacks = [ ]
|
||||
|
||||
# Should the audio periodic callback run in its own thread.
|
||||
audio_periodic_thread = True
|
||||
if renpy.emscripten:
|
||||
audio_periodic_thread = False
|
||||
|
||||
# A list of fonts to preload on Ren'Py startup.
|
||||
preload_fonts = [ ]
|
||||
@@ -906,6 +915,15 @@ say_attributes_use_side_image = True
|
||||
# Does the menu statement show a window by itself, when there is no caption?
|
||||
menu_showed_window = False
|
||||
|
||||
# Should the menu statement produce actions instead of values?
|
||||
menu_actions = True
|
||||
|
||||
# Should disabled menu items be included?
|
||||
menu_include_disabled = False
|
||||
|
||||
# Should we report extraneous attributes?
|
||||
report_extraneous_attributes = True
|
||||
|
||||
del os
|
||||
del collections
|
||||
|
||||
|
||||
@@ -219,8 +219,6 @@ BarValue = renpy.ui.BarValue
|
||||
|
||||
Style = renpy.style.Style # @UndefinedVariable
|
||||
|
||||
absolute = renpy.display.core.absolute
|
||||
|
||||
NoRollback = renpy.python.NoRollback
|
||||
|
||||
|
||||
|
||||
@@ -704,6 +704,9 @@ class Button(renpy.display.layout.Window):
|
||||
self._duplicatable = False
|
||||
|
||||
def _duplicate(self, args):
|
||||
if args and args.args:
|
||||
args.extraneous()
|
||||
|
||||
return self
|
||||
|
||||
def predict_one_action(self):
|
||||
|
||||
+11
-1
@@ -240,6 +240,13 @@ class DisplayableArguments(renpy.object.Object):
|
||||
|
||||
return rv
|
||||
|
||||
def extraneous(self):
|
||||
if renpy.config.developer and renpy.config.report_extraneous_attributes:
|
||||
raise Exception("Image '{}' does not accept attributes '{}'.".format(
|
||||
" ".join(self.name),
|
||||
" ".join(self.args),
|
||||
))
|
||||
|
||||
|
||||
default_style = renpy.style.Style("default")
|
||||
|
||||
@@ -352,6 +359,9 @@ class Displayable(renpy.object.Object):
|
||||
setting its own _duplicatable flag.
|
||||
"""
|
||||
|
||||
if args and args.args:
|
||||
args.extraneous()
|
||||
|
||||
return self
|
||||
|
||||
def _in_current_store(self):
|
||||
@@ -510,7 +520,7 @@ class Displayable(renpy.object.Object):
|
||||
|
||||
for d in self.visit():
|
||||
|
||||
if not d:
|
||||
if d is None:
|
||||
continue
|
||||
|
||||
id_d = id(d)
|
||||
|
||||
@@ -47,10 +47,11 @@ def default_drag_group():
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
def default_drag_joined(drag):
|
||||
return [ (drag, 0, 0) ]
|
||||
|
||||
def default_drop_allowable(drop, drags):
|
||||
return True
|
||||
|
||||
class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
|
||||
"""
|
||||
@@ -168,6 +169,12 @@ class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
|
||||
If false, the default, the drag is dropped onto the droppable with
|
||||
the largest degree of overlap.
|
||||
|
||||
`drop_allowable`
|
||||
A callback that is called to determine whether this drop allow
|
||||
the current drags dropped onto. It is called with two arguments.
|
||||
The first is the Drag which determines its sensitivity.
|
||||
The second is a list of Drags that are being dragged.
|
||||
|
||||
Except for `d`, all of the parameters are available as fields (with
|
||||
the same name) on the Drag object. In addition, after the drag has
|
||||
been rendered, the following fields become available:
|
||||
@@ -177,7 +184,7 @@ class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
|
||||
|
||||
`w`, `h`
|
||||
The width and height of the Drag's child, in pixels.
|
||||
"""
|
||||
"""
|
||||
|
||||
focusable = True
|
||||
|
||||
@@ -198,6 +205,7 @@ class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
|
||||
drag_raise=True,
|
||||
dragged=None,
|
||||
dropped=None,
|
||||
drop_allowable=default_drop_allowable,
|
||||
drag_handle=(0.0, 0.0, 1.0, 1.0),
|
||||
drag_joined=default_drag_joined,
|
||||
clicked=None,
|
||||
@@ -219,6 +227,7 @@ class Drag(renpy.display.core.Displayable, renpy.python.RevertableObject):
|
||||
self.drag_raise = drag_raise
|
||||
self.dragged = dragged
|
||||
self.dropped = dropped
|
||||
self.drop_allowable = drop_allowable
|
||||
self.drag_handle = drag_handle
|
||||
self.drag_joined = drag_joined
|
||||
self.clicked = clicked
|
||||
@@ -740,6 +749,11 @@ class DragGroup(renpy.display.layout.MultiBox):
|
||||
|
||||
All positional parameters to the DragGroup constructor should be
|
||||
Drags, that are added to the DragGroup.
|
||||
|
||||
|
||||
`min_overlap`
|
||||
An integer which means the minimum number of pixels at the
|
||||
overlap so that drop will be allow.
|
||||
"""
|
||||
|
||||
_list_type = renpy.python.RevertableList
|
||||
@@ -753,6 +767,9 @@ class DragGroup(renpy.display.layout.MultiBox):
|
||||
|
||||
replaces = properties.pop("replaces", None)
|
||||
|
||||
min_overlap = properties.pop("min_overlap", 0)
|
||||
self.min_overlap = min_overlap
|
||||
|
||||
super(DragGroup, self).__init__(**properties)
|
||||
|
||||
if replaces is not None:
|
||||
@@ -873,7 +890,11 @@ class DragGroup(renpy.display.layout.MultiBox):
|
||||
|
||||
overlap = rect_overlap_area(r1, r2)
|
||||
|
||||
if overlap >= max_overlap:
|
||||
if (
|
||||
overlap >= max_overlap and
|
||||
overlap >= self.min_overlap and
|
||||
c.drop_allowable(c, joined)
|
||||
):
|
||||
rv = c
|
||||
max_overlap = overlap
|
||||
|
||||
@@ -898,8 +919,11 @@ class DragGroup(renpy.display.layout.MultiBox):
|
||||
if c.x is None:
|
||||
continue
|
||||
|
||||
if (x >= c.x and y >= c.y and
|
||||
x < (c.x+c.w) and y < (c.y+c.h)):
|
||||
if (
|
||||
x >= c.x and y >= c.y and
|
||||
x < (c.x + c.w) and y < (c.y + c.h) and
|
||||
c.drop_allowable(c, joined)
|
||||
):
|
||||
return c
|
||||
|
||||
def get_children(self):
|
||||
|
||||
@@ -77,10 +77,14 @@ def touch_emulator(ev, x, y):
|
||||
y = 0
|
||||
|
||||
elif ev.type == pygame.KEYDOWN and not ios:
|
||||
if not ev.key in TOUCH_KEYS:
|
||||
if ev.mod & pygame.KMOD_SHIFT:
|
||||
pass
|
||||
elif not ev.key in TOUCH_KEYS:
|
||||
return None, x, y
|
||||
|
||||
elif ev.type == pygame.KEYUP and not ios:
|
||||
if ev.mod & pygame.KMOD_SHIFT:
|
||||
pass
|
||||
if not ev.key in TOUCH_KEYS:
|
||||
return None, x, y
|
||||
|
||||
|
||||
@@ -433,6 +433,9 @@ class ImageReference(renpy.display.core.Displayable):
|
||||
|
||||
def _duplicate(self, args):
|
||||
|
||||
if args and args.args:
|
||||
args.extraneous()
|
||||
|
||||
rv = self._copy(args)
|
||||
rv.target = None
|
||||
|
||||
@@ -663,6 +666,10 @@ class DynamicImage(renpy.display.core.Displayable):
|
||||
return True
|
||||
|
||||
def _duplicate(self, args):
|
||||
|
||||
if args and args.args:
|
||||
args.extraneous()
|
||||
|
||||
rv = self._copy(args)
|
||||
rv.target = None
|
||||
# This does not set _duplicatable, since it should always remain the
|
||||
|
||||
@@ -120,6 +120,9 @@ class Container(renpy.display.core.Displayable):
|
||||
|
||||
def _duplicate(self, args):
|
||||
|
||||
if args and args.args:
|
||||
args.extraneous()
|
||||
|
||||
if not self._duplicatable:
|
||||
return self
|
||||
|
||||
|
||||
@@ -983,6 +983,9 @@ class Transform(Container):
|
||||
|
||||
def _duplicate(self, args):
|
||||
|
||||
if args and args.args:
|
||||
args.extraneous()
|
||||
|
||||
if not self._duplicatable:
|
||||
return self
|
||||
|
||||
|
||||
+35
-6
@@ -137,7 +137,7 @@ def interact():
|
||||
return fullscreen
|
||||
|
||||
|
||||
def get_movie_texture(channel, mask_channel=None):
|
||||
def get_movie_texture(channel, mask_channel=None, side_mask=False):
|
||||
|
||||
if not renpy.audio.music.get_playing(channel):
|
||||
return None, False
|
||||
@@ -145,16 +145,29 @@ def get_movie_texture(channel, mask_channel=None):
|
||||
c = renpy.audio.music.get_channel(channel)
|
||||
surf = c.read_video()
|
||||
|
||||
if mask_channel:
|
||||
if side_mask:
|
||||
|
||||
if surf is not None:
|
||||
|
||||
w, h = surf.get_size()
|
||||
w //= 2
|
||||
|
||||
mask_surf = surf.subsurface((w, 0, w, h))
|
||||
surf = surf.subsurface((0, 0, w, h))
|
||||
|
||||
else:
|
||||
mask_surf = None
|
||||
|
||||
elif mask_channel:
|
||||
mc = renpy.audio.music.get_channel(mask_channel)
|
||||
mask_surf = mc.read_video()
|
||||
else:
|
||||
mask_surf = None
|
||||
|
||||
if mask_channel:
|
||||
if mask_surf is not None:
|
||||
|
||||
# Something went wrong with the mask video.
|
||||
if surf and mask_surf:
|
||||
if surf:
|
||||
renpy.display.module.alpha_munge(mask_surf, surf, renpy.display.im.identity)
|
||||
else:
|
||||
surf = None
|
||||
@@ -228,6 +241,16 @@ class Movie(renpy.display.core.Displayable):
|
||||
file will be automatically played on `channel` when the Movie is
|
||||
shown, and automatically stopped when the movie is hidden.
|
||||
|
||||
`side_mask`
|
||||
If true, this tells Ren'Py to use the side-by-side mask mode for
|
||||
the Movie. In this case, the movie is divided in half. The left
|
||||
half is used for color information, while the right half is used
|
||||
for alpha information. The width of the displayable is half the
|
||||
width of the movie file.
|
||||
|
||||
Where possible, `side_mask` should be used over `mask` as it has
|
||||
no chance of frames going out of sync.
|
||||
|
||||
`mask`
|
||||
If given, this should be the path to a movie file that is used as
|
||||
the alpha channel of this displayable. The movie file will be
|
||||
@@ -282,6 +305,7 @@ class Movie(renpy.display.core.Displayable):
|
||||
|
||||
mask = None
|
||||
mask_channel = None
|
||||
side_mask = False
|
||||
|
||||
image = None
|
||||
|
||||
@@ -302,7 +326,7 @@ class Movie(renpy.display.core.Displayable):
|
||||
|
||||
renpy.audio.music.register_channel(name, renpy.config.movie_mixer, loop=True, stop_on_mute=False, movie=True, framedrop=framedrop)
|
||||
|
||||
def __init__(self, fps=24, size=None, channel="movie", play=None, mask=None, mask_channel=None, image=None, play_callback=None, **properties):
|
||||
def __init__(self, fps=24, size=None, channel="movie", play=None, mask=None, mask_channel=None, image=None, play_callback=None, side_mask=False, **properties):
|
||||
super(Movie, self).__init__(**properties)
|
||||
|
||||
global auto_channel_serial
|
||||
@@ -314,6 +338,9 @@ class Movie(renpy.display.core.Displayable):
|
||||
self.channel = channel
|
||||
self._play = play
|
||||
|
||||
if side_mask:
|
||||
mask = None
|
||||
|
||||
self.mask = mask
|
||||
|
||||
if mask is None:
|
||||
@@ -323,6 +350,8 @@ class Movie(renpy.display.core.Displayable):
|
||||
else:
|
||||
self.mask_channel = mask_channel
|
||||
|
||||
self.side_mask = side_mask
|
||||
|
||||
self.ensure_channel(self.channel)
|
||||
self.ensure_channel(self.mask_channel)
|
||||
|
||||
@@ -357,7 +386,7 @@ class Movie(renpy.display.core.Displayable):
|
||||
|
||||
if self.size is None:
|
||||
|
||||
tex, _ = get_movie_texture(self.channel, self.mask_channel)
|
||||
tex, _ = get_movie_texture(self.channel, self.mask_channel, self.side_mask)
|
||||
|
||||
if playing and (tex is not None):
|
||||
width, height = tex.get_size()
|
||||
|
||||
+35
-4
@@ -873,9 +873,29 @@ def menu(items, set_expr):
|
||||
|
||||
# Filter the list of items to only include ones for which the
|
||||
# condition is true.
|
||||
items = [ (substitute(label), value)
|
||||
for label, condition, value in items
|
||||
if renpy.python.py_eval(condition) ]
|
||||
|
||||
if renpy.config.menu_actions:
|
||||
|
||||
location=renpy.game.context().current
|
||||
|
||||
new_items = [ ]
|
||||
|
||||
for label, condition, value in items:
|
||||
label = substitute(label)
|
||||
condition = renpy.python.py_eval(condition)
|
||||
|
||||
if (not renpy.config.menu_include_disabled) and (not condition):
|
||||
continue
|
||||
|
||||
new_items.append((label, renpy.ui.ChoiceReturn(label, value, location, sensitive=condition)))
|
||||
|
||||
items = new_items
|
||||
|
||||
else:
|
||||
|
||||
items = [ (substitute(label), value)
|
||||
for label, condition, value in items
|
||||
if renpy.python.py_eval(condition) ]
|
||||
|
||||
# Filter the list of items on the set_expr:
|
||||
if set_expr:
|
||||
@@ -904,6 +924,7 @@ def menu(items, set_expr):
|
||||
set.append(label)
|
||||
except AttributeError:
|
||||
set.add(label)
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
@@ -1035,7 +1056,11 @@ def display_menu(items,
|
||||
if not label:
|
||||
value = None
|
||||
|
||||
if value is not None:
|
||||
if isinstance(value, renpy.ui.ChoiceReturn):
|
||||
action = value
|
||||
chosen = action.get_chosen()
|
||||
|
||||
elif value is not None:
|
||||
action = renpy.ui.ChoiceReturn(label, value, location)
|
||||
chosen = action.get_chosen()
|
||||
else:
|
||||
@@ -1612,6 +1637,10 @@ def reload_script():
|
||||
|
||||
s = get_screen("menu")
|
||||
|
||||
session.pop("_reload_screen", None)
|
||||
session.pop("_reload_screen_args", None)
|
||||
session.pop("_reload_screen_kwargs", None)
|
||||
|
||||
if not renpy.store.main_menu:
|
||||
|
||||
if s is not None:
|
||||
@@ -1754,6 +1783,8 @@ except:
|
||||
platform = "Android"
|
||||
elif renpy.ios:
|
||||
platform = "iOS"
|
||||
elif sys.platform == "emscripten":
|
||||
platform = "emscripten"
|
||||
else:
|
||||
platform = "Unknown"
|
||||
|
||||
|
||||
+1
-1
@@ -557,7 +557,7 @@ cdef class GLDraw:
|
||||
|
||||
# Pick a texture environment subsystem.
|
||||
|
||||
if EGL or renpy.android or renpy.ios or (allow_shader and use_subsystem(
|
||||
if EGL or renpy.android or renpy.ios or renpy.emscripten or (allow_shader and use_subsystem(
|
||||
glenviron_shader,
|
||||
"RENPY_GL_ENVIRON",
|
||||
"shader",
|
||||
|
||||
+42
-25
@@ -139,17 +139,22 @@ def image_exists_imprecise(name):
|
||||
else:
|
||||
required.add(i)
|
||||
|
||||
for im in renpy.display.image.images:
|
||||
for im, d in renpy.display.image.images.items():
|
||||
|
||||
if im[0] != nametag:
|
||||
continue
|
||||
|
||||
attrs = set(im[1:])
|
||||
|
||||
if [ i for i in required if i not in attrs ]:
|
||||
if [ i for i in banned if i in attrs ]:
|
||||
continue
|
||||
|
||||
if [ i for i in banned if i in attrs ]:
|
||||
li = getattr(d, "_list_attributes", None)
|
||||
|
||||
if li is not None:
|
||||
attrs = attrs | set(li(im[0], required))
|
||||
|
||||
if [ i for i in required if i not in attrs ]:
|
||||
continue
|
||||
|
||||
imprecise_cache.add(name)
|
||||
@@ -172,18 +177,40 @@ def image_exists_precise(name):
|
||||
|
||||
nametag = name[0]
|
||||
|
||||
required = set(name[1:])
|
||||
required = set()
|
||||
banned = set()
|
||||
|
||||
for im in renpy.display.image.images:
|
||||
for i in name[1:]:
|
||||
if i[0] == "-":
|
||||
banned.add(i[1:])
|
||||
else:
|
||||
required.add(i)
|
||||
|
||||
for im, d in renpy.display.image.images.items():
|
||||
|
||||
if im[0] != nametag:
|
||||
continue
|
||||
|
||||
attrs = set(im[1:])
|
||||
|
||||
if attrs == required:
|
||||
precise_cache.add(name)
|
||||
return True
|
||||
if attrs - required:
|
||||
continue
|
||||
|
||||
rest = required - attrs
|
||||
|
||||
if rest:
|
||||
|
||||
try:
|
||||
da = renpy.display.core.DisplayableArguments()
|
||||
da.name=( im[0], ) + tuple(i for i in name[1:] if i in attrs)
|
||||
da.args=tuple(i for i in name[1:] if i in rest)
|
||||
d._duplicate(da)
|
||||
except:
|
||||
continue
|
||||
|
||||
precise_cache.add(name)
|
||||
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@@ -202,26 +229,16 @@ def image_exists(name, expression, tag, precise=True):
|
||||
if expression:
|
||||
return
|
||||
|
||||
namelist = list(name)
|
||||
names = " ".join(namelist)
|
||||
|
||||
# Look for the precise name.
|
||||
while namelist:
|
||||
if tuple(namelist) in renpy.display.image.images:
|
||||
return
|
||||
|
||||
namelist.pop()
|
||||
|
||||
# If we're not precise, then we have to start looking for images
|
||||
# that we can possibly match.
|
||||
if precise:
|
||||
if image_exists_precise(name):
|
||||
return
|
||||
else:
|
||||
if not precise:
|
||||
if image_exists_imprecise(name):
|
||||
return
|
||||
|
||||
report("The image named '%s' was not declared.", names)
|
||||
# If we're not precise, then we have to start looking for images
|
||||
# that we can possibly match.
|
||||
if image_exists_precise(name):
|
||||
return
|
||||
|
||||
report("'{}' is not an image.".format(" ".join(name)) )
|
||||
|
||||
|
||||
# Only check each file once.
|
||||
|
||||
+1
-1
@@ -425,7 +425,7 @@ def save(slotname, extra_info='', mutate_flag=False):
|
||||
|
||||
screenshot = renpy.game.interface.get_screenshot()
|
||||
|
||||
json = { "_save_name" : extra_info }
|
||||
json = { "_save_name" : extra_info, "_renpy_version" : list(renpy.version_tuple), "_version" : renpy.config.version }
|
||||
|
||||
for i in renpy.config.save_json_callbacks:
|
||||
i(json)
|
||||
|
||||
@@ -49,6 +49,8 @@ from renpy.translation import translate_string as __ # @UnusedImport
|
||||
|
||||
from renpy.python import store_eval as eval
|
||||
|
||||
from renpy.display.core import absolute
|
||||
|
||||
|
||||
def _(s):
|
||||
"""
|
||||
|
||||
@@ -93,6 +93,8 @@ def analyze():
|
||||
return
|
||||
|
||||
s = "\n"
|
||||
s = s.encode("utf-8")
|
||||
|
||||
renpy.log.real_stdout.write(s)
|
||||
renpy.display.log.write(s)
|
||||
|
||||
@@ -108,6 +110,7 @@ def analyze():
|
||||
dt[3],
|
||||
event.format(*args),
|
||||
)
|
||||
s = s.encode("utf-8")
|
||||
|
||||
renpy.log.real_stdout.write(s)
|
||||
renpy.display.log.write(s)
|
||||
|
||||
@@ -52,6 +52,7 @@ pure_functions = {
|
||||
# minstore.py
|
||||
"_",
|
||||
"_p",
|
||||
"absolute",
|
||||
|
||||
# defaultstore.py
|
||||
"ImageReference", "Image", "Frame", "Solid", "LiveComposite", "LiveCrop",
|
||||
|
||||
@@ -882,6 +882,7 @@ Keyword("droppable")
|
||||
Keyword("drag_raise")
|
||||
Keyword("dragged")
|
||||
Keyword("dropped")
|
||||
Keyword("drop_allowable")
|
||||
Keyword("drag_handle")
|
||||
Keyword("drag_joined")
|
||||
Keyword("clicked")
|
||||
@@ -893,6 +894,7 @@ add(ui_properties)
|
||||
add(position_properties)
|
||||
|
||||
FunctionStatementParser("draggroup", "ui.draggroup", many)
|
||||
Keyword("min_overlap")
|
||||
add(ui_properties)
|
||||
add(position_properties)
|
||||
|
||||
|
||||
+1
-1
@@ -580,7 +580,7 @@ class Script(object):
|
||||
finally:
|
||||
self.record_pycode = True
|
||||
|
||||
self.assign_names(stmts, fullfn)
|
||||
self.assign_names(stmts, renpy.parser.elide_filename(fullfn))
|
||||
|
||||
if not renpy.macapp:
|
||||
|
||||
|
||||
+15
-1
@@ -39,7 +39,7 @@ import renpy.display
|
||||
import renpy.pyanalysis
|
||||
import renpy.sl2
|
||||
|
||||
from renpy.display.motion import Transform
|
||||
from renpy.display.transform import Transform, ATLTransform
|
||||
from renpy.display.layout import Fixed
|
||||
from renpy.display.predict import displayable as predict_displayable
|
||||
|
||||
@@ -312,6 +312,9 @@ class SLBlock(SLNode):
|
||||
and child displayables.
|
||||
"""
|
||||
|
||||
# RawBlock from parse or None if not present.
|
||||
atl_transform = None
|
||||
|
||||
def __init__(self, loc):
|
||||
SLNode.__init__(self, loc)
|
||||
|
||||
@@ -377,6 +380,13 @@ class SLBlock(SLNode):
|
||||
self.has_keyword = bool(self.keyword)
|
||||
self.keyword_children = [ ]
|
||||
|
||||
if self.atl_transform is not None:
|
||||
self.has_keyword = True
|
||||
|
||||
self.atl_transform.mark_constant()
|
||||
const = self.atl_transform.constant
|
||||
self.constant = min(self.constant, const)
|
||||
|
||||
for i in self.children:
|
||||
if i.has_keyword:
|
||||
self.keyword_children.append(i)
|
||||
@@ -414,6 +424,10 @@ class SLBlock(SLNode):
|
||||
for i in self.keyword_children:
|
||||
i.keywords(context)
|
||||
|
||||
if self.atl_transform is not None:
|
||||
transform = ATLTransform(self.atl_transform, context=context.scope)
|
||||
context.keywords["at"] = transform
|
||||
|
||||
style_prefix = context.keywords.pop("style_prefix", NotGiven)
|
||||
|
||||
if style_prefix is NotGiven:
|
||||
|
||||
@@ -90,7 +90,7 @@ class ShowIf(renpy.display.layout.Container):
|
||||
if self.show_child:
|
||||
cw, ch = cr.get_size()
|
||||
rv = renpy.display.render.Render(cw, ch)
|
||||
rv.blit(cr, (0, 0))
|
||||
rv.blit(cr, (0, 0), focus=self.condition)
|
||||
else:
|
||||
rv = renpy.display.render.Render(0, 0)
|
||||
|
||||
@@ -375,6 +375,7 @@ Keyword("xinitial")
|
||||
Keyword("yinitial")
|
||||
Keyword("scrollbars")
|
||||
Keyword("spacing")
|
||||
Keyword("transpose")
|
||||
Style("spacing")
|
||||
Style("xminimum")
|
||||
Style("yminimum")
|
||||
@@ -460,6 +461,7 @@ Keyword("droppable")
|
||||
Keyword("drag_raise")
|
||||
Keyword("dragged")
|
||||
Keyword("dropped")
|
||||
Keyword("drop_allowable")
|
||||
Keyword("drag_handle")
|
||||
Keyword("drag_joined")
|
||||
Keyword("drag_offscreen")
|
||||
@@ -472,6 +474,7 @@ Keyword("alternate")
|
||||
Style("child")
|
||||
|
||||
DisplayableParser("draggroup", renpy.display.dragdrop.DragGroup, None, many, replaces=True)
|
||||
Keyword("min_overlap")
|
||||
|
||||
DisplayableParser("mousearea", renpy.display.behavior.MouseArea, 0, replaces=True)
|
||||
Keyword("hovered")
|
||||
|
||||
@@ -220,6 +220,7 @@ class Parser(object):
|
||||
"""
|
||||
|
||||
seen_keywords = set()
|
||||
block = False
|
||||
|
||||
# Parses a keyword argument from the lexer.
|
||||
def parse_keyword(l, expect):
|
||||
@@ -244,6 +245,14 @@ class Parser(object):
|
||||
|
||||
seen_keywords.add(name)
|
||||
|
||||
if name == "at" and block and l.keyword("transform"):
|
||||
l.require(":")
|
||||
l.expect_eol()
|
||||
l.expect_block("ATL block")
|
||||
expr = renpy.atl.parse_atl(l.subblock_lexer())
|
||||
target.atl_transform = expr
|
||||
return
|
||||
|
||||
expr = l.comma_expression()
|
||||
|
||||
target.keyword.append((name, expr))
|
||||
|
||||
+43
-19
@@ -32,7 +32,22 @@ registry = { }
|
||||
parsers = renpy.parser.ParseTrie()
|
||||
|
||||
|
||||
def register(name, parse=None, lint=None, execute=None, predict=None, next=None, scry=None, block=False, init=False, translatable=False, execute_init=None, label=None, warp=None): # @ReservedAssignment
|
||||
def register(
|
||||
name,
|
||||
parse=None,
|
||||
lint=None,
|
||||
execute=None,
|
||||
predict=None,
|
||||
next=None,
|
||||
scry=None,
|
||||
block=False,
|
||||
init=False,
|
||||
translatable=False,
|
||||
execute_init=None,
|
||||
init_priority=0,
|
||||
label=None,
|
||||
warp=None,
|
||||
):
|
||||
"""
|
||||
:doc: statement_register
|
||||
:name: renpy.register_statement
|
||||
@@ -48,7 +63,8 @@ def register(name, parse=None, lint=None, execute=None, predict=None, next=None,
|
||||
When this is False, the statement does not expect a block. When True, it
|
||||
expects a block, but leaves it up to the lexer to parse that block. If the
|
||||
string "script", the block is interpreted as containing one or more
|
||||
Ren'Py script language statements.
|
||||
Ren'Py script language statements. If the string "possible", the
|
||||
block expect condition is determined by the parse function.
|
||||
|
||||
`parse`
|
||||
This is a function that takes a Lexer object. This function should parse the
|
||||
@@ -99,21 +115,29 @@ def register(name, parse=None, lint=None, execute=None, predict=None, next=None,
|
||||
`init`
|
||||
True if this statement should be run at init-time. (If the statement
|
||||
is not already inside an init block, it's automatically placed inside
|
||||
an init 0 block.) This calls the execute function, in addition to the
|
||||
an init block.) This calls the execute function, in addition to the
|
||||
execute_init function.
|
||||
|
||||
`init_priority`
|
||||
An integer that determines the priority of initialisation of init block.
|
||||
|
||||
"""
|
||||
name = tuple(name.split())
|
||||
|
||||
registry[name] = dict(parse=parse,
|
||||
lint=lint,
|
||||
execute=execute,
|
||||
execute_init=execute_init,
|
||||
predict=predict,
|
||||
next=next,
|
||||
scry=scry,
|
||||
label=label,
|
||||
warp=warp)
|
||||
registry[name] = dict(
|
||||
parse=parse,
|
||||
lint=lint,
|
||||
execute=execute,
|
||||
execute_init=execute_init,
|
||||
predict=predict,
|
||||
next=next,
|
||||
scry=scry,
|
||||
label=label,
|
||||
warp=warp,
|
||||
)
|
||||
|
||||
if block not in [True, False, "script", "possible"]:
|
||||
raise Exception("Unknown \"block\" argument value: {}".format(block))
|
||||
|
||||
# The function that is called to create an ast.UserStatement.
|
||||
def parse_user_statement(l, loc):
|
||||
@@ -123,21 +147,21 @@ def register(name, parse=None, lint=None, execute=None, predict=None, next=None,
|
||||
rv = renpy.ast.UserStatement(loc, l.text, l.subblock)
|
||||
rv.translatable = translatable
|
||||
|
||||
if not block:
|
||||
if block is False:
|
||||
l.expect_noblock(" ".join(name) + " statement")
|
||||
l.advance()
|
||||
elif block is True:
|
||||
l.expect_block(" ".join(name) + " statement")
|
||||
elif block == "script":
|
||||
l.expect_block(" ".join(name) + " statement")
|
||||
rv.code_block = renpy.parser.parse_block(l.subblock_lexer())
|
||||
l.advance()
|
||||
else:
|
||||
l.expect_block(" ".join(name) + " statement")
|
||||
l.advance()
|
||||
|
||||
l.advance()
|
||||
|
||||
finally:
|
||||
renpy.exports.pop_error_handler()
|
||||
|
||||
if init and not l.init:
|
||||
rv = renpy.ast.Init(loc, [ rv ], 0)
|
||||
rv = renpy.ast.Init(loc, [rv], init_priority + l.init_offset)
|
||||
|
||||
return rv
|
||||
|
||||
|
||||
+30
-32
@@ -640,9 +640,6 @@ cdef class FTFont:
|
||||
if glyph.split == SPLIT_INSTEAD:
|
||||
continue
|
||||
|
||||
if glyph.width == 0:
|
||||
continue
|
||||
|
||||
x = <int> (glyph.x + xo)
|
||||
y = <int> (glyph.y + yo)
|
||||
|
||||
@@ -668,37 +665,38 @@ cdef class FTFont:
|
||||
|
||||
underline_end = min(underline_end, surf.w - 1)
|
||||
|
||||
for py from 0 <= py < rows:
|
||||
if glyph.width > 0:
|
||||
|
||||
for py from 0 <= py < rows:
|
||||
|
||||
if bmy < 0:
|
||||
bmy += 1
|
||||
continue
|
||||
|
||||
line = pixels + bmy * pitch + bmx * 4
|
||||
gline = cache.bitmap.buffer + py * cache.bitmap.pitch + pxstart
|
||||
|
||||
for px from 0 <= px < width:
|
||||
|
||||
alpha = gline[0]
|
||||
|
||||
# Modulate Sa by the glyph's alpha.
|
||||
|
||||
alpha = (alpha * Sa + Sa) >> 8
|
||||
|
||||
# Only draw if we increase the alpha - a cheap way to
|
||||
# allow overlapping characters.
|
||||
if line[3] < alpha:
|
||||
|
||||
line[0] = Sr
|
||||
line[1] = Sg
|
||||
line[2] = Sb
|
||||
line[3] = alpha
|
||||
|
||||
gline += 1
|
||||
line += 4
|
||||
|
||||
if bmy < 0:
|
||||
bmy += 1
|
||||
continue
|
||||
|
||||
line = pixels + bmy * pitch + bmx * 4
|
||||
gline = cache.bitmap.buffer + py * cache.bitmap.pitch + pxstart
|
||||
|
||||
for px from 0 <= px < width:
|
||||
|
||||
alpha = gline[0]
|
||||
|
||||
# Modulate Sa by the glyph's alpha.
|
||||
|
||||
alpha = (alpha * Sa + Sa) >> 8
|
||||
|
||||
# Only draw if we increase the alpha - a cheap way to
|
||||
# allow overlapping characters.
|
||||
if line[3] < alpha:
|
||||
|
||||
line[0] = Sr
|
||||
line[1] = Sg
|
||||
line[2] = Sb
|
||||
line[3] = alpha
|
||||
|
||||
gline += 1
|
||||
line += 4
|
||||
|
||||
bmy += 1
|
||||
|
||||
|
||||
# Underlining.
|
||||
if underline:
|
||||
|
||||
+232
-178
@@ -875,212 +875,250 @@ class Layout(object):
|
||||
|
||||
for type, text in tokens: # @ReservedAssignment
|
||||
|
||||
if type == PARAGRAPH:
|
||||
try:
|
||||
|
||||
# Note that this code is duplicated for the p tag, and for
|
||||
# the empty line case, below.
|
||||
fill_empty_line()
|
||||
if type == PARAGRAPH:
|
||||
|
||||
paragraphs.append(line)
|
||||
line = [ ]
|
||||
# Note that this code is duplicated for the p tag, and for
|
||||
# the empty line case, below.
|
||||
fill_empty_line()
|
||||
|
||||
continue
|
||||
paragraphs.append(line)
|
||||
line = [ ]
|
||||
|
||||
elif type == TEXT:
|
||||
line.extend(tss[-1].subsegment(text))
|
||||
continue
|
||||
continue
|
||||
|
||||
elif type == DISPLAYABLE:
|
||||
line.append((DisplayableSegment(tss[-1], text, renders), u""))
|
||||
continue
|
||||
elif type == TEXT:
|
||||
line.extend(tss[-1].subsegment(text))
|
||||
continue
|
||||
|
||||
# Otherwise, we have a text tag.
|
||||
elif type == DISPLAYABLE:
|
||||
line.append((DisplayableSegment(tss[-1], text, renders), u""))
|
||||
continue
|
||||
|
||||
tag, _, value = text.partition("=")
|
||||
# Otherwise, we have a text tag.
|
||||
|
||||
if tag and tag[0] == "/":
|
||||
tss.pop()
|
||||
tag, _, value = text.partition("=")
|
||||
|
||||
if not tss:
|
||||
raise Exception("%r closes a text tag that isn't open." % text)
|
||||
if tag and tag[0] == "/":
|
||||
tss.pop()
|
||||
|
||||
elif tag == "_start":
|
||||
fs = FlagSegment()
|
||||
line.append((fs, ""))
|
||||
self.start_segment = fs
|
||||
if not tss:
|
||||
raise Exception("%r closes a text tag that isn't open." % text)
|
||||
|
||||
elif tag == "_end":
|
||||
fs = FlagSegment()
|
||||
line.append((fs, ""))
|
||||
self.end_segment = fs
|
||||
elif tag == "_start":
|
||||
fs = FlagSegment()
|
||||
line.append((fs, ""))
|
||||
self.start_segment = fs
|
||||
|
||||
elif tag == "p":
|
||||
# Duplicated from the newline tag.
|
||||
fill_empty_line()
|
||||
elif tag == "_end":
|
||||
fs = FlagSegment()
|
||||
line.append((fs, ""))
|
||||
self.end_segment = fs
|
||||
|
||||
paragraphs.append(line)
|
||||
line = [ ]
|
||||
elif tag == "p":
|
||||
# Duplicated from the newline tag.
|
||||
fill_empty_line()
|
||||
|
||||
elif tag == "space":
|
||||
width = self.scale_int(int(value))
|
||||
line.append((SpaceSegment(tss[-1], width=width), u""))
|
||||
paragraphs.append(line)
|
||||
line = [ ]
|
||||
|
||||
elif tag == "vspace":
|
||||
# Duplicates from the newline tag.
|
||||
elif tag == "space":
|
||||
|
||||
height = self.scale_int(int(value))
|
||||
if len(value) < 1:
|
||||
raise Exception("empty value supplied for tag %r" % tag)
|
||||
|
||||
if line:
|
||||
width = self.scale_int(int(value))
|
||||
line.append((SpaceSegment(tss[-1], width=width), u""))
|
||||
|
||||
elif tag == "vspace":
|
||||
|
||||
if len(value) < 1:
|
||||
raise Exception("empty value supplied for tag %r" % tag)
|
||||
|
||||
# Duplicates from the newline tag.
|
||||
|
||||
height = self.scale_int(int(value))
|
||||
|
||||
if line:
|
||||
paragraphs.append(line)
|
||||
|
||||
line = [ (SpaceSegment(tss[-1], height=height), u"") ]
|
||||
paragraphs.append(line)
|
||||
|
||||
line = [ (SpaceSegment(tss[-1], height=height), u"") ]
|
||||
paragraphs.append(line)
|
||||
line = [ ]
|
||||
|
||||
line = [ ]
|
||||
elif tag == "w":
|
||||
pass
|
||||
|
||||
elif tag == "w":
|
||||
pass
|
||||
elif tag == "fast":
|
||||
pass
|
||||
|
||||
elif tag == "fast":
|
||||
pass
|
||||
elif tag == "nw":
|
||||
pass
|
||||
|
||||
elif tag == "nw":
|
||||
pass
|
||||
elif tag == "a":
|
||||
self.has_hyperlinks = True
|
||||
|
||||
elif tag == "a":
|
||||
self.has_hyperlinks = True
|
||||
hyperlink_styler = style.hyperlink_functions[0]
|
||||
|
||||
hyperlink_styler = style.hyperlink_functions[0]
|
||||
if hyperlink_styler:
|
||||
hls = hyperlink_styler(value)
|
||||
else:
|
||||
hls = style
|
||||
|
||||
old_prefix = hls.prefix
|
||||
|
||||
link = len(self.hyperlink_targets) + 1
|
||||
self.hyperlink_targets[link] = value
|
||||
|
||||
if not text_displayable.hyperlink_sensitive(value):
|
||||
hls.set_prefix("insensitive_")
|
||||
elif (renpy.display.focus.get_focused() is text_displayable) and (renpy.display.focus.argument == link):
|
||||
hls.set_prefix("hover_")
|
||||
else:
|
||||
hls.set_prefix("idle_")
|
||||
|
||||
ts = push()
|
||||
# inherit vertical style
|
||||
vert_style = ts.vertical
|
||||
size = ts.size
|
||||
|
||||
ts.take_style(hls, self)
|
||||
|
||||
ts.vertical = vert_style
|
||||
ts.hyperlink = link
|
||||
|
||||
if renpy.config.hyperlink_inherit_size:
|
||||
ts.size = size
|
||||
|
||||
hls.set_prefix(old_prefix)
|
||||
|
||||
elif tag == "b":
|
||||
push().bold = True
|
||||
|
||||
elif tag == "i":
|
||||
push().italic = True
|
||||
|
||||
elif tag == "u":
|
||||
if value:
|
||||
push().underline = self.scale_int(int(value))
|
||||
else:
|
||||
push().underline = self.scale_int(1)
|
||||
|
||||
elif tag == "s":
|
||||
push().strikethrough = True
|
||||
|
||||
elif tag == "plain":
|
||||
ts = push()
|
||||
ts.bold = False
|
||||
ts.italic = False
|
||||
ts.underline = False
|
||||
ts.strikethrough = False
|
||||
|
||||
elif tag == "":
|
||||
style = getattr(renpy.store.style, value)
|
||||
push().take_style(style, self)
|
||||
|
||||
elif tag == "font":
|
||||
push().font = value
|
||||
|
||||
elif tag == "size":
|
||||
|
||||
if len(value) < 1:
|
||||
raise Exception("empty value supplied for tag %r" % tag)
|
||||
|
||||
if value[0] in "+-":
|
||||
push().size += int(value)
|
||||
else:
|
||||
push().size = int(value)
|
||||
|
||||
elif tag == "color":
|
||||
|
||||
if len(value) < 1:
|
||||
raise Exception("empty value supplied for tag %r" % tag)
|
||||
|
||||
push().color = renpy.easy.color(value)
|
||||
|
||||
elif tag == "outlinecolor":
|
||||
|
||||
if len(value) < 1:
|
||||
raise Exception("empty value supplied for tag %r" % tag)
|
||||
|
||||
push().outline_color = renpy.easy.color(value)
|
||||
|
||||
elif tag == "alpha":
|
||||
|
||||
if len(value) < 1:
|
||||
raise Exception("empty value supplied for tag %r" % tag)
|
||||
|
||||
ts = push()
|
||||
if value[0] in "+-":
|
||||
value = ts.color.alpha + float(value)
|
||||
elif value[0] == "*":
|
||||
value = ts.color.alpha * float(value[1:])
|
||||
else:
|
||||
value = float(value)
|
||||
|
||||
ts.color = ts.color.replace_opacity(value)
|
||||
|
||||
elif tag == "k":
|
||||
|
||||
if len(value) < 1:
|
||||
raise Exception("empty value supplied for tag %r" % tag)
|
||||
|
||||
push().kerning = self.scale(float(value))
|
||||
|
||||
elif tag == "rt":
|
||||
ts = push()
|
||||
# inherit vertical style
|
||||
vert_style = ts.vertical
|
||||
ts.take_style(style.ruby_style, self)
|
||||
ts.vertical = vert_style
|
||||
ts.ruby_top = True
|
||||
self.has_ruby = True
|
||||
|
||||
elif tag == "art":
|
||||
ts = push()
|
||||
# inherit vertical style
|
||||
vert_style = ts.vertical
|
||||
ts.take_style(style.altruby_style, self)
|
||||
ts.vertical = vert_style
|
||||
ts.ruby_top = "alt"
|
||||
self.has_ruby = True
|
||||
|
||||
elif tag == "rb":
|
||||
push().ruby_bottom = True
|
||||
# We only care about ruby if we have a top.
|
||||
|
||||
elif tag == "cps":
|
||||
|
||||
if len(value) < 1:
|
||||
raise Exception("empty value supplied for tag %r" % tag)
|
||||
|
||||
ts = push()
|
||||
|
||||
if value[0] == "*":
|
||||
ts.cps *= float(value[1:])
|
||||
else:
|
||||
ts.cps = float(value)
|
||||
|
||||
elif tag == "vert":
|
||||
push().vertical = True
|
||||
|
||||
elif tag == "horiz":
|
||||
ts = push()
|
||||
ts.vertical = False
|
||||
|
||||
elif tag[0] == "#":
|
||||
pass
|
||||
|
||||
if hyperlink_styler:
|
||||
hls = hyperlink_styler(value)
|
||||
else:
|
||||
hls = style
|
||||
raise Exception("Unknown text tag %r" % text)
|
||||
|
||||
old_prefix = hls.prefix
|
||||
|
||||
link = len(self.hyperlink_targets) + 1
|
||||
self.hyperlink_targets[link] = value
|
||||
|
||||
if not text_displayable.hyperlink_sensitive(value):
|
||||
hls.set_prefix("insensitive_")
|
||||
elif (renpy.display.focus.get_focused() is text_displayable) and (renpy.display.focus.argument == link):
|
||||
hls.set_prefix("hover_")
|
||||
else:
|
||||
hls.set_prefix("idle_")
|
||||
|
||||
ts = push()
|
||||
# inherit vertical style
|
||||
vert_style = ts.vertical
|
||||
size = ts.size
|
||||
|
||||
ts.take_style(hls, self)
|
||||
|
||||
ts.vertical = vert_style
|
||||
ts.hyperlink = link
|
||||
|
||||
if renpy.config.hyperlink_inherit_size:
|
||||
ts.size = size
|
||||
|
||||
hls.set_prefix(old_prefix)
|
||||
|
||||
elif tag == "b":
|
||||
push().bold = True
|
||||
|
||||
elif tag == "i":
|
||||
push().italic = True
|
||||
|
||||
elif tag == "u":
|
||||
if value:
|
||||
push().underline = self.scale_int(int(value))
|
||||
else:
|
||||
push().underline = self.scale_int(1)
|
||||
|
||||
elif tag == "s":
|
||||
push().strikethrough = True
|
||||
|
||||
elif tag == "plain":
|
||||
ts = push()
|
||||
ts.bold = False
|
||||
ts.italic = False
|
||||
ts.underline = False
|
||||
ts.strikethrough = False
|
||||
|
||||
elif tag == "":
|
||||
style = getattr(renpy.store.style, value)
|
||||
push().take_style(style, self)
|
||||
|
||||
elif tag == "font":
|
||||
push().font = value
|
||||
|
||||
elif tag == "size":
|
||||
if value[0] in "+-":
|
||||
push().size += int(value)
|
||||
else:
|
||||
push().size = int(value)
|
||||
|
||||
elif tag == "color":
|
||||
push().color = renpy.easy.color(value)
|
||||
|
||||
elif tag == "outlinecolor":
|
||||
push().outline_color = renpy.easy.color(value)
|
||||
|
||||
elif tag == "alpha":
|
||||
ts = push()
|
||||
if value[0] in "+-":
|
||||
value = ts.color.alpha + float(value)
|
||||
elif value[0] == "*":
|
||||
value = ts.color.alpha * float(value[1:])
|
||||
else:
|
||||
value = float(value)
|
||||
|
||||
ts.color = ts.color.replace_opacity(value)
|
||||
|
||||
elif tag == "k":
|
||||
push().kerning = self.scale(float(value))
|
||||
|
||||
elif tag == "rt":
|
||||
ts = push()
|
||||
# inherit vertical style
|
||||
vert_style = ts.vertical
|
||||
ts.take_style(style.ruby_style, self)
|
||||
ts.vertical = vert_style
|
||||
ts.ruby_top = True
|
||||
self.has_ruby = True
|
||||
|
||||
elif tag == "art":
|
||||
ts = push()
|
||||
# inherit vertical style
|
||||
vert_style = ts.vertical
|
||||
ts.take_style(style.altruby_style, self)
|
||||
ts.vertical = vert_style
|
||||
ts.ruby_top = "alt"
|
||||
self.has_ruby = True
|
||||
|
||||
elif tag == "rb":
|
||||
push().ruby_bottom = True
|
||||
# We only care about ruby if we have a top.
|
||||
|
||||
elif tag == "cps":
|
||||
ts = push()
|
||||
|
||||
if value[0] == "*":
|
||||
ts.cps *= float(value[1:])
|
||||
else:
|
||||
ts.cps = float(value)
|
||||
|
||||
elif tag == "vert":
|
||||
push().vertical = True
|
||||
|
||||
elif tag == "horiz":
|
||||
ts = push()
|
||||
ts.vertical = False
|
||||
|
||||
elif tag[0] == "#":
|
||||
pass
|
||||
|
||||
else:
|
||||
raise Exception("Unknown text tag %r" % text)
|
||||
except:
|
||||
renpy.game.exception_info = "While processing text tag {{{!s}}} in {!r}.:".format(text, text_displayable.get_all_text())
|
||||
raise
|
||||
|
||||
# If the line is empty, fill it with a space.
|
||||
fill_empty_line()
|
||||
@@ -1417,6 +1455,10 @@ class Text(renpy.display.core.Displayable):
|
||||
self.displayable_offsets = [ ]
|
||||
|
||||
def _duplicate(self, args):
|
||||
|
||||
if args and args.args:
|
||||
args.extraneous()
|
||||
|
||||
if self._duplicatable:
|
||||
rv = self._copy(args)
|
||||
rv._unique()
|
||||
@@ -1453,6 +1495,18 @@ class Text(renpy.display.core.Displayable):
|
||||
s = s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n")
|
||||
return u"Text \"{}\"".format(s)
|
||||
|
||||
def get_all_text(self):
|
||||
"""
|
||||
Gets all the text,
|
||||
"""
|
||||
s = u""
|
||||
|
||||
for i in self.text:
|
||||
if isinstance(i, basestring):
|
||||
s += i
|
||||
|
||||
return s
|
||||
|
||||
def _scope(self, scope, update=True):
|
||||
"""
|
||||
Called to update the scope, when necessary.
|
||||
|
||||
@@ -681,3 +681,220 @@ def known_languages():
|
||||
"""
|
||||
|
||||
return { i for i in renpy.game.script.translator.languages if i is not None } # @UndefinedVariable
|
||||
|
||||
################################################################################
|
||||
# Detect language
|
||||
################################################################################
|
||||
|
||||
locales = {
|
||||
"ab": "abkhazian",
|
||||
"aa": "afar",
|
||||
"af": "afrikaans",
|
||||
"ak": "akan",
|
||||
"sq": "albanian",
|
||||
"am": "amharic",
|
||||
"ar": "arabic",
|
||||
"an": "aragonese",
|
||||
"hy": "armenian",
|
||||
"as": "assamese",
|
||||
"av": "avaric",
|
||||
"ae": "avestan",
|
||||
"ay": "aymara",
|
||||
"az": "azerbaijani",
|
||||
"bm": "bambara",
|
||||
"ba": "bashkir",
|
||||
"eu": "basque",
|
||||
"be": "belarusian",
|
||||
"bn": "bengali",
|
||||
"bh": "bihari",
|
||||
"bi": "bislama",
|
||||
"bs": "bosnian",
|
||||
"br": "breton",
|
||||
"bg": "bulgarian",
|
||||
"my": "burmese",
|
||||
"ca": "catalan",
|
||||
"ch": "chamorro",
|
||||
"ce": "chechen",
|
||||
"ny": "chewa",
|
||||
"cv": "chuvash",
|
||||
"kw": "cornish",
|
||||
"co": "corsican",
|
||||
"cr": "cree",
|
||||
"hr": "croatian",
|
||||
"cs": "czech",
|
||||
"da": "danish",
|
||||
"dv": "maldivian",
|
||||
"nl": "dutch",
|
||||
"dz": "dzongkha",
|
||||
"en": "english",
|
||||
"et": "estonian",
|
||||
"ee": "ewe",
|
||||
"fo": "faroese",
|
||||
"fj": "fijian",
|
||||
"fi": "finnish",
|
||||
"fr": "french",
|
||||
"ff": "fulah",
|
||||
"gl": "galician",
|
||||
"ka": "georgian",
|
||||
"de": "german",
|
||||
"el": "greek",
|
||||
"gn": "guaran",
|
||||
"gu": "gujarati",
|
||||
"ht": "haitian",
|
||||
"ha": "hausa",
|
||||
"he": "hebrew",
|
||||
"hz": "herero",
|
||||
"hi": "hindi",
|
||||
"ho": "hiri_motu",
|
||||
"hu": "hungarian",
|
||||
"id": "indonesian",
|
||||
"ga": "irish",
|
||||
"ig": "igbo",
|
||||
"ik": "inupiaq",
|
||||
"is": "icelandic",
|
||||
"it": "italian",
|
||||
"iu": "inuktitut",
|
||||
"ja": "japanese",
|
||||
"jv": "javanese",
|
||||
"kl": "greenlandic",
|
||||
"kn": "kannada",
|
||||
"kr": "kanuri",
|
||||
"ks": "kashmiri",
|
||||
"kk": "kazakh",
|
||||
"km": "khmer",
|
||||
"ki": "kikuyu",
|
||||
"rw": "kinyarwanda",
|
||||
"ky": "kirghiz",
|
||||
"kv": "komi",
|
||||
"kg": "kongo",
|
||||
"ko": "korean",
|
||||
"ku": "kurdish",
|
||||
"kj": "kuanyama",
|
||||
"la": "latin",
|
||||
"lb": "luxembourgish",
|
||||
"lg": "ganda",
|
||||
"li": "limburgan",
|
||||
"ln": "lingala",
|
||||
"lo": "lao",
|
||||
"lt": "lithuanian",
|
||||
"lv": "latvian",
|
||||
"gv": "manx",
|
||||
"mk": "macedonian",
|
||||
"mg": "malagasy",
|
||||
"ms": "malay",
|
||||
"ml": "malayalam",
|
||||
"mt": "maltese",
|
||||
"mi": "maori",
|
||||
"mr": "marathi",
|
||||
"mh": "marshallese",
|
||||
"mn": "mongolian",
|
||||
"na": "nauru",
|
||||
"nv": "navaho",
|
||||
"ne": "nepali",
|
||||
"ng": "ndonga",
|
||||
"no": "norwegian",
|
||||
"ii": "nuosu",
|
||||
"nr": "ndebele",
|
||||
"oc": "occitan",
|
||||
"oj": "ojibwa",
|
||||
"om": "oromo",
|
||||
"or": "oriya",
|
||||
"os": "ossetian",
|
||||
"pa": "panjabi",
|
||||
"pi": "pali",
|
||||
"fa": "persian",
|
||||
"pl": "polish",
|
||||
"ps": "pashto",
|
||||
"pt": "portuguese",
|
||||
"qu": "quechua",
|
||||
"rm": "romansh",
|
||||
"rn": "rundi",
|
||||
"ro": "romanian",
|
||||
"ru": "russian",
|
||||
"sa": "sanskrit",
|
||||
"sc": "sardinian",
|
||||
"sd": "sindhi",
|
||||
"se": "sami",
|
||||
"sm": "samoan",
|
||||
"sg": "sango",
|
||||
"sr": "serbian",
|
||||
"gd": "gaelic",
|
||||
"sn": "shona",
|
||||
"si": "sinhala",
|
||||
"sk": "slovak",
|
||||
"sl": "slovene",
|
||||
"so": "somali",
|
||||
"st": "sotho",
|
||||
"es": "spanish",
|
||||
"su": "sundanese",
|
||||
"sw": "swahili",
|
||||
"ss": "swati",
|
||||
"sv": "swedish",
|
||||
"ta": "tamil",
|
||||
"te": "telugu",
|
||||
"tg": "tajik",
|
||||
"th": "thai",
|
||||
"ti": "tigrinya",
|
||||
"bo": "tibetan",
|
||||
"tk": "turkmen",
|
||||
"tl": "tagalog",
|
||||
"tn": "tswana",
|
||||
"to": "tongan",
|
||||
"tr": "turkish",
|
||||
"ts": "tsonga",
|
||||
"tt": "tatar",
|
||||
"tw": "twi",
|
||||
"ty": "tahitian",
|
||||
"ug": "uighur",
|
||||
"uk": "ukrainian",
|
||||
"ur": "urdu",
|
||||
"uz": "uzbek",
|
||||
"ve": "venda",
|
||||
"vi": "vietnamese",
|
||||
"wa": "walloon",
|
||||
"cy": "welsh",
|
||||
"wo": "wolof",
|
||||
"fy": "frisian",
|
||||
"xh": "xhosa",
|
||||
"yi": "yiddish",
|
||||
"yo": "yoruba",
|
||||
"za": "zhuang",
|
||||
"zu": "zulu",
|
||||
"chs": "simplified_chinese",
|
||||
"cht": "traditional_chinese",
|
||||
"zh": "traditional_chinese",
|
||||
}
|
||||
|
||||
def detect_user_locale():
|
||||
import locale
|
||||
if renpy.windows:
|
||||
import ctypes
|
||||
windll = ctypes.windll.kernel32
|
||||
locale_name = locale.windows_locale.get(windll.GetUserDefaultUILanguage())
|
||||
elif renpy.android:
|
||||
from jnius import autoclass
|
||||
Locale = autoclass('java.util.Locale')
|
||||
locale_name = str(Locale.getDefault().getLanguage())
|
||||
elif renpy.ios:
|
||||
import pyobjus
|
||||
NSLocale = pyobjus.autoclass("NSLocale")
|
||||
languages = NSLocale.preferredLanguages()
|
||||
locale_name = languages.objectAtIndex_(0).UTF8String().decode("utf-8")
|
||||
locale_name.replace("-", "_")
|
||||
else:
|
||||
locale_name = locale.getdefaultlocale()
|
||||
if locale_name is not None:
|
||||
locale_name = locale_name[0]
|
||||
|
||||
if locale_name is None:
|
||||
return None, None
|
||||
|
||||
normalize = locale.normalize(locale_name)
|
||||
if normalize == locale_name:
|
||||
language = region = locale_name
|
||||
else:
|
||||
locale_name = normalize
|
||||
if '.' in locale_name:
|
||||
locale_name, _ = locale_name.split('.', 1)
|
||||
language, region = locale_name.lower().split("_")
|
||||
return language, region
|
||||
|
||||
+6
-2
@@ -662,10 +662,13 @@ class ChoiceActionBase(Action):
|
||||
previously visited and mark it so if it is chosen.
|
||||
"""
|
||||
|
||||
def __init__(self, label, value, location=None, block_all=None):
|
||||
sensitive = True
|
||||
|
||||
def __init__(self, label, value, location=None, block_all=None, sensitive=True):
|
||||
self.label = label
|
||||
self.value = value
|
||||
self.location = location
|
||||
self.sensitive = sensitive
|
||||
|
||||
if block_all is None:
|
||||
self.block_all = renpy.config.fix_rollback_without_choice
|
||||
@@ -681,7 +684,8 @@ class ChoiceActionBase(Action):
|
||||
self.chosen = renpy.game.persistent._chosen = { }
|
||||
|
||||
def get_sensitive(self):
|
||||
return not renpy.exports.in_fixed_rollback() or (not self.block_all and self.get_selected())
|
||||
return (self.sensitive and
|
||||
not renpy.exports.in_fixed_rollback() or (not self.block_all and self.get_selected()))
|
||||
|
||||
def get_selected(self):
|
||||
roll_forward = renpy.exports.roll_forward_info()
|
||||
|
||||
@@ -236,6 +236,37 @@ Please think twice about archiving your game. Keeping files open will
|
||||
help others run your game on future platforms – platforms that may not
|
||||
exist until after you're gone.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
Some stores ask the requirements for Ren'Py applications to run. While
|
||||
this varies from game to game, here's a set of minimums for a generic
|
||||
visual novel.
|
||||
|
||||
**Windows**
|
||||
|
||||
* Version: Windows XP or higher.
|
||||
* CPU: 2.0 GHz Core 2 Duo
|
||||
* RAM: 2.0 GB
|
||||
* Graphics: OpenGL 2.0 or DirectX 9.0c
|
||||
|
||||
**macOS**
|
||||
|
||||
* Version: 10.6+
|
||||
* CPU: 2.0 GHz Core 2 Duo (64 bit only)
|
||||
* RAM: 2.0 GB
|
||||
* Graphics: OpenGL 2.0
|
||||
|
||||
**Linux**
|
||||
|
||||
* Version: Ubuntu 12.04+
|
||||
* CPU: 2.0 GHz Core 2 Duo
|
||||
* RAM: 2.0 GB
|
||||
* Graphics: OpenGL 2.0
|
||||
|
||||
The amount of disk space required is entirely determined by the assets in your
|
||||
game, and the amount of CPU and RAM needed may also vary.
|
||||
|
||||
|
||||
Build Functions
|
||||
---------------
|
||||
|
||||
@@ -2,7 +2,87 @@
|
||||
Full Changelog
|
||||
==============
|
||||
|
||||
.. _renpy-7.1.2:
|
||||
|
||||
7.1.2
|
||||
=====
|
||||
|
||||
Improvements
|
||||
------------
|
||||
|
||||
Ren'Py's screen language now support the inclusion of anonymous ATL
|
||||
transforms. It's now possible to write::
|
||||
|
||||
screen hello_title():
|
||||
text "Hello.":
|
||||
at transform:
|
||||
align (0.5, 0.5) alpha 0.0
|
||||
linear 0.5 alpha 1.0
|
||||
|
||||
The new :func:`SetLocalVariable` and :func:`ToggleLocalVariable` actions
|
||||
make it possible to set variables inside used screens.
|
||||
|
||||
The new :var:`config.menu_include_disabled` variable determines if menus
|
||||
should include entries disabled by an if clause.
|
||||
|
||||
Shift-keybindings (like shift+I and shift+R) now work in the android
|
||||
emulation mode.
|
||||
|
||||
Ren'Py now better reports errors in text tags that require a value but are
|
||||
not given one.
|
||||
|
||||
The new :var:`_version` variable indicates the version of the game itself
|
||||
that was used when a new game is first created. This only stores the version
|
||||
at game creation - after that, it's up to the creator to keep it updated.
|
||||
|
||||
The :func:`Movie` displayable now supports a new mode the color data and
|
||||
alpha mask data are placed side-by-side in the same file. This prevents
|
||||
issues where a main and mask movie could go out of sync.
|
||||
|
||||
The :func:`FilePageNext` and :func:`FilePagePrevious` functions now take
|
||||
arguments that control if the they can bring the player to the auto or
|
||||
quick save pages.
|
||||
|
||||
Translations
|
||||
------------
|
||||
|
||||
Ren'Py now has the ability to automatically detect the locale of the user's
|
||||
system, and use it to set the language. Please see
|
||||
:var:`config.enable_language_autodetect` and the :ref:`Translation <translation>`
|
||||
documentation for how this works.
|
||||
|
||||
The French, German, Korean, and Russian translations have been updated.
|
||||
|
||||
Fixes
|
||||
-----
|
||||
|
||||
A Windows-specific bug that caused RTL (the support for languages like
|
||||
Arabic and Hebrew) to corrupt the second half of text strings has been
|
||||
fixed. This should prevent garbage characters from being displayed when
|
||||
rendering those languages.
|
||||
|
||||
Ren'Py will now report an error if a game accesses an image that does not
|
||||
exist, but has as a prefix an image that does exist. Before this change,
|
||||
if ``eileen happy`` exists and ``eileen happy unknown`` was shown, the
|
||||
additional attribute would be ignored.
|
||||
|
||||
Lint has been improved to deal with images that take attributes that are
|
||||
not in the image name, like layered images.
|
||||
|
||||
Ren'Py generates choice menu images that are suitable for use on the phone.
|
||||
|
||||
Android Fixes
|
||||
-------------
|
||||
|
||||
As Ren'Py's new Android support only worked well on a 64-bit version of
|
||||
Java 8, we make that 64-bit requirement explicit.
|
||||
|
||||
|
||||
.. _renpy-7.1.1:
|
||||
|
||||
7.1.1
|
||||
=====
|
||||
|
||||
.. _history-7.1.1:
|
||||
|
||||
History Fix
|
||||
|
||||
@@ -389,6 +389,12 @@ Occasionally Used
|
||||
The default implementation of this uses the narrator character to
|
||||
display a blank line without interacting.
|
||||
|
||||
.. var:: config.enable_language_autodetect = False
|
||||
|
||||
If true, Ren'Py will attempt to determine the name of the language
|
||||
to use based on the locale of the player's system. If successful,
|
||||
this languagfe will be used as the default language.
|
||||
|
||||
.. var:: config.enter_sound = None
|
||||
|
||||
If not None, this is a sound file that is played when entering the
|
||||
@@ -520,6 +526,16 @@ Occasionally Used
|
||||
If not None, this should be a string giving the default language
|
||||
that the game is translated into by the translation framework.
|
||||
|
||||
.. var:: config.locale_to_language_function = ...
|
||||
|
||||
A function that determines the language the game should use,
|
||||
based on the the user's locale.
|
||||
It takes 2 arguments strings that give the the ISO code of the locale
|
||||
and the ISO code of the region.
|
||||
|
||||
It should return a string giving the name of a translation to use, or
|
||||
None to use the default translation.
|
||||
|
||||
.. var:: config.main_menu = [ ... ]
|
||||
|
||||
The default main menu, when not using screens. For more details,
|
||||
@@ -534,6 +550,11 @@ Occasionally Used
|
||||
A list of layer names (as strings) that are cleared when entering
|
||||
the game menu.
|
||||
|
||||
.. var:: config.menu_include_disabled = False
|
||||
|
||||
When this variable is set, choices disables with the if statement are
|
||||
included as disabled buttons.
|
||||
|
||||
.. var:: config.menu_window_subtitle = ""
|
||||
|
||||
The :var:`_window_subtitle` variable is set to this value when entering
|
||||
|
||||
@@ -56,6 +56,7 @@ the omission in future versions.
|
||||
* Eniko
|
||||
* Eevee (Lexy Munroe)
|
||||
* Evilantishad0w
|
||||
* Felix Lampe
|
||||
* Franck_v
|
||||
* Gas
|
||||
* George Economidis
|
||||
@@ -82,6 +83,7 @@ the omission in future versions.
|
||||
* Kevin Turner
|
||||
* Kinsman
|
||||
* Koichi "vbkaisetsu" Akabe
|
||||
* Konstantin Mozheyko
|
||||
* Konstantin Nikolayev
|
||||
* Kuroonehalf
|
||||
* Kyouryuukunn
|
||||
@@ -126,10 +128,12 @@ the omission in future versions.
|
||||
* Saltome
|
||||
* Sapphi
|
||||
* Scout
|
||||
* Shehriyar Qureshi
|
||||
* Shiz
|
||||
* SleepKirby
|
||||
* Spiky Caterpillar
|
||||
* Susnux
|
||||
* Sylvain Beucler
|
||||
* Thuong Nguyen Huu
|
||||
* Tlm-2501
|
||||
* Tmrwiz
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -65,4 +65,5 @@ true. In the following menu::
|
||||
...
|
||||
|
||||
The third choice will only be presented if the ``drank_tea`` variable is
|
||||
true.
|
||||
true. (However if, the :var:`config.menu_include_disabled` variable is set
|
||||
to True, it will be shown as a disabled button.)
|
||||
|
||||
@@ -1408,16 +1408,18 @@ screen quick_menu():
|
||||
|
||||
zorder 100
|
||||
|
||||
hbox:
|
||||
style_prefix "quick"
|
||||
if quick_menu:
|
||||
|
||||
xalign 0.5
|
||||
yalign 1.0
|
||||
hbox:
|
||||
style_prefix "quick"
|
||||
|
||||
textbutton _("Back") action Rollback()
|
||||
textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
|
||||
textbutton _("Auto") action Preference("auto-forward", "toggle")
|
||||
textbutton _("Menu") action ShowMenu()
|
||||
xalign 0.5
|
||||
yalign 1.0
|
||||
|
||||
textbutton _("Back") action Rollback()
|
||||
textbutton _("Skip") action Skip() alternate Skip(fast=True, confirm=True)
|
||||
textbutton _("Auto") action Preference("auto-forward", "toggle")
|
||||
textbutton _("Menu") action ShowMenu()
|
||||
|
||||
|
||||
style window:
|
||||
@@ -1455,7 +1457,3 @@ style slider_pref_vbox:
|
||||
style slider_pref_slider:
|
||||
variant "small"
|
||||
xsize 900
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+20
-11
@@ -169,10 +169,25 @@ allow the game to react to various events.
|
||||
All user interface statements take the following common properties:
|
||||
|
||||
`at`
|
||||
A transform, or list of transforms, that are used to wrap this
|
||||
displayable. The show, hide, replace, and replaced external events
|
||||
are delivered to a transform if and only if it is added directly
|
||||
to the screen.
|
||||
This can be a transform, or a list of transforms, or an anonymous
|
||||
transform (a transform that is defined directly in at)
|
||||
|
||||
::
|
||||
|
||||
transform hello_t:
|
||||
align (0.7, 0.5) alpha 0.0
|
||||
linear 0.5 alpha 1.0
|
||||
|
||||
screen hello_title():
|
||||
text "Hello." at hello_t
|
||||
text "Hello.":
|
||||
at transform:
|
||||
align (0.2, 0.5) alpha 0.0
|
||||
linear 0.5 alpha 1.0
|
||||
|
||||
This transforms are used to wrap this displayable. The show, hide,
|
||||
replace, and replaced external events are delivered to a transform
|
||||
if and only if it is added directly to the screen.
|
||||
|
||||
For example, if a vbox is wrapped in a transform, and added directly
|
||||
to the screen, then events are delivered to that transform. But if
|
||||
@@ -1808,16 +1823,11 @@ Screen Statements
|
||||
In addition to the screen statement, there are three Ren'Py script
|
||||
language statements that involve screens.
|
||||
|
||||
Two of these statements take a keyword argument list. This is a Python
|
||||
argument list, in parentheses, consisting of only keyword
|
||||
arguments. Positional arguments, extra positional arguments (*), and
|
||||
extra keyword arguments (**) are not allowed.
|
||||
|
||||
Show Screen
|
||||
-----------
|
||||
|
||||
The ``show screen`` statement causes a screen to be shown. It takes an
|
||||
screen name, and an optional argument list. If present, the arguments
|
||||
screen name, and an optional Python argument list. If present, the arguments
|
||||
are used to initialize the scope of the screen.
|
||||
|
||||
The show screen statement takes an optional ``nopredict`` keyword, that
|
||||
@@ -1986,4 +1996,3 @@ An example of defining a screen variant is:
|
||||
variant "small"
|
||||
|
||||
text "Hello, World." size 30
|
||||
|
||||
|
||||
+148
-148
@@ -1,187 +1,187 @@
|
||||
<ul class='sponsors'>
|
||||
<li> __skwrl__ (6.99.14.3–7.1.1)
|
||||
<li> Adia Alderson (6.99.13–7.1.1)
|
||||
<li> Aleema (6.99.13–7.1.1)
|
||||
<li> <a href="http://alexdodge.net/" rel="nofollow">Alex Dodge</a> (6.99.14–7.1.1)
|
||||
<li> <a href="https://rabidb.com/" rel="nofollow">AlexSSZ</a> (6.99.13–7.1.1)
|
||||
<li> <a href="https://alic-szecsei.com" rel="nofollow">Alic Szecsei</a> (6.99.14.3–7.1.1)
|
||||
<li> Anne Camlin (7.0–7.1.1)
|
||||
<li> __skwrl__ (6.99.14.3–7.1.2)
|
||||
<li> Adia Alderson (6.99.13–7.1.2)
|
||||
<li> Aleema (6.99.13–7.1.2)
|
||||
<li> <a href="http://alexdodge.net/" rel="nofollow">Alex Dodge</a> (6.99.14–7.1.2)
|
||||
<li> <a href="https://rabidb.com/" rel="nofollow">AlexSSZ</a> (6.99.13–7.1.2)
|
||||
<li> <a href="https://alic-szecsei.com" rel="nofollow">Alic Szecsei</a> (6.99.14.3–7.1.2)
|
||||
<li> Anne Camlin (7.0–7.1.2)
|
||||
<li> <a href="https://lemmasoft.renai.us/forums/viewtopic.php?f=51&t=34131" rel="nofollow">AR09FQF-AQ09FRF</a> (6.99.14.1–7.0)
|
||||
<li> Asatiir (6.99.13–7.0)
|
||||
<li> <a href="https://www.atwistedspirit.com/" rel="nofollow">ATwistedSpirit</a> (7.1–7.1.1)
|
||||
<li> <a href="https://www.atwistedspirit.com/" rel="nofollow">ATwistedSpirit</a> (7.1–7.1.2)
|
||||
<li> <a href="https://patchworkprincess.moe/" rel="nofollow">Azura (Vanessa Parker)</a> (7.0–7.1)
|
||||
<li> <a href="https://www.youtube.com/channel/UC3Xm0sk-rRCtD-yVp64WPWQ" rel="nofollow">BadGamer</a> (6.99.14.3–7.1.1)
|
||||
<li> <a href="https://www.youtube.com/channel/UC3Xm0sk-rRCtD-yVp64WPWQ" rel="nofollow">BadGamer</a> (6.99.14.3–7.1.2)
|
||||
<li> Belfort and Bastion (6.99.13–7.1)
|
||||
<li> Biotikos Development (6.99.13–7.1.1)
|
||||
<li> Biotikos Development (6.99.13–7.1.2)
|
||||
<li> Bob (6.99.13–7.0)
|
||||
<li> <a href="https://bobcgames.tumblr.com" rel="nofollow">Bob Conway</a> (6.99.14.1–7.1.1)
|
||||
<li> Bob Reus (7.1–7.1.1)
|
||||
<li> Booom313's tinker corner (6.99.14–7.1.1)
|
||||
<li> Boreas Bear (6.99.13–7.1.1)
|
||||
<li> <a href="http://boyslaughplus.moe" rel="nofollow">Boys Laugh +</a> (6.99.13–7.1.1)
|
||||
<li> <a href="https://bobcgames.tumblr.com" rel="nofollow">Bob Conway</a> (6.99.14.1–7.1.2)
|
||||
<li> Bob Reus (7.1–7.1.2)
|
||||
<li> Booom313's tinker corner (6.99.14–7.1.2)
|
||||
<li> Boreas Bear (6.99.13–7.1.2)
|
||||
<li> <a href="http://boyslaughplus.moe" rel="nofollow">Boys Laugh +</a> (6.99.13–7.1.2)
|
||||
<li> Brett Douglas (6.99.14–6.99.14.3)
|
||||
<li> Brimney (6.99.13–7.1.1)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.brunimultimedia.com" rel="nofollow">Bruni Multimedia</a> (6.99.14–7.1.1)
|
||||
<li> Brimney (6.99.13–7.1.2)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.brunimultimedia.com" rel="nofollow">Bruni Multimedia</a> (6.99.14–7.1.2)
|
||||
<li> <a href="http://www.bura.cl" rel="nofollow">BURA</a> (6.99.13)
|
||||
<li> Cameron Woodard (6.99.14.3–7.1.1)
|
||||
<li> Cara Hillstock (6.99.13–7.1.1)
|
||||
<li> <a href="https://www.celebrityhunter.com.br" rel="nofollow">Celebrity Hunter</a> (7.1–7.1.1)
|
||||
<li> Charlene Gilbert (6.99.13–7.1.1)
|
||||
<li> <a href="http://charliethegoldfish.com" rel="nofollow">Charlie Francis Cassidy</a> (6.99.13–7.1.1)
|
||||
<li> Chekhov's Ghost (7.1–7.1.1)
|
||||
<li> Cherry Kiss Games (6.99.14.1–7.1.1)
|
||||
<li> Chrysoula Tzavelas (6.99.13–7.1.1)
|
||||
<li> <a href="https://cloverfirefly.itch.io" rel="nofollow">cloverfirefly</a> (6.99.13–7.1.1)
|
||||
<li> CobaltCore (7.1.1)
|
||||
<li> CobraPL (7.1–7.1.1)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://obscurasoft.com/" rel="nofollow">Coming Out On Top</a> (6.99.13–7.1.1)
|
||||
<li> <a href="http://www.computerart.club/" rel="nofollow">computerart.club</a> (6.99.14–7.1.1)
|
||||
<li> CookieNomNom (7.1.1)
|
||||
<li> Crazy Cactus (6.99.14.3–7.1.1)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=http://cricketbat.me" rel="nofollow">cricketbat_</a> (7.0–7.1.1)
|
||||
<li> Cameron Woodard (6.99.14.3–7.1.2)
|
||||
<li> Cara Hillstock (6.99.13–7.1.2)
|
||||
<li> <a href="https://www.celebrityhunter.com.br" rel="nofollow">Celebrity Hunter</a> (7.1–7.1.2)
|
||||
<li> Charlene Gilbert (6.99.13–7.1.2)
|
||||
<li> <a href="http://charliethegoldfish.com" rel="nofollow">Charlie Francis Cassidy</a> (6.99.13–7.1.2)
|
||||
<li> Chekhov's Ghost (7.1–7.1.2)
|
||||
<li> Cherry Kiss Games (6.99.14.1–7.1.2)
|
||||
<li> Chrysoula Tzavelas (6.99.13–7.1.2)
|
||||
<li> <a href="https://cloverfirefly.itch.io" rel="nofollow">cloverfirefly</a> (6.99.13–7.1.2)
|
||||
<li> CobaltCore (7.1.1–7.1.2)
|
||||
<li> CobraPL (7.1–7.1.2)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://obscurasoft.com/" rel="nofollow">Coming Out On Top</a> (6.99.13–7.1.2)
|
||||
<li> <a href="http://www.computerart.club/" rel="nofollow">computerart.club</a> (6.99.14–7.1.2)
|
||||
<li> CookieNomNom (7.1.1–7.1.2)
|
||||
<li> Crazy Cactus (6.99.14.3–7.1.2)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=http://cricketbat.me" rel="nofollow">cricketbat_</a> (7.0–7.1.2)
|
||||
<li> <a href="http://cultofape.com" rel="nofollow">CultOfApe</a> (6.99.14–7.0)
|
||||
<li> Culture4Jam (6.99.13–7.1.1)
|
||||
<li> Daniel Burns (7.1–7.1.1)
|
||||
<li> Culture4Jam (6.99.13–7.1.2)
|
||||
<li> Daniel Burns (7.1–7.1.2)
|
||||
<li> <a href="http://dark-aii.net" rel="nofollow">Dark-Aii</a> (6.99.14.1–6.99.14.3)
|
||||
<li> <a href="http://www.darksirengames.com" rel="nofollow">DarkSirenGames</a> (6.99.13–7.1.1)
|
||||
<li> Darryl Taylor (7.0–7.1.1)
|
||||
<li> David Koster (6.99.14–7.1.1)
|
||||
<li> David Yingling (6.99.14.1–7.1.1)
|
||||
<li> Dee (7.1–7.1.1)
|
||||
<li> Denny Cheng (6.99.14.2–7.1.1)
|
||||
<li> Dharker Studios Ltd (6.99.13–6.99.14, 7.1.1)
|
||||
<li> <a href="http://coriginate.com" rel="nofollow">Ds110</a> (6.99.13–7.1.1)
|
||||
<li> DuoDevelopers (7.1.1)
|
||||
<li> E. William Brown (6.99.13–7.1.1)
|
||||
<li> <a href="https://twitter.com/WC_EchoFrost" rel="nofollow">EchoFrost (Watercress)</a> (6.99.14.2–7.1.1)
|
||||
<li> <a href="https://www.youtube.com/c/ElaineDoesCoding" rel="nofollow">ElaineDoesCoding</a> (7.0–7.1.1)
|
||||
<li> eric chi hung ng (7.0–7.1.1)
|
||||
<li> Euan 'Xolf' Robertson (6.99.13–7.1.1)
|
||||
<li> <a href="http://www.darksirengames.com" rel="nofollow">DarkSirenGames</a> (6.99.13–7.1.2)
|
||||
<li> Darryl Taylor (7.0–7.1.2)
|
||||
<li> David Koster (6.99.14–7.1.2)
|
||||
<li> David Yingling (6.99.14.1–7.1.2)
|
||||
<li> Dee (7.1–7.1.2)
|
||||
<li> Denny Cheng (6.99.14.2–7.1.2)
|
||||
<li> Dharker Studios Ltd (6.99.13–6.99.14, 7.1.1–7.1.2)
|
||||
<li> <a href="http://coriginate.com" rel="nofollow">Ds110</a> (6.99.13–7.1.2)
|
||||
<li> DuoDevelopers (7.1.1–7.1.2)
|
||||
<li> E. William Brown (6.99.13–7.1.2)
|
||||
<li> <a href="https://twitter.com/WC_EchoFrost" rel="nofollow">EchoFrost (Watercress)</a> (6.99.14.2–7.1.2)
|
||||
<li> <a href="https://www.youtube.com/c/ElaineDoesCoding" rel="nofollow">ElaineDoesCoding</a> (7.0–7.1.2)
|
||||
<li> eric chi hung ng (7.0–7.1.2)
|
||||
<li> Euan 'Xolf' Robertson (6.99.13–7.1.2)
|
||||
<li> Eve Hallows (6.99.13–6.99.14)
|
||||
<li> Exiscoming (6.99.14–7.1.1)
|
||||
<li> <a href="https://moonlitworks.com/" rel="nofollow">Eyzi</a> (7.0–7.1.1)
|
||||
<li> Fuseblower (7.0–7.1.1)
|
||||
<li> George (7.1–7.1.1)
|
||||
<li> <a href="http://www.gtbono.com" rel="nofollow">Giovanni Tempobono</a> (7.1–7.1.1)
|
||||
<li> <a href="https://goldengamebarn.com/" rel="nofollow">Golden Game Barn</a> (6.99.13–7.1.1)
|
||||
<li> <a href="https://twitter.com/goodtalesvn" rel="nofollow">Good Tales</a> (7.1–7.1.1)
|
||||
<li> Great Chicken Studio (6.99.14–7.1.1)
|
||||
<li> Grimiku (7.0–7.1.1)
|
||||
<li> Gunso (6.99.13–7.1.1)
|
||||
<li> HAG Productions (7.1.1)
|
||||
<li> <a href="http://hanb.jp" rel="nofollow">HanbitGaram (MOEWORK Entertainment)</a> (7.1–7.1.1)
|
||||
<li> Exiscoming (6.99.14–7.1.2)
|
||||
<li> <a href="https://moonlitworks.com/" rel="nofollow">Eyzi</a> (7.0–7.1.2)
|
||||
<li> Fuseblower (7.0–7.1.2)
|
||||
<li> George (7.1–7.1.2)
|
||||
<li> <a href="http://www.gtbono.com" rel="nofollow">Giovanni Tempobono</a> (7.1–7.1.2)
|
||||
<li> <a href="https://goldengamebarn.com/" rel="nofollow">Golden Game Barn</a> (6.99.13–7.1.2)
|
||||
<li> <a href="https://twitter.com/goodtalesvn" rel="nofollow">Good Tales</a> (7.1–7.1.2)
|
||||
<li> Great Chicken Studio (6.99.14–7.1.2)
|
||||
<li> Grimiku (7.0–7.1.2)
|
||||
<li> Gunso (6.99.13–7.1.2)
|
||||
<li> HAG Productions (7.1.1–7.1.2)
|
||||
<li> <a href="http://hanb.jp" rel="nofollow">HanbitGaram (MOEWORK Entertainment)</a> (7.1–7.1.2)
|
||||
<li> Happimochi (6.99.13–6.99.14)
|
||||
<li> HopesGaming (7.1.1)
|
||||
<li> HopesGaming (7.1.1–7.1.2)
|
||||
<li> <a href="https://ijemin.com" rel="nofollow">I_Jemin</a> (6.99.13–7.0)
|
||||
<li> <a href="https://irredeemable.net/" rel="nofollow">Irredeemable Games</a> (6.99.14–7.1.1)
|
||||
<li> J. C. Holder (6.99.13–7.1.1)
|
||||
<li> <a href="https://irredeemable.net/" rel="nofollow">Irredeemable Games</a> (6.99.14–7.1.2)
|
||||
<li> J. C. Holder (6.99.13–7.1.2)
|
||||
<li> James Tyner (6.99.13–7.1)
|
||||
<li> JeongPyo Lee (6.99.13–7.1.1)
|
||||
<li> Joanna B (6.99.13–7.1.1)
|
||||
<li> JoeBanks (7.1–7.1.1)
|
||||
<li> Jonas Kyratzes (7.1.1)
|
||||
<li> jonnymelabo (6.99.13–7.1.1)
|
||||
<li> JeongPyo Lee (6.99.13–7.1.2)
|
||||
<li> Joanna B (6.99.13–7.1.2)
|
||||
<li> JoeBanks (7.1–7.1.2)
|
||||
<li> Jonas Kyratzes (7.1.1–7.1.2)
|
||||
<li> jonnymelabo (6.99.13–7.1.2)
|
||||
<li> Josh Kaplan (6.99.13–6.99.14.2)
|
||||
<li> K. Starbuck (6.99.13–6.99.14)
|
||||
<li> Kampmichi (7.1.1)
|
||||
<li> Kayde Initials (6.99.13–7.1.1)
|
||||
<li> <a href="http://kexboy.com" rel="nofollow">KEXBOY</a> (6.99.13–7.1.1)
|
||||
<li> Kikai Digital (7.0–7.1.1)
|
||||
<li> <a href="http://www.gamesbykinmoku.com" rel="nofollow">Kinmoku</a> (6.99.13–7.1.1)
|
||||
<li> <a href="http://krsm94.web.fc2.com/" rel="nofollow">Klast Halc (crAsm)</a> (6.99.14.2–7.1.1)
|
||||
<li> Kosmos Games (6.99.14–7.1.1)
|
||||
<li> <a href="https://de.koubaibu.tech/" rel="nofollow">Koubaibu Technology Group</a> (7.1–7.1.1)
|
||||
<li> lain105/EckoMars (6.99.13–7.1.1)
|
||||
<li> LateWhiteRabbit (6.99.14–7.1.1)
|
||||
<li> <a href="https://lernakow.itch.io" rel="nofollow">Lernakow</a> (6.99.14.3–7.1.1)
|
||||
<li> LewdKitty (7.0–7.1.1)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.lewdlab.com/" rel="nofollow">Lewdlab</a> (6.99.14.1–7.1.1)
|
||||
<li> <a href="https://lemmasoft.renai.us/forums/viewtopic.php?f=66&t=48011&p=482643" rel="nofollow">Lezalith</a> (7.1–7.1.1)
|
||||
<li> Lictor (6.99.14.2–7.1.1)
|
||||
<li> Little Napoleon (7.1–7.1.1)
|
||||
<li> <a href="http://trash.moe/" rel="nofollow">Lore</a> (6.99.13–7.1.1)
|
||||
<li> Luke Jackson (6.99.13–7.1.1)
|
||||
<li> <a href="http://luscious-spirit-studios.tumblr.com/" rel="nofollow">Luscious Spirit Studios</a> (6.99.13–7.1.1)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.patreon.com/Luxee" rel="nofollow">Luxee</a> (6.99.14.3–7.1.1)
|
||||
<li> Maeve Bandruid (6.99.13–7.1.1)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.patreon.com/manitu" rel="nofollow">MANITU Games CO.</a> (6.99.13–7.1.1)
|
||||
<li> <a href="https://manorstories.fr" rel="nofollow">ManorStories</a> (6.99.14–7.1.1)
|
||||
<li> <a href="http://www.marionettecode.com/" rel="nofollow">Marionette</a> (6.99.14–7.1.1)
|
||||
<li> Kampmichi (7.1.1–7.1.2)
|
||||
<li> Kayde Initials (6.99.13–7.1.2)
|
||||
<li> <a href="http://kexboy.com" rel="nofollow">KEXBOY</a> (6.99.13–7.1.2)
|
||||
<li> Kikai Digital (7.0–7.1.2)
|
||||
<li> <a href="http://www.gamesbykinmoku.com" rel="nofollow">Kinmoku</a> (6.99.13–7.1.2)
|
||||
<li> <a href="http://krsm94.web.fc2.com/" rel="nofollow">Klast Halc (crAsm)</a> (6.99.14.2–7.1.2)
|
||||
<li> Kosmos Games (6.99.14–7.1.2)
|
||||
<li> <a href="https://de.koubaibu.tech/" rel="nofollow">Koubaibu Technology Group</a> (7.1–7.1.2)
|
||||
<li> lain105/EckoMars (6.99.13–7.1.2)
|
||||
<li> LateWhiteRabbit (6.99.14–7.1.2)
|
||||
<li> <a href="https://lernakow.itch.io" rel="nofollow">Lernakow</a> (6.99.14.3–7.1.2)
|
||||
<li> LewdKitty (7.0–7.1.2)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.lewdlab.com/" rel="nofollow">Lewdlab</a> (6.99.14.1–7.1.2)
|
||||
<li> <a href="https://lemmasoft.renai.us/forums/viewtopic.php?f=66&t=48011&p=482643" rel="nofollow">Lezalith</a> (7.1–7.1.2)
|
||||
<li> Lictor (6.99.14.2–7.1.2)
|
||||
<li> Little Napoleon (7.1–7.1.2)
|
||||
<li> <a href="http://trash.moe/" rel="nofollow">Lore</a> (6.99.13–7.1.2)
|
||||
<li> Luke Jackson (6.99.13–7.1.2)
|
||||
<li> <a href="http://luscious-spirit-studios.tumblr.com/" rel="nofollow">Luscious Spirit Studios</a> (6.99.13–7.1.2)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.patreon.com/Luxee" rel="nofollow">Luxee</a> (6.99.14.3–7.1.2)
|
||||
<li> Maeve Bandruid (6.99.13–7.1.2)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.patreon.com/manitu" rel="nofollow">MANITU Games CO.</a> (6.99.13–7.1.2)
|
||||
<li> <a href="https://manorstories.fr" rel="nofollow">ManorStories</a> (6.99.14–7.1.2)
|
||||
<li> <a href="http://www.marionettecode.com/" rel="nofollow">Marionette</a> (6.99.14–7.1.2)
|
||||
<li> MAW.3D.Art (6.99.13)
|
||||
<li> Max J Sher (6.99.13–7.1.1)
|
||||
<li> MCatter Dev (7.1–7.1.1)
|
||||
<li> <a href="https://meagantrott.com" rel="nofollow">Meagan Trott</a> (6.99.13–7.1.1)
|
||||
<li> <a href="http://metasepia.icecavern.net" rel="nofollow">Metasepia Games</a> (6.99.13–7.1.1)
|
||||
<li> <a href="http://www.meyaoi.com" rel="nofollow">Meyaoi Games</a> (6.99.13–6.99.14, 6.99.14.3–7.1.1)
|
||||
<li> Meyvol (6.99.14.1–7.1.1)
|
||||
<li> Michael Simon (7.1.1)
|
||||
<li> Michaela Laws (6.99.13–7.1.1)
|
||||
<li> Max J Sher (6.99.13–7.1.2)
|
||||
<li> MCatter Dev (7.1–7.1.2)
|
||||
<li> <a href="https://meagantrott.com" rel="nofollow">Meagan Trott</a> (6.99.13–7.1.2)
|
||||
<li> <a href="http://metasepia.icecavern.net" rel="nofollow">Metasepia Games</a> (6.99.13–7.1.2)
|
||||
<li> <a href="http://www.meyaoi.com" rel="nofollow">Meyaoi Games</a> (6.99.13–6.99.14, 6.99.14.3–7.1.2)
|
||||
<li> Meyvol (6.99.14.1–7.1.2)
|
||||
<li> Michael Simon (7.1.1–7.1.2)
|
||||
<li> Michaela Laws (6.99.13–7.1.2)
|
||||
<li> <a href="http://www.milkteestudios.com" rel="nofollow">Milktee Studios</a> (7.0–7.1)
|
||||
<li> Miss Skizzors (7.0–7.1.1)
|
||||
<li> Montse Latre (7.1.1)
|
||||
<li> <a href="https://mrvaldez.ph/" rel="nofollow">MrValdez</a> (7.0–7.1.1)
|
||||
<li> Miss Skizzors (7.0–7.1.2)
|
||||
<li> Montse Latre (7.1.1–7.1.2)
|
||||
<li> <a href="https://mrvaldez.ph/" rel="nofollow">MrValdez</a> (7.0–7.1.2)
|
||||
<li> <a href="https://ms45.itch.io" rel="nofollow">Ms .45</a> (6.99.13)
|
||||
<li> nasredin (6.99.14.3–7.1.1)
|
||||
<li> Natalie Van Sistine (7.0–7.1.1)
|
||||
<li> <a href="https://cafe.naver.com/vmo.cafe" rel="nofollow">Naver cafe VMO</a> (7.1–7.1.1)
|
||||
<li> nasredin (6.99.14.3–7.1.2)
|
||||
<li> Natalie Van Sistine (7.0–7.1.2)
|
||||
<li> <a href="https://cafe.naver.com/vmo.cafe" rel="nofollow">Naver cafe VMO</a> (7.1–7.1.2)
|
||||
<li> <a href="http://cafe.naver.com/vmo" rel="nofollow">NaverCafe VMO</a> (6.99.13–7.1)
|
||||
<li> Neigan (7.0)
|
||||
<li> Nicholas Swenson (6.99.14–7.1.1)
|
||||
<li> <a href="https://www.patreon.com/nikraria" rel="nofollow">nikraria</a> (6.99.13–7.1.1)
|
||||
<li> Nova Alamak (6.99.14.3–7.1.1)
|
||||
<li> Nicholas Swenson (6.99.14–7.1.2)
|
||||
<li> <a href="https://www.patreon.com/nikraria" rel="nofollow">nikraria</a> (6.99.13–7.1.2)
|
||||
<li> Nova Alamak (6.99.14.3–7.1.2)
|
||||
<li> <a href="http://devety.com" rel="nofollow">Oleksii olety Kyrylchuk</a> (6.99.14.1–6.99.14.2)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.patreon.com/palantogames" rel="nofollow">Palanto Games</a> (7.0–7.1.1)
|
||||
<li> Panthera Morag (6.99.13–7.1.1)
|
||||
<li> Patchwork Princess (7.1–7.1.1)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=https://www.patreon.com/palantogames" rel="nofollow">Palanto Games</a> (7.0–7.1.2)
|
||||
<li> Panthera Morag (6.99.13–7.1.2)
|
||||
<li> Patchwork Princess (7.1–7.1.2)
|
||||
<li> Patricia (6.99.13–7.1.1)
|
||||
<li> <a href="http://peachpattch.com/" rel="nofollow">peachpattch</a> (6.99.14–7.1.1)
|
||||
<li> philat (6.99.14.1–7.1.1)
|
||||
<li> plasterbrain (6.99.13–7.1.1)
|
||||
<li> <a href="http://peachpattch.com/" rel="nofollow">peachpattch</a> (6.99.14–7.1.2)
|
||||
<li> philat (6.99.14.1–7.1.2)
|
||||
<li> plasterbrain (6.99.13–7.1.2)
|
||||
<li> Ploppertje (6.99.13–6.99.14.3)
|
||||
<li> Podge (6.99.13–7.1.1)
|
||||
<li> Podge (6.99.13–7.1.2)
|
||||
<li> Puriwit Sesupaponphong (6.99.13)
|
||||
<li> Puriwit Sesupaponphong (6.99.13–7.1)
|
||||
<li> Pólyí Konrád (7.1–7.1.1)
|
||||
<li> <a href="http://www.cottoncandycyanide.com/" rel="nofollow">Quantum Suicide</a> (7.1–7.1.1)
|
||||
<li> <a href="http://razzartvisual.com/" rel="nofollow">Razz</a> (6.99.13–7.1.1)
|
||||
<li> <a href="http://www.cottoncandycyanide.com/" rel="nofollow">Quantum Suicide</a> (7.1–7.1.2)
|
||||
<li> <a href="http://razzartvisual.com/" rel="nofollow">Razz</a> (6.99.13–7.1.2)
|
||||
<li> <a href="https://twitter.com/ragnarhomsar" rel="nofollow">Realga</a> (7.0–7.1)
|
||||
<li> René Dudfield (6.99.13–7.1.1)
|
||||
<li> Richard (6.99.14–7.1.1)
|
||||
<li> <a href="http://impqueen.com/" rel="nofollow">Rinmaru</a> (6.99.13–7.1.1)
|
||||
<li> Rizia Praja (6.99.14.1–7.1.1)
|
||||
<li> René Dudfield (6.99.13–7.1.2)
|
||||
<li> Richard (6.99.14–7.1.2)
|
||||
<li> <a href="http://impqueen.com/" rel="nofollow">Rinmaru</a> (6.99.13–7.1.2)
|
||||
<li> Rizia Praja (6.99.14.1–7.1.2)
|
||||
<li> Robyn Rosenfeld (7.1)
|
||||
<li> <a href="http://sunkoiwish.com/" rel="nofollow">Royce A Xaiyeon</a> (6.99.13–7.1.1)
|
||||
<li> Ryan Balgos (6.99.14–7.1.1)
|
||||
<li> <a href="http://sunkoiwish.com/" rel="nofollow">Royce A Xaiyeon</a> (6.99.13–7.1.2)
|
||||
<li> Ryan Balgos (6.99.14–7.1.2)
|
||||
<li> Ryan Whited (6.99.14–7.1)
|
||||
<li> <a href="https://saiffyros.wordpress.com/" rel="nofollow">Saiffyros</a> (6.99.14–7.1.1)
|
||||
<li> Sam Yang (6.99.13–7.1.1)
|
||||
<li> Simply Aria (6.99.14–7.1.1)
|
||||
<li> <a href="http://sleepyagents.co.uk" rel="nofollow">Sleepy Agents</a> (6.99.13–7.1.1)
|
||||
<li> Snowlocke (7.0–7.1.1)
|
||||
<li> <a href="https://saiffyros.wordpress.com/" rel="nofollow">Saiffyros</a> (6.99.14–7.1.2)
|
||||
<li> Sam Yang (6.99.13–7.1.2)
|
||||
<li> Simply Aria (6.99.14–7.1.2)
|
||||
<li> <a href="http://sleepyagents.co.uk" rel="nofollow">Sleepy Agents</a> (6.99.13–7.1.2)
|
||||
<li> Snowlocke (7.0–7.1.2)
|
||||
<li> <a href="http://store.steampowered.com/app/570350/Sorry_Entschuldigung__A_Psychological_Horror_Visual_Novel/" rel="nofollow">Sorry. (Entschuldigung)</a> (6.99.14.2–7.1)
|
||||
<li> Spyros Panagiotopoulos (6.99.14–7.1)
|
||||
<li> Steamlynx (6.99.14.1–7.1.1)
|
||||
<li> Stefan Gagne (6.99.13–7.1.1)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=http://www.patreon.com/errilhl" rel="nofollow">Studio Errilhl</a> (6.99.14.3–7.1.1)
|
||||
<li> Taosym (6.99.13–7.1.1)
|
||||
<li> Steamlynx (6.99.14.1–7.1.2)
|
||||
<li> Stefan Gagne (6.99.13–7.1.2)
|
||||
<li> <a href="https://www.renpy.org/agegate?url=http://www.patreon.com/errilhl" rel="nofollow">Studio Errilhl</a> (6.99.14.3–7.1.2)
|
||||
<li> Taosym (6.99.13–7.1.2)
|
||||
<li> Teofilo Hurtado (6.99.14–7.1.1)
|
||||
<li> Thomas Charlie (6.99.13–7.1.1)
|
||||
<li> Timothy Landreth (6.99.13–7.1.1)
|
||||
<li> Timothy Young (6.99.14.1–7.1.1)
|
||||
<li> TJ Huckabee (6.99.13–7.1.1)
|
||||
<li> Thomas Charlie (6.99.13–7.1.2)
|
||||
<li> Timothy Landreth (6.99.13–7.1.2)
|
||||
<li> Timothy Young (6.99.14.1–7.1.2)
|
||||
<li> TJ Huckabee (6.99.13–7.1.2)
|
||||
<li> ToastCrust (6.99.13–6.99.14)
|
||||
<li> Tobias Wüthrich (6.99.13–6.99.14.3)
|
||||
<li> <a href="http://tremmigames.tk/" rel="nofollow">tremmiGames</a> (7.0–7.1.1)
|
||||
<li> trooper6 (6.99.13–7.1.1)
|
||||
<li> <a href="https://www.youtube.com/tryinmorning" rel="nofollow">tryinmorning</a> (6.99.13–7.1.1)
|
||||
<li> <a href="https://studiomugenjohncel.wordpress.com/" rel="nofollow">Uncle Mugen (Mugenjohncel</a> (6.99.14.2–7.1.1)
|
||||
<li> <a href="http://www.visualsaga.com/" rel="nofollow">Visual Saga</a> (6.99.13–7.1.1)
|
||||
<li> <a href="http://tremmigames.tk/" rel="nofollow">tremmiGames</a> (7.0–7.1.2)
|
||||
<li> trooper6 (6.99.13–7.1.2)
|
||||
<li> <a href="https://www.youtube.com/tryinmorning" rel="nofollow">tryinmorning</a> (6.99.13–7.1.2)
|
||||
<li> <a href="https://studiomugenjohncel.wordpress.com/" rel="nofollow">Uncle Mugen (Mugenjohncel</a> (6.99.14.2–7.1.2)
|
||||
<li> <a href="http://www.visualsaga.com/" rel="nofollow">Visual Saga</a> (6.99.13–7.1.2)
|
||||
<li> Vollschauer (6.99.13–6.99.14)
|
||||
<li> <a href="http://vxlloyd.com" rel="nofollow">VX Lloyd</a> (6.99.14.3–7.0)
|
||||
<li> Wayne Wollesen (6.99.14.3–7.1.1)
|
||||
<li> <a href="https://www.facebook.com/weeabooriot" rel="nofollow">Weeabooriot Cosplay</a> (6.99.13–7.1.1)
|
||||
<li> <a href="https://arcaniinteractive.com/" rel="nofollow">William Lucht</a> (7.0–7.1.1)
|
||||
<li> William Tumeo (6.99.13–7.1.1)
|
||||
<li> <a href="http://winterwolves.com/ambersmagicshop.htm" rel="nofollow">Winter Wolves</a> (6.99.13–7.1.1)
|
||||
<li> <a href="http://astralore.com/" rel="nofollow">Yakmala!</a> (6.99.13–7.1.1)
|
||||
<li> <a href="https://www.facebook.com/weeabooriot" rel="nofollow">Weeabooriot Cosplay</a> (6.99.13–7.1.2)
|
||||
<li> <a href="https://arcaniinteractive.com/" rel="nofollow">William Lucht</a> (7.0–7.1.2)
|
||||
<li> William Tumeo (6.99.13–7.1.2)
|
||||
<li> <a href="http://winterwolves.com/ambersmagicshop.htm" rel="nofollow">Winter Wolves</a> (6.99.13–7.1.2)
|
||||
<li> <a href="http://astralore.com/" rel="nofollow">Yakmala!</a> (6.99.13–7.1.2)
|
||||
</ul>
|
||||
|
||||
@@ -127,6 +127,15 @@ and rolled-back when rollback occurs.
|
||||
|
||||
Controls of if skipping is allowed.
|
||||
|
||||
.. var:: _version = ...
|
||||
|
||||
This is set to :var:`config.version` when a new game is started. It can be
|
||||
use by the ``after_load`` label or :var:`config.after_load_callbacks` to
|
||||
determine which upgrades need to be done.
|
||||
|
||||
This is only set once, upon the initial start. After that, the game is
|
||||
responsible for updating _version as necessary.
|
||||
|
||||
.. var:: _window = False
|
||||
|
||||
This set by the ``window show`` and ``window hide`` statements, and indirectly
|
||||
|
||||
@@ -380,6 +380,9 @@ The default language is chosen using the following method:
|
||||
* If :var:`config.language` is set, that language is used.
|
||||
* If the game has ever chosen a language in the past, that language is
|
||||
used.
|
||||
* If this is the first time the game has been run and
|
||||
:var:`config.enable_language_autodetect` is True, Ren'Py tries to
|
||||
autodtetect the language using :var:`config.locale_to_language_function`.
|
||||
* If this is the first time the game has been run,
|
||||
:var:`config.default_language` is used. (This defaults to the None
|
||||
language.)
|
||||
|
||||
@@ -799,10 +799,10 @@ screen preferences():
|
||||
style_prefix "radio"
|
||||
label _("Language")
|
||||
|
||||
textbutton "English" text_font "DejaVuSans.ttf"action Language(None)
|
||||
textbutton "Français" text_font "DejaVuSans.ttf"action Language("french")
|
||||
textbutton "English" text_font "DejaVuSans.ttf" action Language(None)
|
||||
textbutton "Français" text_font "DejaVuSans.ttf" action Language("french")
|
||||
textbutton "Русский" text_font "DejaVuSans.ttf" action Language("russian")
|
||||
textbutton "Bahasa Melayu" text_font "DejaVuSans.ttf"action Language("malay")
|
||||
textbutton "Bahasa Melayu" text_font "DejaVuSans.ttf" action Language("malay")
|
||||
|
||||
#end language_picker
|
||||
|
||||
@@ -974,6 +974,7 @@ screen history():
|
||||
if not _history_list:
|
||||
label _("The dialogue history is empty.")
|
||||
|
||||
define gui.history_allow_tags = set()
|
||||
|
||||
style history_window is empty
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ translate french strings:
|
||||
|
||||
# screens.rpy:782
|
||||
old "Rollback Side"
|
||||
new "Rollback"
|
||||
new "Rembobinage côté"
|
||||
|
||||
# screens.rpy:783
|
||||
#old "Disable"
|
||||
@@ -215,7 +215,7 @@ translate french strings:
|
||||
|
||||
# screens.rpy:800
|
||||
old "Language"
|
||||
new "Langage"
|
||||
new "Langue"
|
||||
|
||||
# screens.rpy:815
|
||||
old "Text Speed"
|
||||
@@ -351,7 +351,7 @@ translate french strings:
|
||||
|
||||
# screens.rpy:1111
|
||||
old "Mouse Wheel Up\nClick Rollback Side"
|
||||
new "Molette de souris vers le haut\nClic dans le sens Rollback"
|
||||
new "Molette de souris vers le haut\nClic du côté rembobinage"
|
||||
|
||||
# screens.rpy:1115
|
||||
old "Mouse Wheel Down"
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -951,6 +951,7 @@ screen history():
|
||||
if not _history_list:
|
||||
label _("The dialogue history is empty.")
|
||||
|
||||
define gui.history_allow_tags = set()
|
||||
|
||||
style history_window is empty
|
||||
|
||||
|
||||
Reference in New Issue
Block a user