Skip to content

Instantly share code, notes, and snippets.

@jeremyabel
Last active March 27, 2024 18:05
Show Gist options
  • Save jeremyabel/75c57abaa5c506aaf1f239e8babdb23b to your computer and use it in GitHub Desktop.
Save jeremyabel/75c57abaa5c506aaf1f239e8babdb23b to your computer and use it in GitHub Desktop.
Unreal Common Input Keyboard Action Icon Generator
import argparse
import csv
import pyperclip
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
supersample = 3
fontsize = 80
padding = 64
def main():
parser = argparse.ArgumentParser(description='Generate keyboard button icons from an input csv file')
parser.add_argument('FILEPATH', type=CSVPath, help='the input csv file')
parser.add_argument('-s', '--size', type=int, default=128)
args = vars(parser.parse_args())
size = (args['size'] * supersample, args['size'] * supersample)
font = ImageFont.truetype(font="Fonts/OpenSans-Bold.ttf", size=fontsize*supersample)
pasters = []
pasters.append('(Key=LeftMouseButton,KeyBrush=(ImageSize=(X=256.000000,Y=256.000000),ResourceObject="/Script/Engine.Texture2D\'/Game/UI/Platform/KeyboardMouse/Icon-Mouse-Button-L.Icon-Mouse-Button-L\'"))')
pasters.append('(Key=RightMouseButton,KeyBrush=(ImageSize=(X=256.000000,Y=256.000000),ResourceObject="/Script/Engine.Texture2D\'/Game/UI/Platform/KeyboardMouse/Icon-Mouse-Button-R.Icon-Mouse-Button-R\'"))')
with open(args['FILEPATH'], newline='', encoding='utf-8') as csvfile:
csvreader = csv.DictReader(csvfile)
for row in csvreader:
label = row['Label']
text = label if label else row['Key']
xoff = int(row['XOffset']) if row['XOffset'] else 0
yoff = int(row['YOffset']) if row['YOffset'] else 0
textbox = font.getbbox(text)
textsize = (textbox[2] - textbox[0], textbox[3] - textbox[1])
size = (max(args['size']*supersample, textsize[0] + (padding*supersample)), size[1])
textcenter = (((size[0] - textsize[0]) // 2) + (xoff*supersample), 20 + yoff*supersample)
im = Image.new('RGBA', size)
draw = ImageDraw.Draw(im)
draw.rounded_rectangle([(0, 0), size], radius=16*supersample, width=9*supersample)
draw.text(textcenter, text, fill="white", font=font)
im = im.resize((size[0] // supersample, size[1] // supersample), resample=Image.Resampling.LANCZOS)
filename = f'Icon-Keyboard-{row["Key"]}'
im.save(f"output/{filename}.png")
pasters.append(f'(Key={row["Key"]},KeyBrush=(ImageSize=(X={im.size[0]},Y={im.size[1]}),ResourceObject="/Script/Engine.Texture2D\'/Game/UI/Platform/KeyboardMouse/{filename}.{filename}\'"))')
joinedpasters = ','.join(pasters)
pyperclip.copy(f'({joinedpasters})')
def CSVPath(pathstr):
path = Path(pathstr)
if path.is_file():
if path.exists():
ext = path.suffix.lower()
if ext == '.csv':
return pathstr
else:
raise argparse.ArgumentTypeError(f"\"{pathstr}\" must be a .csv file")
else:
raise argparse.ArgumentTypeError(f"\"{pathstr}\" does not exist")
else:
raise argparse.ArgumentTypeError(f"\"{pathstr}\" is not a valid file path")
if __name__ == "__main__":
main();
Key Label Icon XOffset YOffset
BackSpace
Tab
Enter
Pause
CapsLock CapsLk -5
Escape Esc
SpaceBar
PageUp PgUp -5
PageDown PgDn -5
End
Home
Left
Up
Right
Down
Insert Ins
Delete Del
Zero 0
One 1
Two 2
Three 3
Four 4
Five 5
Six 6
Seven 7
Eight 8
Nine 9
A
B
C -2 1
D
E -1
F
G
H
I
J 6 -6
K
L
M
N
O
P
Q -1 -5
R
S
T
U
V
W
X
Y
Z
NumPadZero Num 0
NumPadOne Num 1
NumPadTwo Num 2
NumPadThree Num 3
NumPadFour Num 4
NumPadFive Num 5
NumPadSix Num 6
NumPadSeven Num 7
NumPadEight Num 8
NumPadNine Num 9
Multiply Num *
Add Num +
Subtract Num -
Decimal Num .
Divide Num /
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
NumLock NumLk
ScrollLock ScrLk
LeftShift L Shift
RightShift R Shift
LeftControl L Ctrl
RightControl R Ctrl
LeftAlt L Alt
RightAlt R Alt
LeftCommand L Cmd
RightCommand R Cmd
Semicolon ;
Equals =
Comma ,
Underscore _
Hyphen -
Period .
Slash /
Tilde ~
LeftBracket [ -3 -5
LeftParantheses ( -3 -5
Backslash \
RightBracket ] 3 -5
RightParantheses ) 3 -5
Apostrophe '
Quote "
Asterix *
Ampersand &
Caret ^
Dollar $
Exclamation !
Colon :
A_AccentGrave À 7
E_AccentGrave È -1 7
E_AccentAigu É -1 7
C_Cedille Ç -2 -6
Section § 2
pillow==10.2.0
pyperclip==1.8.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment