Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
UncertainProd
GitHub Repository: UncertainProd/FnF-Spritesheet-and-XML-Maker
Path: blob/master/src/xmlpngUI.py
254 views
1
import sys
2
from PyQt5.QtCore import QSize, Qt
3
from PyQt5.QtGui import QIcon, QPixmap
4
from PyQt5.QtWidgets import QAction, QActionGroup, QApplication, QGridLayout, QInputDialog, QLineEdit, QMainWindow, QMessageBox, QProgressDialog, QPushButton, QSpacerItem, QLabel, QFileDialog
5
from os import path
6
from animationwindow import AnimationView
7
import engine.icongridutils as icongridutils
8
import engine.spritesheetutils as spritesheetutils
9
# from frameorderscreen import FrameOrderScreen
10
from xmltablewindow import XMLTableView
11
import json
12
13
import engine.xmlpngengine as xmlpngengine
14
from mainUI import Ui_MainWindow
15
from spriteframe import SpriteFrame
16
from utils import SPRITEFRAME_SIZE, get_stylesheet_from_file
17
from settingswindow import SettingsWindow
18
19
20
def display_progress_bar(parent, title="Sample text", startlim=0, endlim=100):
21
def update_prog_bar(progress, progresstext):
22
progbar.setValue(progress)
23
progbar.setLabel(QLabel(progresstext))
24
progbar = QProgressDialog(title, None, startlim, endlim, parent)
25
progbar.setWindowModality(Qt.WindowModal)
26
progbar.show()
27
28
return update_prog_bar, progbar
29
30
def set_preferences(prefdict):
31
try:
32
with open('preferences.json', 'w') as f:
33
json.dump(prefdict, f)
34
except Exception as e:
35
with open("error.log", 'a') as errlog:
36
errlog.write(str(e))
37
38
class MyApp(QMainWindow):
39
def __init__(self, prefs):
40
super().__init__()
41
42
self.ui = Ui_MainWindow()
43
self.ui.setupUi(self)
44
self.setWindowTitle("XML Generator")
45
46
self.ui.generatexml_btn.clicked.connect(self.generate_xml)
47
self.ui.actionExport_as_Spritesheet_and_XML.triggered.connect(self.generate_xml)
48
self.ui.actionExport_induvidual_images.triggered.connect(self.export_bunch_of_imgs)
49
self.ui.frames_area.setWidgetResizable(True)
50
self.frames_layout = QGridLayout(self.ui.sprite_frame_content)
51
self.ui.frames_area.setWidget(self.ui.sprite_frame_content)
52
53
self.num_labels = 0
54
self.labels = []
55
self.selected_labels = []
56
# self.frame_dict = {} # dict< pose_name: str -> frames: list[SpriteFrame] >
57
58
self.add_img_button = QPushButton()
59
self.add_img_button.setIcon(QIcon("./assets/AddImg.png"))
60
self.add_img_button.setGeometry(0, 0, SPRITEFRAME_SIZE, SPRITEFRAME_SIZE)
61
self.add_img_button.setFixedSize(QSize(SPRITEFRAME_SIZE, SPRITEFRAME_SIZE))
62
self.add_img_button.setIconSize(QSize(SPRITEFRAME_SIZE, SPRITEFRAME_SIZE))
63
self.add_img_button.clicked.connect(self.open_frame_imgs)
64
65
self.frames_layout.addWidget(self.add_img_button, 0, 0, Qt.AlignmentFlag(0x1|0x20))
66
self.ui.myTabs.setCurrentIndex(0)
67
68
self.setWindowIcon(QIcon("./assets/appicon.png"))
69
self.icongrid_zoom = 1
70
self.ui.uploadicongrid_btn.clicked.connect(self.uploadIconGrid)
71
self.ui.actionImport_IconGrid.triggered.connect(self.uploadIconGrid)
72
self.ui.generateicongrid_btn.clicked.connect(self.getNewIconGrid)
73
self.ui.uploadicons_btn.clicked.connect(self.appendIcon)
74
self.ui.actionImport_Icons.triggered.connect(self.appendIcon)
75
self.ui.actionClear_IconGrid.triggered.connect(self.clearIconGrid)
76
self.ui.actionClear_Icon_selection.triggered.connect(self.clearSelectedIcons)
77
78
self.action_zoom_in = QAction(self.ui.icongrid_holder_label)
79
self.ui.icongrid_holder_label.addAction(self.action_zoom_in)
80
self.action_zoom_in.triggered.connect(self.zoomInPixmap)
81
self.action_zoom_in.setShortcut("Ctrl+i")
82
83
self.action_zoom_out = QAction(self.ui.icongrid_holder_label)
84
self.ui.icongrid_holder_label.addAction(self.action_zoom_out)
85
self.action_zoom_out.triggered.connect(self.zoomOutPixmap)
86
self.action_zoom_out.setShortcut("Ctrl+o")
87
88
self.ui.zoom_label.setText("Zoom: 100%")
89
90
self.iconpaths = []
91
self.icongrid_path = ""
92
93
self.ui.posename_btn.clicked.connect(self.setAnimationNames)
94
self.ui.posename_btn.setDisabled(True)
95
self.ui.charname_textbox.textChanged.connect(self.onCharacterNameChange)
96
97
self.num_cols = 6
98
self.num_rows = 1
99
100
self.ui.actionImport_Images.triggered.connect(self.open_frame_imgs)
101
self.ui.action_import_existing.triggered.connect(self.open_existing_spsh_xml)
102
self.ui.actionImport_from_GIF.triggered.connect(self.open_gif)
103
104
self.num_rows = 1 + self.num_labels//self.num_cols
105
106
for i in range(self.num_cols):
107
self.frames_layout.setColumnMinimumWidth(i, 0)
108
self.frames_layout.setColumnStretch(i, 0)
109
for i in range(self.num_rows):
110
self.frames_layout.setRowMinimumHeight(i, 0)
111
self.frames_layout.setRowStretch(i, 0)
112
113
vspcr = QSpacerItem(1, 1)
114
self.frames_layout.addItem(vspcr, self.num_rows, 0, 1, 4)
115
116
hspcr = QSpacerItem(1, 1)
117
self.frames_layout.addItem(hspcr, 0, self.num_cols, self.num_rows, 1)
118
119
self.ui.actionClear_Spritesheet_Grid.triggered.connect(self.clear_spriteframe_grid)
120
self.ui.myTabs.currentChanged.connect(self.handle_tab_change)
121
self.ui.spsh_settings_btn.clicked.connect(self.show_settings)
122
123
self.settings_widget = SettingsWindow()
124
125
self.anim_view_window = AnimationView()
126
self.ui.actionPreview_Animation.triggered.connect(self.show_anim_preview)
127
self.ui.actionPreview_Animation.setEnabled(len(self.labels) > 0)
128
# adding a QActionGroup at runtime :/
129
darkmode_action_group = QActionGroup(self.ui.menuDefault_Dark_mode)
130
theme_opts = ["Default", "Dark Mode"]
131
checked_action = "Default" if prefs.get("theme", 'default') != 'dark' else "Dark Mode"
132
for opt in theme_opts:
133
action = QAction(opt, self.ui.menuDefault_Dark_mode, checkable=True, checked=(opt == checked_action))
134
self.ui.menuDefault_Dark_mode.addAction(action)
135
darkmode_action_group.addAction(action)
136
darkmode_action_group.setExclusive(True)
137
darkmode_action_group.triggered.connect(self.set_dark_mode)
138
139
self.xml_table = XMLTableView(['Image Path', 'Name', 'Width', 'Height', 'FrameX', 'FrameY', 'FrameWidth', 'FrameHeight'])
140
self.ui.actionView_XML_structure.triggered.connect(self.show_table_view)
141
self.ui.actionView_XML_structure.setEnabled(len(self.labels) > 0)
142
self.ui.actionFlipX.triggered.connect(lambda: self.flip_labels('X'))
143
self.ui.actionFlipY.triggered.connect(lambda: self.flip_labels('Y'))
144
145
self.ui.use_psychengine_checkbox.clicked.connect(self.handle_psychengine_checkbox)
146
147
# self.frame_order_screen = FrameOrderScreen()
148
# self.ui.actionChange_Frame_Ordering.triggered.connect(self.show_frame_order_screen)
149
# self.ui.actionChange_Frame_Ordering.setEnabled(len(self.labels) > 0)
150
151
# Note: Add any extra windows before this if your want the themes to apply to them
152
if prefs.get("theme", 'default') == 'dark':
153
self.set_theme(get_stylesheet_from_file("assets/app-styles.qss"))
154
155
156
def ranged_selection_handler(self, selected_spriteframe):
157
first_selected_spriteframe = None
158
for sprf in self.labels:
159
if sprf == selected_spriteframe:
160
break
161
162
if sprf.select_checkbox.checkState() != 0 and sprf != selected_spriteframe:
163
first_selected_spriteframe = sprf
164
break
165
166
if first_selected_spriteframe is not None:
167
start_selecting = False
168
for sprf in self.labels:
169
if sprf == first_selected_spriteframe:
170
start_selecting = True
171
172
if start_selecting:
173
# checks the box and adds it to the selected list
174
sprf.select_checkbox.setChecked(1)
175
176
if sprf == selected_spriteframe:
177
break
178
179
def ranged_deletion_handler(self, selected_spriteframe):
180
first_selected_spriteframe = None
181
for sprf in self.labels:
182
if sprf == selected_spriteframe:
183
break
184
185
if sprf.select_checkbox.checkState() != 0 and sprf != selected_spriteframe:
186
first_selected_spriteframe = sprf
187
break
188
189
if first_selected_spriteframe is not None:
190
start_selecting = False
191
for sprf in self.labels:
192
if sprf == first_selected_spriteframe:
193
start_selecting = True
194
195
if start_selecting:
196
# unchecks the box and removes it from the selected list
197
sprf.select_checkbox.setChecked(0)
198
199
if sprf == selected_spriteframe:
200
break
201
202
203
def open_gif(self):
204
gifpath = self.get_asset_path("Select the GIF file", "GIF images (*.gif)")
205
if gifpath != '':
206
update_prog_bar, progbar = display_progress_bar(self, "Extracting sprite frames....")
207
QApplication.processEvents()
208
209
sprites = spritesheetutils.get_gif_frames(gifpath, update_prog_bar)
210
for i, spfr in enumerate(sprites):
211
spfr.frameparent = self
212
self.add_spriteframe(spfr)
213
update_prog_bar(50 + ((i+1)*50//len(sprites)), f"Adding frames from: {gifpath}")
214
progbar.close()
215
216
self.ui.posename_btn.setDisabled(self.num_labels <= 0)
217
218
def handle_psychengine_checkbox(self, checked):
219
self.ui.uploadicongrid_btn.setEnabled(not checked)
220
221
# def show_frame_order_screen(self):
222
# self.frame_order_screen.set_frame_dict(self.frame_dict)
223
# self.frame_order_screen.show()
224
225
def flip_labels(self, dxn='X'):
226
for lab in self.selected_labels:
227
lab.flip_img(dxn)
228
229
for lab in list(self.selected_labels):
230
# this automatically removes it from self.selected_labels
231
lab.select_checkbox.setChecked(False)
232
233
def show_table_view(self):
234
print("Showing table view...")
235
self.xml_table.fill_data(self.labels)
236
self.xml_table.show()
237
238
def set_dark_mode(self, event):
239
if event.text() == "Dark Mode":
240
styles = get_stylesheet_from_file("./assets/app-styles.qss")
241
self.set_theme(styles)
242
else:
243
self.set_theme("")
244
245
def set_theme(self, stylestr):
246
self.setStyleSheet(stylestr)
247
self.settings_widget.setStyleSheet(stylestr)
248
self.anim_view_window.setStyleSheet(stylestr)
249
self.xml_table.setStyleSheet(stylestr)
250
# self.frame_order_screen.setStyleSheet(stylestr)
251
if stylestr == "":
252
set_preferences({ "theme":"default" })
253
else:
254
set_preferences({ "theme":"dark" })
255
256
def show_anim_preview(self):
257
self.anim_view_window.parse_and_load_frames(self.labels)
258
self.anim_view_window.show()
259
260
def show_settings(self):
261
self.settings_widget.show()
262
263
def handle_tab_change(self, newtabind):
264
self.ui.actionClear_Spritesheet_Grid.setDisabled(newtabind != 0)
265
self.ui.action_import_existing.setDisabled(newtabind != 0)
266
self.ui.actionImport_from_GIF.setDisabled(newtabind != 0)
267
self.ui.actionImport_Images.setDisabled(newtabind != 0)
268
self.ui.actionEdit_Frame_Properties.setDisabled(newtabind != 0 or len(self.selected_labels) <= 0)
269
self.ui.menuExport.setDisabled(newtabind != 0)
270
self.ui.menuEdit_Selected_Images.setDisabled(newtabind != 0)
271
272
self.ui.actionImport_IconGrid.setDisabled(newtabind != 1)
273
self.ui.actionImport_Icons.setDisabled(newtabind != 1)
274
self.ui.actionClear_IconGrid.setDisabled(newtabind != 1)
275
self.ui.actionClear_Icon_selection.setDisabled(newtabind != 1)
276
277
def onCharacterNameChange(self):
278
for label in self.labels:
279
label.img_label.setToolTip(label.get_tooltip_string(self))
280
281
def clear_spriteframe_grid(self):
282
labs = list(self.labels)
283
for lab in labs:
284
lab.remove_self(self)
285
self.ui.actionEdit_Frame_Properties.setDisabled(len(self.selected_labels) <= 0)
286
287
def resizeEvent(self, a0):
288
w = self.width()
289
# print("Current width", w)
290
if w < 1228:
291
self.num_cols = 6
292
elif 1228 <= w <= 1652:
293
self.num_cols = 8
294
else:
295
self.num_cols = 12
296
self.re_render_grid()
297
return super().resizeEvent(a0)
298
299
def open_existing_spsh_xml(self):
300
imgpath = self.get_asset_path("Select Spritesheet File", "PNG Images (*.png)")
301
302
if imgpath != '':
303
xmlpath = self.get_asset_path("Select XML File", "XML Files (*.xml)")
304
if xmlpath != '':
305
trubasenamefn = lambda fpath: path.basename(fpath).split('.')[0]
306
charname = trubasenamefn(xmlpath)
307
if trubasenamefn(imgpath) != trubasenamefn(xmlpath):
308
self.msgbox = QMessageBox(self)
309
self.msgbox.setWindowTitle("Conflicting file names")
310
self.msgbox.setText("The Spritesheet and the XML file have different file names.\nThe character name will not be auto-filled")
311
self.msgbox.setIcon(QMessageBox.Warning)
312
self.msgbox.addButton("OK", QMessageBox.YesRole)
313
cancel_import = self.msgbox.addButton("Cancel import", QMessageBox.NoRole)
314
x = self.msgbox.exec_()
315
clickedbtn = self.msgbox.clickedButton()
316
if clickedbtn == cancel_import:
317
return
318
charname = self.ui.charname_textbox.text() # trubasenamefn(imgpath) if clickedbtn == usespsh else trubasenamefn(xmlpath)
319
print("[DEBUG] Exit status of msgbox: "+str(x))
320
321
322
update_prog_bar, progbar = display_progress_bar(self, "Extracting sprite frames....")
323
QApplication.processEvents()
324
325
sprites = spritesheetutils.split_spsh(imgpath, xmlpath, update_prog_bar)
326
for i, spfr in enumerate(sprites):
327
spfr.frameparent = self
328
self.add_spriteframe(spfr)
329
update_prog_bar(50 + ((i+1)*50//len(sprites)), f"Adding: {imgpath}")
330
progbar.close()
331
332
self.ui.posename_btn.setDisabled(self.num_labels <= 0)
333
334
self.ui.charname_textbox.setText(charname)
335
336
337
338
def open_frame_imgs(self):
339
imgpaths = self.get_asset_path("Select sprite frames", "PNG Images (*.png)", True)
340
341
if imgpaths:
342
update_prog_bar, progbar = display_progress_bar(self, "Importing sprite frames....", 0, len(imgpaths))
343
QApplication.processEvents()
344
345
for i, pth in enumerate(imgpaths):
346
# self.add_img(pth)
347
self.add_spriteframe(SpriteFrame(self, pth))
348
update_prog_bar(i+1, f"Adding: {pth}")
349
progbar.close()
350
351
if len(self.labels) > 0:
352
self.ui.posename_btn.setDisabled(False)
353
354
def add_spriteframe(self, sp):
355
self.num_rows = 1 + self.num_labels//self.num_cols
356
357
self.frames_layout.setRowMinimumHeight(self.num_rows - 1, 0)
358
self.frames_layout.setRowStretch(self.num_rows - 1, 0)
359
360
vspcr = QSpacerItem(1, 1)
361
self.frames_layout.addItem(vspcr, self.num_rows, 0, 1, 4)
362
363
hspcr = QSpacerItem(1, 1)
364
self.frames_layout.addItem(hspcr, 0, self.num_cols, self.num_rows, 1)
365
366
self.labels.append(sp)
367
self.frames_layout.removeWidget(self.add_img_button)
368
self.frames_layout.addWidget(self.labels[-1], self.num_labels // self.num_cols, self.num_labels % self.num_cols, Qt.AlignmentFlag(0x1|0x20))
369
self.num_labels += 1
370
self.frames_layout.addWidget(self.add_img_button, self.num_labels // self.num_cols, self.num_labels % self.num_cols, Qt.AlignmentFlag(0x1|0x20))
371
self.ui.actionPreview_Animation.setEnabled(len(self.labels) > 0)
372
self.ui.actionView_XML_structure.setEnabled(len(self.labels) > 0)
373
# self.ui.actionChange_Frame_Ordering.setEnabled(len(self.labels) > 0)
374
375
# self.update_frame_dict(sp.img_xml_data.pose_name, sp)
376
377
def update_frame_dict(self, key, val, remove=False):
378
# TODO
379
return
380
381
def re_render_grid(self):
382
self.num_rows = 1 + self.num_labels//self.num_cols
383
for i in range(self.num_cols):
384
self.frames_layout.setColumnMinimumWidth(i, 0)
385
self.frames_layout.setColumnStretch(i, 0)
386
for i in range(self.num_rows):
387
self.frames_layout.setRowMinimumHeight(i, 0)
388
self.frames_layout.setRowStretch(i, 0)
389
390
vspcr = QSpacerItem(1, 1)
391
self.frames_layout.addItem(vspcr, self.num_rows, 0, 1, 4)
392
393
hspcr = QSpacerItem(1, 1)
394
self.frames_layout.addItem(hspcr, 0, self.num_cols, self.num_rows, 1)
395
396
for i, sp in enumerate(self.labels):
397
self.frames_layout.addWidget(sp, i//self.num_cols, i%self.num_cols, Qt.AlignmentFlag(0x1|0x20))
398
self.frames_layout.removeWidget(self.add_img_button)
399
self.frames_layout.addWidget(self.add_img_button, self.num_labels // self.num_cols, self.num_labels % self.num_cols, Qt.AlignmentFlag(0x1|0x20))
400
401
def export_bunch_of_imgs(self):
402
savedir = QFileDialog.getExistingDirectory(caption="Save image sequence to...")
403
updatefn, progbar = display_progress_bar(self, "Exporting Image Sequence", startlim=0, endlim=len(self.labels))
404
QApplication.processEvents()
405
406
errmsg = xmlpngengine.save_img_sequence(self.labels, savedir, updatefn)
407
progbar.close()
408
if errmsg:
409
self.display_msg_box("Error!", text=f"An error occured: {errmsg}", icon=QMessageBox.Critical)
410
else:
411
self.display_msg_box("Success!", text="Image sequence saved successfully!", icon=QMessageBox.Information)
412
413
def generate_xml(self):
414
charname = self.ui.charname_textbox.text()
415
charname = charname.strip()
416
if self.num_labels > 0 and charname != '':
417
savedir = QFileDialog.getExistingDirectory(caption="Save files to...")
418
print("Stuff saved to: ", savedir)
419
if savedir != '':
420
update_prog_bar, progbar = display_progress_bar(self, "Generating....", 0, len(self.labels))
421
QApplication.processEvents()
422
423
statuscode, errmsg = xmlpngengine.make_png_xml(
424
self.labels,
425
savedir,
426
charname,
427
update_prog_bar
428
)
429
progbar.close()
430
if errmsg is None:
431
self.display_msg_box(
432
window_title="Done!",
433
text="Your files have been generated!\nCheck the folder you had selected",
434
icon=QMessageBox.Information
435
)
436
else:
437
self.display_msg_box(
438
window_title="Error!",
439
text=("Some error occured! Error message: " + errmsg),
440
icon=QMessageBox.Critical
441
)
442
else:
443
errtxt = "Please enter some frames" if self.num_labels <= 0 else "Please enter the name of your character"
444
self.display_msg_box(
445
window_title="Error!",
446
text=errtxt,
447
icon=QMessageBox.Critical
448
)
449
450
def zoomInPixmap(self):
451
if self.icongrid_path and self.icongrid_zoom <= 5:
452
self.icongrid_zoom *= 1.1
453
icongrid_pixmap = QPixmap(self.icongrid_path)
454
w = icongrid_pixmap.width()
455
h = icongrid_pixmap.height()
456
icongrid_pixmap = icongrid_pixmap.scaled(int(w*self.icongrid_zoom), int(h*self.icongrid_zoom), 1)
457
self.ui.icongrid_holder_label.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
458
self.ui.scrollAreaWidgetContents_2.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
459
self.ui.icongrid_holder_label.setPixmap(icongrid_pixmap)
460
self.ui.zoom_label.setText("Zoom: %.2f %%" % (self.icongrid_zoom*100))
461
462
463
def zoomOutPixmap(self):
464
if self.icongrid_path and self.icongrid_zoom >= 0.125:
465
self.icongrid_zoom /= 1.1
466
icongrid_pixmap = QPixmap(self.icongrid_path)
467
w = icongrid_pixmap.width()
468
h = icongrid_pixmap.height()
469
icongrid_pixmap = icongrid_pixmap.scaled(int(w*self.icongrid_zoom), int(h*self.icongrid_zoom), 1)
470
self.ui.icongrid_holder_label.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
471
self.ui.scrollAreaWidgetContents_2.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
472
self.ui.icongrid_holder_label.setPixmap(icongrid_pixmap)
473
self.ui.zoom_label.setText("Zoom: %.2f %%" % (self.icongrid_zoom*100))
474
475
def uploadIconGrid(self):
476
print("Uploading icongrid...")
477
self.icongrid_path = self.get_asset_path("Select the Icon-grid", "PNG Images (*.png)")
478
icongrid_pixmap = QPixmap(self.icongrid_path)
479
self.ui.icongrid_holder_label.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
480
self.ui.scrollAreaWidgetContents_2.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
481
self.ui.icongrid_holder_label.setPixmap(icongrid_pixmap)
482
483
def clearIconGrid(self):
484
self.icongrid_path = ""
485
self.ui.icongrid_holder_label.clear()
486
487
def getNewIconGrid(self):
488
if self.ui.use_psychengine_checkbox.isChecked():
489
if len(self.iconpaths) > 0:
490
print("Using psych engine style icon grid generation....")
491
savepath, _ = QFileDialog.getSaveFileName(self, "Save as filename", filter="PNG files (*.png)")
492
493
stat, problemimg, exception_msg = icongridutils.makePsychEngineIconGrid(self.iconpaths, savepath)
494
495
if exception_msg is not None:
496
self.display_msg_box(
497
window_title="Error!",
498
text=f"An error occured: {exception_msg}",
499
icon=QMessageBox.Critical
500
)
501
else:
502
if stat == 0:
503
self.display_msg_box(
504
window_title="Done!",
505
text="Your icon-grid has been generated!",
506
icon=QMessageBox.Information
507
)
508
# display final image onto the icon display area
509
icongrid_pixmap = QPixmap(savepath)
510
self.ui.icongrid_holder_label.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
511
self.ui.scrollAreaWidgetContents_2.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
512
self.ui.icongrid_holder_label.setPixmap(icongrid_pixmap)
513
elif stat == 1:
514
self.display_msg_box(
515
window_title="Icon image error",
516
text=f"The icon {problemimg} is bigger than 150x150 and couldn't be added to the final grid\nThe final grid was generated without it",
517
icon=QMessageBox.Warning
518
)
519
else:
520
self.display_msg_box(
521
window_title="Error!",
522
text="Please select some icons",
523
icon=QMessageBox.Critical
524
)
525
526
# no need to continue past this if in psych-engine mode
527
return
528
529
if self.icongrid_path != '' and len(self.iconpaths) > 0:
530
print("Valid!")
531
# savedir = QFileDialog.getExistingDirectory(caption="Save New Icongrid to...")
532
# if savedir != '':
533
stat, newinds, problemimg, exception_msg = icongridutils.appendIconToGrid(self.icongrid_path, self.iconpaths) #, savedir)
534
print("[DEBUG] Function finished with status: ", stat)
535
errmsgs = [
536
'Icon grid was too full to insert a new icon',
537
'Your character icon: {} is too big! Max size: 150 x 150',
538
'Unable to find suitable location to insert your icon'
539
]
540
541
if exception_msg is not None:
542
self.display_msg_box(
543
window_title="An Error occured",
544
text=("An Exception (Error) occurred somewhere\nError message:\n"+exception_msg),
545
icon=QMessageBox.Critical
546
)
547
else:
548
if stat == 0:
549
self.display_msg_box(
550
window_title="Done!",
551
text="Your icon-grid has been generated!\nYour icon's indices are {}".format(newinds),
552
icon=QMessageBox.Information
553
)
554
elif stat == 4:
555
self.display_msg_box(
556
window_title="Warning!",
557
text="One of your icons was smaller than the 150 x 150 icon size!\nHowever, your icon-grid is generated but the icon has been re-adjusted. \nYour icon's indices: {}".format(newinds),
558
icon=QMessageBox.Warning
559
)
560
else:
561
self.display_msg_box(
562
window_title="Error!",
563
text=errmsgs[stat - 1].format(problemimg),
564
icon=QMessageBox.Critical
565
)
566
icongrid_pixmap = QPixmap(self.icongrid_path)
567
self.ui.icongrid_holder_label.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
568
self.ui.scrollAreaWidgetContents_2.setFixedSize(icongrid_pixmap.width(), icongrid_pixmap.height())
569
self.ui.icongrid_holder_label.setPixmap(icongrid_pixmap)
570
else:
571
errtxt = "Please add an icon-grid image" if self.icongrid_path == '' else "Please add an icon"
572
self.display_msg_box(
573
window_title="Error!",
574
text=errtxt,
575
icon=QMessageBox.Critical
576
)
577
578
def appendIcon(self):
579
print("Appending icon")
580
self.iconpaths = self.get_asset_path("Select your character icons", "PNG Images (*.png)", True)
581
print("Got icon: ", self.iconpaths)
582
if len(self.iconpaths) > 0:
583
print("Valid selected")
584
self.ui.iconselected_label.setText("No. of\nicons selected:\n{}".format(len(self.iconpaths)))
585
else:
586
self.ui.iconselected_label.setText("No. of\nicons selected:\n0")
587
588
def clearSelectedIcons(self):
589
self.iconpaths = []
590
self.ui.iconselected_label.setText("Number of\nicons selected:\n{}".format(len(self.iconpaths)))
591
592
def setAnimationNames(self):
593
if len(self.selected_labels) == 0:
594
self.display_msg_box(window_title="Error", text="Please select some frames to rename by checking the checkboxes on them", icon=QMessageBox.Critical)
595
else:
596
text, okPressed = QInputDialog.getText(self, "Change Animation (Pose) Prefix Name", "Current Animation (Pose) prefix:"+(" "*50), QLineEdit.Normal) # very hack-y soln but it works!
597
if okPressed and text != '':
598
print("new pose prefix = ", text)
599
for label in self.selected_labels:
600
# self.update_frame_dict(label.img_xml_data.pose_name, label, remove=True)
601
label.data.pose_name = text
602
label.modified = True
603
# self.update_frame_dict(text, label)
604
label.img_label.setToolTip(label.get_tooltip_string(self))
605
606
for label in list(self.selected_labels):
607
# this automatically removes it from self.selected_labels
608
label.select_checkbox.setChecked(False)
609
else:
610
print("Cancel pressed!")
611
612
def display_msg_box(self, window_title="MessageBox", text="Text Here", icon=None):
613
self.msgbox = QMessageBox(self)
614
self.msgbox.setWindowTitle(window_title)
615
self.msgbox.setText(text)
616
if not icon:
617
self.msgbox.setIcon(QMessageBox.Information)
618
else:
619
self.msgbox.setIcon(icon)
620
x = self.msgbox.exec_()
621
print("[DEBUG] Exit status of msgbox: "+str(x))
622
623
def get_asset_path(self, wintitle="Sample", fileformat=None, multiple=False):
624
if multiple:
625
return QFileDialog.getOpenFileNames(
626
caption=wintitle,
627
filter=fileformat,
628
)[0]
629
else:
630
return QFileDialog.getOpenFileName(
631
caption=wintitle,
632
filter=fileformat,
633
)[0]
634
635
636
637
638
if __name__ == '__main__':
639
app = QApplication(sys.argv)
640
641
prefs = None
642
try:
643
with open('preferences.json') as f:
644
prefs = json.load(f)
645
except FileNotFoundError as fnfe:
646
with open("error.log", 'a') as errlog:
647
errlog.write(str(fnfe))
648
649
with open('preferences.json', 'w') as f:
650
prefs = { "theme":"default" }
651
json.dump(prefs, f)
652
653
myapp = MyApp(prefs)
654
myapp.show()
655
656
try:
657
sys.exit(app.exec_())
658
except SystemExit:
659
print("Closing...")
660