diff options
author | Jesusaves <cpntb1@ymail.com> | 2020-05-15 04:55:56 -0300 |
---|---|---|
committer | Jesusaves <cpntb1@ymail.com> | 2020-05-15 04:55:56 -0300 |
commit | aa120b650afc2fa9ccabdbf32d79fcbea76d4996 (patch) | |
tree | aa5c0c927b48a4d4e7d28ed8796825dac8f2eedd | |
parent | 29a9f39efd9edad19cf44482a3dc2be7acd6046a (diff) | |
download | tools-aa120b650afc2fa9ccabdbf32d79fcbea76d4996.tar.gz tools-aa120b650afc2fa9ccabdbf32d79fcbea76d4996.tar.bz2 tools-aa120b650afc2fa9ccabdbf32d79fcbea76d4996.tar.xz tools-aa120b650afc2fa9ccabdbf32d79fcbea76d4996.zip |
Twine Mouboo Tool.
It converts simple twine stories into game code.
Only plain text, one-line C comments and basic navigation are supported.
(DO NOT use pipe navigation)
-rwxr-xr-x | misc/twine.py | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/misc/twine.py b/misc/twine.py new file mode 100755 index 0000000..4949ec8 --- /dev/null +++ b/misc/twine.py @@ -0,0 +1,167 @@ +#!/usr/bin/python2 + +import sys +from HTMLParser import HTMLParser + +''' twine2rpy is for storyboarding/testing Ren'py scripts in Twine and converting +the Twine source file to .rpy. + +This example was made for use with Twine 2, which exports directly to HTML. +It only supports simple narrator speech and flow control: Variables, conditionals, +images, and even markup are not supported. + +It should not be hard to extend this script (unless you're using HTML inside the +dialog blocks). THIS FILE IS PROVIDED AS-IS, WITHOUT WARRANTIES OF ANY KIND, +EXPRESS OR IMPLIED, EXCEPT WHERE OTHERWISE REQUIRED BY LAW. + +PS. This script version is not meant for production use. +From the command line: twine2rpy_2.py source.txt ''' + + +####################################################################### +# Open Twine source file + +# This function will (in an expensive manner) find the tuples we want +# on HTML argument list. +def dl_getkey(array, key): + for k in array: + if k[0] == key: + return k[1] + +# Receive arguments from commandline +try: + file_name = sys.argv[1] +except IndexError: + print("Usage: ./converter.py <twineproject.html>") + print("") + print("Made with Harlowe2 syntax. Use other syntaxes at your own risk!") + exit(0) + +# Receives a HTML file +open_file = open(file_name) +txt_file = open_file.read() +txt_file = txt_file.replace(""", "\"").replace("'", "\'") + +# Prepare the Ren'Py file +renpy_file = "t2_" + file_name[:file_name.find(".")].rstrip() + ".txt" +rpy_file = open(renpy_file, "w") + +# Global dictionaries +# TLT : Top Level Tag (what we're examining right now). +TLT="html" +LABELS={} +INMENU=False +PARSE=False +BREAK=False + +# Parse data +# The "data" is received as-is; As long that it doesn't uses HTML, +# It should not break. +def parse(basedata): + global TLT, LABELS, INMENU, BREAK + data=basedata.split("\n") + + # Convert stuff + for d in data: + # regexes (or anything which would break this) + d=d.replace("\"", "\\\"") + d=d.strip() + + # Exceptions: Do not add empty dialog boxes + if d == "": + if BREAK: + rpy_file.write(" next;\n") + #rpy_file.write(" mesn;\n") + BREAK=False + rpy_file.write("\n") + continue + + # Handle comments + if (d.startswith("//")): + rpy_file.write(" %s\n" % d) + continue + + # Here is an example of how simple menus could be handed: + if (d.startswith("[[") and not INMENU): + d=d.replace("[[", "").replace("]]", "") + INMENU=True + rpy_file.write(" menu\n") + target=LABELS[d] + rpy_file.write(" l(\"%s\"), L_%s" % (d, target)) + elif (d.startswith("[[") and INMENU): + d=d.replace("[[", "").replace("]]", "") + target=LABELS[d] + rpy_file.write(",\n l(\"%s\"), L_%s" % (d, target)) + elif INMENU: + INMENU=False + rpy_file.write(";\n") + + else: + # Save it as a narrator speech block; + # It will ignore other markdown and comments, too, but thankfully, + # it is not very difficult to add regexes and replaces for them. + rpy_file.write(" mesq l(\"%s\");\n" % d) + BREAK=True + + +# HTML Magic +# create a subclass and override the default handler methods +class MyHTMLParser(HTMLParser): + def handle_starttag(self, tag, attrs): + global TLT, LABELS, PARSE + # Set on TLT variable what tag we're in + # FIXME: You probably don't want to redefine TLT after + # it has been set to tw-passagedata; Instead, you'll want + # handle_endtag() to unset this. This is necessary if you plan + # in converting scripts with HTML code inside the passages. + TLT=tag + + # A new passage! Lets get its name and pid. + if tag == "tw-passagedata": + labelname=dl_getkey(attrs, "name") + labelid=dl_getkey(attrs, "pid") + # Not writing file, lets register the label on the dict + if not PARSE: + LABELS[labelname]=labelid + print("Register label: %s" % labelname) + # If we're writing the file, then give it a safe label name + else: + rpy_file.write("L_%s:\n" % labelid) + + def handle_endtag(self, tag): + global PARSE, INMENU + # Ops, seems like we finished the passage! + # To prevent implicit fallthroughs, lets call return + if tag == "tw-passagedata" and PARSE: + if not INMENU: + rpy_file.write(" close;\n\n") + else: + INMENU=False + rpy_file.write(";\n") + rpy_file.write(" close;\n\n") + + def handle_data(self, data): + global TLT, PARSE + if (TLT in ["script", "style"] or not PARSE): + # Silently ignore Twine stuff + pass + else: + # We're writing and we're inside a passage, so call parse() on it + if (TLT == "tw-passagedata"): + parse(data) + +# Do a dry run. +# This is needed to prepare LABELS dictionary +parser = MyHTMLParser() +parser.feed(txt_file) + +# Prepare the file +PARSE=True +parser.feed(txt_file) + +# Close files we opened +open_file.close() +rpy_file.close() + +# Report our success +print("Success!") |