Skip to content

Commit

Permalink
Support multi-char dialogs
Browse files Browse the repository at this point in the history
  • Loading branch information
valrus committed Mar 29, 2016
1 parent b5ef4ca commit 9bee3a0
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 48 deletions.
41 changes: 22 additions & 19 deletions src/UndertaleApp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from flask.ext.compress import Compress
from PIL import Image, ImageDraw, ImageFont

from personalities import apply_personality
from personalities import apply_personality, PersonalityOverrideException


from imgurpython import ImgurClient
Expand Down Expand Up @@ -63,7 +63,7 @@ def _indent(line_num, line):
return '* ' + line


def getFontForCharacter(character):
def get_font_for_character(character):
font_dir = os.path.join(app.root_path, 'static', 'css', 'fonts')
if character.lower() == 'sans':
return ImageFont.load(os.path.join(font_dir, 'a skele-ton.pil'))
Expand All @@ -83,54 +83,57 @@ def chunks(lst, length, max_chunks=3):
left -= 1


def dialogBox(portraits, text, fnt, doIndent=True):
def get_character_from_portrait(src):
return os.path.basename(os.path.dirname(src)).lower()


def dialogBox(portraits, text):
textChunks = list(chunks(text.split('\n'), 3))
orig_size = Size(298, 4 + 84 * len(textChunks))
# mode = '1' is black and white
img = Image.new(b'1', orig_size)
draw = ImageDraw.Draw(img)
draw.fontmode = b'1'
for boxNum, (portrait_src, textChunk) in enumerate(zip(portraits, textChunks)):
for boxNum, (portrait_src, text_chunk) in enumerate(zip(portraits, textChunks)):
character = get_character_from_portrait(portrait_src)
apply_personality(' '.join(text_chunk), character)
box_text = [_clean_text(line, character) for line in text_chunk]
fnt = get_font_for_character(character)
y_offset = 84 * boxNum
draw.rectangle((4, 4 + y_offset, 294, 80 + y_offset), fill=1)
draw.rectangle((7, 7 + y_offset, 291, 77 + y_offset), fill=0)
img.paste(Image.open(portrait_src.lstrip('/')), (13, 12 + y_offset))
for row, line in enumerate(textChunk[:3]):
for row, line in enumerate(box_text[:3]):
if app.debug:
print('"{}"'.format(repr(line)), draw.textsize(line, font=fnt))
draw.text((77, y_offset + 16 + row * 18),
_indent(row, line) if doIndent else line,
_indent(row, line) if character != 'papyrus' else line,
fill=1, font=fnt)
return img.resize(Size(orig_size.x * 2, orig_size.y * 2))


@app.route('/submit', methods=['GET'])
def makeDialogBox():
character = request.args.get('character').lower()
text = _clean_text(request.args.get('text'), character)
imgData = apply_personality(text, character)
if imgData is None:
text = request.args.get('text')
try:
mood_imgs = request.args.getlist('moodImg')
if app.debug:
print(mood_imgs)
box = dialogBox(
mood_imgs,
text,
getFontForCharacter(character),
doIndent=(character != 'papyrus')
)
box = dialogBox(mood_imgs, text)
stream = StringIO()
box.save(stream, format='png', optimize=True)
imgData = b64encode(stream.getvalue())
img_data = b64encode(stream.getvalue())

@after_this_request
def cleanup(response):
stream.close()
return response
except PersonalityOverrideException as override_response:
img_data = override_response.img_data

if app.debug:
print(imgData)
return imgData
print(img_data)
return img_data


@app.route('/imgur_id', methods=['GET'])
Expand Down
14 changes: 9 additions & 5 deletions src/personalities.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,25 @@
MAX_TEXT = 210


class PersonalityOverrideException(Exception):
def __init__(self, img_data):
self.img_data = img_data


def apply_personality(text, character):
char = CHARACTERS[character.lower()]
try:
text.encode(char.encoding)
except UnicodeEncodeError:
return char.no_language()
raise PersonalityOverrideException(char.no_language())
else:
lowertext = text.lower()
if any(word in lowertext for word in NAUGHTY_WORDS):
return char.naughty_word()
raise PersonalityOverrideException(char.naughty_word())
elif lowertext.startswith(COPYPASTA_START):
return char.copypasta()
raise PersonalityOverrideException(char.copypasta())
elif len(text) > MAX_TEXT:
return char.too_long()
return None
raise PersonalityOverrideException(char.too_long())


class Character(object):
Expand Down
45 changes: 21 additions & 24 deletions src/static/js/UndertaleDialog.elm
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ titleImgMap root address =
]
[ mapArea [ 606, 43, 626, 61 ] "hOI!"
<| Either.Right
<| ( address, ChooseMood Character.Temmie (defaultSprite root Character.Temmie) )
<| ( address
, UpdateDialogs
<| DialogBoxes.SetImages Character.Temmie
<| defaultSprite root Character.Temmie
)
]


Expand Down Expand Up @@ -164,7 +168,10 @@ characterButton address staticRoot c =

_ ->
button
[ onClick address <| ChooseMood c (defaultSprite staticRoot c)
[ onClick address
<| UpdateDialogs
<| DialogBoxes.SetImages c
<| defaultSprite staticRoot c
, style flatButton
]
[ img [ src <| defaultSprite staticRoot c ] [] ]
Expand All @@ -190,7 +197,9 @@ moodButton address root c n =
spriteStr = spriteNumber root c n
in
button
[ onClick address <| ChooseMood c spriteStr
[ onClick address
<| UpdateDialogs
<| DialogBoxes.SetImages c spriteStr
, style flatButton
]
[ img [ src <| spriteStr ] [] ]
Expand Down Expand Up @@ -409,7 +418,6 @@ type Action
= NoOp ()
| EnterCheatCode (Set.Set Char)
| ActivateEXMode
| ChooseMood Character.Name String
| UpdateDialogs DialogBoxes.Action
| SetScriptRoot String
| SetStaticRoot String
Expand Down Expand Up @@ -444,28 +452,19 @@ update action model =
, none
)

ChooseMood c s ->
let
( newBoxes, moveCursor ) = DialogBoxes.update (DialogBoxes.SetImages c s) model.dialogs
in
( { model
| selection = Just c
, dialogs = newBoxes
, imageData = Nothing
}
, toFocusEffect
model.focusMailbox.address
{ elementId = textBoxId 1
, moveCursorToEnd = moveCursor
}
)

UpdateDialogs action ->
let
( newBoxes, moveCursor ) = DialogBoxes.update action model.dialogs
in
( { model
| dialogs = newBoxes
| selection =
case action of
DialogBoxes.SetImages c s ->
Just c

_ ->
model.selection
, dialogs = newBoxes
, imageData = Nothing
}
, toFocusEffect
Expand Down Expand Up @@ -541,9 +540,7 @@ getDialogBoxImg model =
Just c ->
Http.url
(getSubmitUrl model.scriptRoot)
([ ( "character", toString c )
, ( "text", DialogBoxes.concat model.dialogs )
]
([ ( "text", DialogBoxes.concat model.dialogs ) ]
++ (List.map ((,) "moodImg") <| DialogBoxes.getImgSrcs model.dialogs)
)
|> Http.getString
Expand Down

0 comments on commit 9bee3a0

Please sign in to comment.