this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

message editor fix + dialog creation refactor

clover 099dd0ed 34ce9f38

+2385 -1997
+1 -1
.settings/org.eclipse.jdt.core.prefs
··· 465 465 org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line=one_line_if_empty 466 466 org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false 467 467 org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false 468 - org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=true 468 + org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false 469 469 org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false 470 470 org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line=one_line_never 471 471 org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line=one_line_never
+1 -1
.vscode/eclipse-format.xml
··· 198 198 <setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/> 199 199 <setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/> 200 200 <setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/> 201 - <setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="true"/> 201 + <setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/> 202 202 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/> 203 203 <setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case_after_arrow" value="end_of_line"/> 204 204 <setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+1 -1
app.properties
··· 1 - version=0.9.1 1 + version=0.9.2
+68 -40
src/main/java/app/Environment.java
··· 94 94 private static String gitBuildTag; 95 95 96 96 public static boolean isDeluxe() 97 - { return isDeluxe; } 97 + { 98 + return isDeluxe; 99 + } 98 100 99 101 public static String getVersionString() 100 - { return versionString; } 102 + { 103 + return versionString; 104 + } 101 105 102 106 public static String decorateTitle(String title) 103 107 { ··· 239 243 } 240 244 241 245 public static boolean isCommandLine() 242 - { return commandLine; } 246 + { 247 + return commandLine; 248 + } 243 249 244 250 public static File getWorkingDirectory() 245 251 { ··· 250 256 } 251 257 252 258 public static File getProjectDirectory() 253 - { return projectDirectory; } 259 + { 260 + return projectDirectory; 261 + } 254 262 255 263 public static File getSourceDirectory() 256 - { return new File(projectDirectory, "/src/"); } 264 + { 265 + return new File(projectDirectory, "/src/"); 266 + } 257 267 258 268 public static File getProjectFile(String relativePath) 259 269 { ··· 277 287 278 288 if (!latestVersion.equals("v" + versionString)) { 279 289 Logger.log("Detected newer remote version: " + latestVersion); 280 - SwingUtils.showFramedMessageDialog(null, 281 - "A newer version is available!\n" + 282 - "Please visit the GitHub repo to download it.", 283 - "Update Available", 284 - JOptionPane.WARNING_MESSAGE); 290 + 291 + SwingUtils.getWarningDialog() 292 + .setTitle("Update Available") 293 + .setMessage("A newer version is available!", "Please visit the GitHub repo to download it.") 294 + .show(); 285 295 } 286 296 } 287 297 else { ··· 299 309 File db = Directories.DATABASE.toFile(); 300 310 301 311 if (!db.exists() || !db.isDirectory()) { 302 - SwingUtils.showFramedMessageDialog(null, 303 - "Could not find required directory: " + db.getName() + System.lineSeparator() + 304 - "It should be in the same directory as StarRod.jar" + System.lineSeparator() + 305 - "Did you extract ALL the files for Star Rod?", 306 - "Missing Directory", 307 - JOptionPane.ERROR_MESSAGE); 312 + SwingUtils.getMessageDialog() 313 + .setTitle("Missing Directory") 314 + .setMessage("Could not find required directory: " + db.getName(), 315 + "It should be in the same directory as the jar.") 316 + .setMessageType(JOptionPane.ERROR_MESSAGE) 317 + .show(); 318 + 308 319 exit(); 309 320 } 310 321 } ··· 315 326 316 327 // we may need to create a new config file here 317 328 if (!configFile.exists()) { 318 - int choice = SwingUtils.showFramedConfirmDialog(null, 319 - String.format("Could not find Star Rod config! %nCreate a new one?"), 320 - "Missing Config", 321 - JOptionPane.YES_NO_OPTION, 322 - JOptionPane.QUESTION_MESSAGE); 329 + int choice = SwingUtils.getConfirmDialog() 330 + .setTitle("Missing Config") 331 + .setMessage("Could not find Star Rod config!", "Create a new one?") 332 + .setMessageType(JOptionPane.QUESTION_MESSAGE) 333 + .setOptionsType(JOptionPane.YES_NO_OPTION) 334 + .choose(); 323 335 324 336 if (choice != JOptionPane.OK_OPTION) 325 337 exit(); 326 338 327 339 mainConfig = makeConfig(configFile, Scope.Main); 328 340 329 - SwingUtils.showFramedMessageDialog(null, 330 - "Select your project directory.", 331 - "Select Project Directory", 332 - JOptionPane.PLAIN_MESSAGE); 341 + SwingUtils.getMessageDialog() 342 + .setTitle("Select Project Directory") 343 + .setMessage("Select your project directory.") 344 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 345 + .show(); 333 346 334 347 return promptSelectProject(); 335 348 } ··· 353 366 } 354 367 355 368 // project directory is missing, prompt to select new one 356 - SwingUtils.showFramedMessageDialog(null, 357 - String.format("Could not find project directory! %nPlease select a new one."), 358 - "Missing Project Directory", 359 - JOptionPane.ERROR_MESSAGE); 369 + SwingUtils.getErrorDialog() 370 + .setTitle("Missing Project Directory") 371 + .setMessage("Could not find project directory!", "Please select a new one.") 372 + .show(); 360 373 361 374 return promptSelectProject(); 362 375 } ··· 384 397 if (isCommandLine()) 385 398 Logger.logError(message); 386 399 else 387 - SwingUtils.showFramedMessageDialog(null, message, title, JOptionPane.ERROR_MESSAGE); 400 + SwingUtils.getErrorDialog() 401 + .setTitle(title) 402 + .setMessage(message) 403 + .show(); 388 404 } 389 405 390 406 public static boolean loadProject(File projectDir) throws IOException ··· 475 491 File configFile = new File(projectDirectory, FN_PROJ_CONFIG); 476 492 477 493 if (!configFile.exists()) { 478 - int choice = SwingUtils.showFramedConfirmDialog(null, 479 - "Could not find project config!\nCreate a new one?", 480 - "Missing Config", 481 - JOptionPane.YES_NO_OPTION, 482 - JOptionPane.QUESTION_MESSAGE); 494 + 495 + int choice = SwingUtils.getConfirmDialog() 496 + .setTitle("Missing Config") 497 + .setMessage("Could not find project config!", "Create a new one?") 498 + .setMessageType(JOptionPane.QUESTION_MESSAGE) 499 + .setOptionsType(JOptionPane.YES_NO_OPTION) 500 + .choose(); 483 501 484 502 if (choice != JOptionPane.OK_OPTION) 485 503 exit(); ··· 545 563 } 546 564 547 565 public static boolean isWindows() 548 - { return osFamily == OSFamily.Windows; } 566 + { 567 + return osFamily == OSFamily.Windows; 568 + } 549 569 550 570 public static boolean isMacOS() 551 - { return osFamily == OSFamily.Mac; } 571 + { 572 + return osFamily == OSFamily.Mac; 573 + } 552 574 553 575 public static boolean isLinux() 554 - { return osFamily == OSFamily.Linux; } 576 + { 577 + return osFamily == OSFamily.Linux; 578 + } 555 579 556 580 public static void reloadIcons() 557 581 { ··· 562 586 } 563 587 564 588 public static final Image getDefaultIconImage() 565 - { return (ICON_DEFAULT == null) ? null : ICON_DEFAULT.getImage(); } 589 + { 590 + return (ICON_DEFAULT == null) ? null : ICON_DEFAULT.getImage(); 591 + } 566 592 567 593 public static final Image getErrorIconImage() 568 - { return (ICON_DEFAULT == null) ? null : ICON_DEFAULT.getImage(); } 594 + { 595 + return (ICON_DEFAULT == null) ? null : ICON_DEFAULT.getImage(); 596 + } 569 597 570 598 private static ImageIcon loadIconAsset(ExpectedAsset asset) 571 599 {
+44 -28
src/main/java/app/RomValidator.java
··· 39 39 public static File validateROM(File f) throws IOException 40 40 { 41 41 if (f.length() != LENGTH) { 42 - SwingUtils.showFramedMessageDialog(null, 43 - "Selected file is not the correct size.", 44 - "ROM Validation Error", 45 - JOptionPane.ERROR_MESSAGE); 42 + SwingUtils.getMessageDialog() 43 + .setTitle("ROM Validation Error") 44 + .setMessage("Selected file is not the correct size.") 45 + .setMessageType(JOptionPane.ERROR_MESSAGE) 46 + .show(); 47 + 46 48 return null; 47 49 } 48 50 ··· 76 78 77 79 if (v64 || n64 || x64) { 78 80 // just need to byteswap 79 - SwingUtils.showFramedMessageDialog(null, 80 - "Selected ROM has incorrect byte order.\nA corrected copy will be made.", 81 - "ROM Validation Warning", 82 - JOptionPane.WARNING_MESSAGE); 81 + SwingUtils.getMessageDialog() 82 + .setTitle("ROM Validation Warning") 83 + .setMessage("Selected ROM has incorrect byte order.", "A corrected copy will be made.") 84 + .setMessageType(JOptionPane.WARNING_MESSAGE) 85 + .show(); 83 86 84 87 pleaseWait.setVisible(true); 85 88 ··· 114 117 } 115 118 else { 116 119 pleaseWait.setVisible(false); 117 - SwingUtils.showFramedMessageDialog(null, 118 - "Incorrect ROM or version, CRC does not match.", 119 - "ROM Validation Failure", 120 - JOptionPane.ERROR_MESSAGE); 120 + 121 + SwingUtils.getMessageDialog() 122 + .setTitle("ROM Validation Failure") 123 + .setMessage("Incorrect ROM or version, CRC does not match.") 124 + .setMessageType(JOptionPane.ERROR_MESSAGE) 125 + .show(); 126 + 121 127 raf.close(); 122 128 return null; 123 129 } ··· 129 135 // now compute the checksum 130 136 if (!verifyCRCs(raf)) { 131 137 pleaseWait.setVisible(false); 132 - SwingUtils.showFramedMessageDialog(null, 133 - "ROM data does not match CRC values!", 134 - "ROM Validation Failure", 135 - JOptionPane.ERROR_MESSAGE); 138 + 139 + SwingUtils.getMessageDialog() 140 + .setTitle("ROM Validation Failure") 141 + .setMessage("ROM data does not match CRC values!") 142 + .setMessageType(JOptionPane.ERROR_MESSAGE) 143 + .show(); 144 + 136 145 return null; 137 146 } 138 147 } 139 148 else { 140 149 pleaseWait.setVisible(false); 141 - SwingUtils.showFramedMessageDialog(null, 142 - "Incorrect ROM or version, CRC does not match.", 143 - "ROM Validation Failure", 144 - JOptionPane.ERROR_MESSAGE); 150 + 151 + SwingUtils.getMessageDialog() 152 + .setTitle("ROM Validation Failure") 153 + .setMessage("Incorrect ROM or version, CRC does not match.") 154 + .setMessageType(JOptionPane.ERROR_MESSAGE) 155 + .show(); 156 + 145 157 raf.close(); 146 158 return null; 147 159 } ··· 162 174 String fileMD5 = sb.toString(); 163 175 if (!fileMD5.equals(MD5)) { 164 176 pleaseWait.setVisible(false); 165 - SwingUtils.showFramedMessageDialog(null, 166 - "MD5 hash does not match!", 167 - "ROM Validation Failure", 168 - JOptionPane.ERROR_MESSAGE); 177 + 178 + SwingUtils.getMessageDialog() 179 + .setTitle("ROM Validation Failure") 180 + .setMessage("MD5 hash does not match!") 181 + .setMessageType(JOptionPane.ERROR_MESSAGE) 182 + .show(); 183 + 169 184 return null; 170 185 } 171 186 } 172 187 catch (NoSuchAlgorithmException e) { 173 - SwingUtils.showFramedMessageDialog(null, 174 - "Missing MD5 hash algorithm, could not complete validation!", 175 - "ROM Validation Warning", 176 - JOptionPane.WARNING_MESSAGE); 188 + SwingUtils.getMessageDialog() 189 + .setTitle("ROM Validation Warning") 190 + .setMessage("Missing MD5 hash algorithm, could not complete validation!") 191 + .setMessageType(JOptionPane.WARNING_MESSAGE) 192 + .show(); 177 193 } 178 194 179 195 pleaseWait.setVisible(false);
+9 -11
src/main/java/app/StackTraceDialog.java
··· 146 146 JOptionPane.UNINITIALIZED_VALUE); 147 147 148 148 if (value.equals(OPT_DETAILS)) { 149 - String[] options = { "OK", "Copy to Clipboard" }; 150 - 151 149 JScrollPane detailScrollPane = new JScrollPane(textArea); 152 150 detailScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); 153 151 154 - int selection = SwingUtils.showFramedOptionDialog(null, 155 - detailScrollPane, 156 - "Exception Details", 157 - JOptionPane.YES_NO_CANCEL_OPTION, 158 - JOptionPane.ERROR_MESSAGE, 159 - Environment.ICON_ERROR, 160 - options, 161 - options[0]); 152 + int choice = SwingUtils.getOptionDialog() 153 + .setTitle("Exception Details") 154 + .setMessage(detailScrollPane) 155 + .setMessageType(JOptionPane.ERROR_MESSAGE) 156 + .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION) 157 + .setIcon(Environment.ICON_ERROR) 158 + .setOptions("OK", "Copy to Clipboard") 159 + .choose(); 162 160 163 - if (selection == 1) { 161 + if (choice == 1) { 164 162 StringSelection stringSelection = new StringSelection(textArea.getText()); 165 163 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); 166 164 cb.setContents(stringSelection, null);
+24 -19
src/main/java/app/StarRodMain.java
··· 247 247 int choice = JOptionPane.OK_OPTION; 248 248 249 249 if (taskRunning) 250 - choice = SwingUtils.showFramedConfirmDialog(null, String.format( 251 - "A task is still running. %nAre you sure you want to exit?"), 252 - "Task Still Running", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 250 + choice = SwingUtils.getConfirmDialog() 251 + .setTitle("Task Still Running") 252 + .setMessage("A task is still running.", "Are you sure you want to exit?") 253 + .setMessageType(JOptionPane.WARNING_MESSAGE) 254 + .setOptionsType(JOptionPane.YES_NO_OPTION) 255 + .choose(); 253 256 254 257 if (choice == JOptionPane.OK_OPTION) { 255 258 dispose(); ··· 387 390 { 388 391 new EditorWorker(() -> { 389 392 if (!Environment.projectConfig.getBoolean(Options.ExtractedMapData)) { 390 - int result = SwingUtils.showFramedConfirmDialog(null, 391 - "This action will modify the source files of almost every map.\n" 392 - + "Consider creating a backup or committing any changes before proceeding.\n" 393 - + "Are you ready to begin extracting?", 394 - "Extraction Warning", 395 - JOptionPane.YES_NO_CANCEL_OPTION, 396 - JOptionPane.WARNING_MESSAGE); 393 + int choice = SwingUtils.getConfirmDialog() 394 + .setTitle("Extraction Warning") 395 + .setMessage("This action will modify the source files of almost every map.", 396 + "Consider creating a backup or committing any changes before proceeding.", 397 + "Are you ready to begin extracting?") 398 + .setMessageType(JOptionPane.WARNING_MESSAGE) 399 + .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION) 400 + .choose(); 397 401 398 - if (result == JOptionPane.YES_OPTION) { 402 + if (choice == JOptionPane.YES_OPTION) { 399 403 Logger.log("Extracting map data...", Priority.MILESTONE); 400 404 Extractor.extractAll(); 401 405 402 - SwingUtils.showFramedMessageDialog(null, 403 - "Complete!", 404 - "All Data Extracted", 405 - JOptionPane.PLAIN_MESSAGE); 406 + SwingUtils.getMessageDialog() 407 + .setTitle("All Data Extracted") 408 + .setMessage("Complete!") 409 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 410 + .show(); 406 411 407 412 Environment.projectConfig.setBoolean(Options.ExtractedMapData, true); 408 413 Environment.projectConfig.saveConfigFile(); 409 414 } 410 415 } 411 416 else { 412 - SwingUtils.showFramedMessageDialog(null, 413 - "Map data has already been extracted for this project.", 414 - "Data Already Extracted", 415 - JOptionPane.WARNING_MESSAGE); 417 + SwingUtils.getWarningDialog() 418 + .setTitle("Data Already Extracted") 419 + .setMessage("Map data has already been extracted for this project.") 420 + .show(); 416 421 } 417 422 }); 418 423 }
+204 -111
src/main/java/app/SwingUtils.java
··· 18 18 import javax.swing.JComboBox; 19 19 import javax.swing.JComponent; 20 20 import javax.swing.JDialog; 21 - import javax.swing.JFileChooser; 22 21 import javax.swing.JFrame; 23 22 import javax.swing.JLabel; 24 23 import javax.swing.JOptionPane; ··· 75 74 return dialogFrame; 76 75 } 77 76 78 - public static final int showFramedOpenDialog(JFileChooser chooser, Component parentComponent) 77 + public static class OpenDialogCounter 79 78 { 80 - JFrame dialogFrame = createDialogFrame(parentComponent, chooser.getDialogTitle()); 81 - int choice = chooser.showOpenDialog(dialogFrame); 82 - dialogFrame.dispose(); 83 - return choice; 79 + private int count; 80 + 81 + public OpenDialogCounter() 82 + { 83 + count = 0; 84 + } 85 + 86 + public void increment() 87 + { 88 + count++; 89 + } 90 + 91 + public void decrement() 92 + { 93 + count--; 94 + } 95 + 96 + public void reset() 97 + { 98 + count = 0; 99 + } 100 + 101 + public boolean isZero() 102 + { 103 + return count == 0; 104 + } 84 105 } 85 106 86 - public static final int showFramedSaveDialog(JFileChooser chooser, Component parentComponent) 107 + private static enum DialogType 87 108 { 88 - JFrame dialogFrame = createDialogFrame(parentComponent, chooser.getDialogTitle()); 89 - int choice = chooser.showSaveDialog(dialogFrame); 90 - dialogFrame.dispose(); 91 - return choice; 109 + MESSAGE, 110 + CONFIRM, 111 + INPUT, 112 + OPTION, 113 + WARNING, 114 + ERROR 92 115 } 93 116 94 - public static final void showFramedMessageDialog( 95 - Component parentComponent, 96 - Object message, 97 - String title, 98 - int messageType, 99 - Icon icon) 117 + public static final DialogBuilder getMessageDialog() 100 118 { 101 - JFrame dialogFrame = createDialogFrame(parentComponent, title); 102 - JOptionPane.showMessageDialog(dialogFrame, message, title, messageType, icon); 103 - dialogFrame.dispose(); 119 + return new DialogBuilder(DialogType.MESSAGE); 104 120 } 105 121 106 - public static final void showFramedMessageDialog( 107 - Component parentComponent, 108 - Object message, 109 - String title, 110 - int messageType) 122 + public static final DialogBuilder getConfirmDialog() 111 123 { 112 - JFrame dialogFrame = createDialogFrame(parentComponent, title); 113 - JOptionPane.showMessageDialog(dialogFrame, message, title, messageType); 114 - dialogFrame.dispose(); 124 + return new DialogBuilder(DialogType.CONFIRM); 115 125 } 116 126 117 - public static final void showFramedErrorMessage( 118 - Component parentComponent, 119 - Object message, 120 - String title) 127 + public static final DialogBuilder getInputDialog() 121 128 { 122 - showFramedMessageDialog(parentComponent, message, 123 - title, JOptionPane.ERROR_MESSAGE, Environment.ICON_ERROR); 129 + return new DialogBuilder(DialogType.INPUT); 124 130 } 125 131 126 - /* 127 - public static final void showFramedMessageDialog( 128 - Component parentComponent, 129 - Object message, 130 - String title) 132 + public static final DialogBuilder getOptionDialog() 131 133 { 132 - JFrame dialogFrame = createDiaglogFrame(parentComponent, title); 133 - JOptionPane.showMessageDialog(dialogFrame, message); 134 - dialogFrame.dispose(); 134 + return new DialogBuilder(DialogType.OPTION); 135 135 } 136 - */ 137 136 138 - public static final int showFramedOptionDialog( 139 - Component parentComponent, 140 - Object message, 141 - String title, 142 - int optionType, 143 - int messageType, 144 - Object[] options, 145 - Object initialValue) 137 + public static final DialogBuilder getWarningDialog() 146 138 { 147 - JFrame dialogFrame = createDialogFrame(parentComponent, title); 148 - int choice = JOptionPane.showOptionDialog( 149 - dialogFrame, message, title, 150 - optionType, messageType, null, 151 - options, initialValue); 152 - dialogFrame.dispose(); 153 - return choice; 139 + return new DialogBuilder(DialogType.WARNING); 154 140 } 155 141 156 - public static final int showFramedOptionDialog( 157 - Component parentComponent, 158 - Object message, 159 - String title, 160 - int optionType, 161 - int messageType, 162 - Icon icon, 163 - Object[] options, 164 - Object initialValue) 142 + public static final DialogBuilder getErrorDialog() 165 143 { 166 - JFrame dialogFrame = createDialogFrame(parentComponent, title); 167 - int choice = JOptionPane.showOptionDialog( 168 - dialogFrame, message, title, 169 - optionType, messageType, icon, 170 - options, initialValue); 171 - dialogFrame.dispose(); 172 - return choice; 144 + return new DialogBuilder(DialogType.ERROR); 173 145 } 174 146 175 - public static final int showFramedConfirmDialog( 176 - Component parentComponent, 177 - Object message, 178 - String title, 179 - int optionType, 180 - int messageType) 147 + public static class DialogBuilder 181 148 { 182 - JFrame dialogFrame = createDialogFrame(parentComponent, title); 183 - int choice = JOptionPane.showConfirmDialog( 184 - dialogFrame, message, title, 185 - optionType, messageType); 186 - dialogFrame.dispose(); 187 - return choice; 188 - } 149 + private final DialogType type; 150 + private String title = "TITLE MISSING"; 151 + private Object message = "MESSAGE MISSING"; 152 + private int optionType; 153 + private int messageType; 154 + private Icon icon; 155 + private Object[] options = null; 156 + private Object initialValue = null; 157 + private Component parentComponent = null; 158 + private OpenDialogCounter counter = null; 159 + 160 + private DialogBuilder(DialogType type) 161 + { 162 + this.type = type; 163 + 164 + // set defaults 165 + switch (type) { 166 + case MESSAGE: 167 + optionType = JOptionPane.DEFAULT_OPTION; 168 + messageType = JOptionPane.INFORMATION_MESSAGE; 169 + break; 170 + case CONFIRM: 171 + optionType = JOptionPane.YES_NO_CANCEL_OPTION; 172 + messageType = JOptionPane.QUESTION_MESSAGE; 173 + break; 174 + case INPUT: 175 + break; 176 + case OPTION: 177 + break; 178 + case WARNING: 179 + messageType = JOptionPane.WARNING_MESSAGE; 180 + break; 181 + case ERROR: 182 + messageType = JOptionPane.ERROR_MESSAGE; 183 + icon = Environment.ICON_ERROR; 184 + break; 185 + } 186 + } 187 + 188 + public DialogBuilder setTitle(String title) 189 + { 190 + this.title = title; 191 + return this; 192 + } 193 + 194 + public DialogBuilder setMessage(Object message) 195 + { 196 + this.message = message; 197 + return this; 198 + } 199 + 200 + public DialogBuilder setMessage(String ... lines) 201 + { 202 + this.message = String.join(System.lineSeparator(), lines); 203 + return this; 204 + } 205 + 206 + public DialogBuilder setMessageType(int messageType) 207 + { 208 + this.messageType = messageType; 209 + return this; 210 + } 211 + 212 + public DialogBuilder setOptionsType(int optionType) 213 + { 214 + this.optionType = optionType; 215 + return this; 216 + } 217 + 218 + public DialogBuilder setIcon(Icon icon) 219 + { 220 + this.icon = icon; 221 + return this; 222 + } 223 + 224 + public DialogBuilder setOptions(String ... options) 225 + { 226 + this.options = options; 227 + return this; 228 + } 229 + 230 + public DialogBuilder setDefault(Object initialValue) 231 + { 232 + this.initialValue = initialValue; 233 + return this; 234 + } 235 + 236 + public DialogBuilder setParent(Component parentComponent) 237 + { 238 + this.parentComponent = parentComponent; 239 + return this; 240 + } 241 + 242 + public DialogBuilder setCounter(OpenDialogCounter counter) 243 + { 244 + this.counter = counter; 245 + return this; 246 + } 247 + 248 + public void show() 249 + { 250 + choose(); 251 + } 252 + 253 + public void showLater() 254 + { 255 + if (SwingUtilities.isEventDispatchThread()) { 256 + choose(); 257 + } 258 + else { 259 + SwingUtilities.invokeLater(() -> { 260 + choose(); 261 + }); 262 + } 263 + } 189 264 190 - public static final int showFramedConfirmDialog( 191 - Component parentComponent, 192 - Object message, 193 - String title, 194 - int optionType) 195 - { 196 - JFrame dialogFrame = createDialogFrame(parentComponent, title); 197 - int choice = JOptionPane.showConfirmDialog( 198 - dialogFrame, message, title, optionType); 199 - dialogFrame.dispose(); 200 - return choice; 201 - } 265 + public String prompt() 266 + { 267 + if (counter != null) 268 + counter.increment(); 202 269 203 - public static final String showFramedInputDialog( 204 - Component parentComponent, 205 - Object message, 206 - String title, 207 - int messageType) 208 - { 209 - JFrame dialogFrame = createDialogFrame(parentComponent, title); 210 - String reply = JOptionPane.showInputDialog(dialogFrame, message, title, messageType); 211 - dialogFrame.dispose(); 212 - return reply; 270 + JFrame dialogFrame = createDialogFrame(parentComponent, title); 271 + 272 + Object result = JOptionPane.showInputDialog(parentComponent, 273 + message, title, messageType, 274 + icon, options, initialValue); 275 + 276 + dialogFrame.dispose(); 277 + 278 + if (counter != null) 279 + counter.decrement(); 280 + 281 + return (String) result; 282 + } 283 + 284 + public int choose() 285 + { 286 + if (counter != null) 287 + counter.increment(); 288 + 289 + JFrame dialogFrame = createDialogFrame(parentComponent, title); 290 + 291 + int result = JOptionPane.showOptionDialog(parentComponent, 292 + message, title, optionType, messageType, 293 + icon, options, initialValue); 294 + 295 + dialogFrame.dispose(); 296 + 297 + if (counter != null) 298 + counter.decrement(); 299 + 300 + return result; 301 + } 213 302 } 214 303 215 304 public static final void showDialog(JDialog dialog, String title) ··· 471 560 } 472 561 473 562 public static Color getTextColor() 474 - { return UIManager.getColor("Label.foreground"); } 563 + { 564 + return UIManager.getColor("Label.foreground"); 565 + } 475 566 476 567 private static Color getBackgoundColor() 477 - { return UIManager.getColor("Label.background"); } 568 + { 569 + return UIManager.getColor("Label.background"); 570 + } 478 571 479 572 private static int getBackgroundLuminance() 480 573 {
+9 -6
src/main/java/app/ThemesEditor.java
··· 75 75 exitToMainMenu = true; 76 76 String currentThemeName = Themes.getCurrentThemeName(); 77 77 if (!initialThemeName.equals(currentThemeName)) { 78 - int choice = SwingUtils.showFramedConfirmDialog(null, 79 - String.format("Theme has been changed.%nDo you want to save changes?"), 80 - "Save Changes", JOptionPane.YES_NO_CANCEL_OPTION); 78 + int choice = SwingUtils.getConfirmDialog() 79 + .setTitle("Save Changes") 80 + .setMessage("Theme has been changed.", "Do you want to save changes?") 81 + .choose(); 81 82 82 83 switch (choice) { 83 84 case JOptionPane.YES_OPTION: 84 85 Environment.mainConfig.setString(Options.Theme, Themes.getCurrentThemeKey()); 85 86 Environment.mainConfig.saveConfigFile(); 86 87 87 - SwingUtils.showFramedMessageDialog(null, 88 - String.format("Theme has been changed. %nStar Rod must restart."), 89 - "Theme Changed", JOptionPane.WARNING_MESSAGE); 88 + SwingUtils.getWarningDialog() 89 + .setTitle("Theme Changed") 90 + .setMessage("Theme has been changed.", "Star Rod must restart.") 91 + .show(); 92 + 90 93 Environment.exit(); 91 94 break; 92 95 case JOptionPane.NO_OPTION:
+7 -7
src/main/java/app/config/Config.java
··· 8 8 import java.util.List; 9 9 import java.util.Map.Entry; 10 10 11 - import javax.swing.JOptionPane; 12 - 13 11 import app.SwingUtils; 14 12 import app.config.Options.Scope; 15 13 import app.config.Options.Type; ··· 31 29 } 32 30 33 31 public File getFile() 34 - { return file; } 32 + { 33 + return file; 34 + } 35 35 36 36 public void readConfig() throws IOException 37 37 { ··· 100 100 pw.close(); 101 101 } 102 102 catch (FileNotFoundException e) { 103 - SwingUtils.showFramedMessageDialog(null, 104 - "Could not update config: " + file.getAbsolutePath(), 105 - "Config Write Exception", 106 - JOptionPane.ERROR_MESSAGE); 103 + SwingUtils.getErrorDialog() 104 + .setTitle("Config Write Exception") 105 + .setMessage("Could not update config:", file.getAbsolutePath()) 106 + .show(); 107 107 System.exit(-1); 108 108 } 109 109
+23 -16
src/main/java/assets/ui/SelectMapDialog.java
··· 97 97 Map newMap = Map.loadMap(selectedFile); 98 98 99 99 // prompt for a description 100 - String newMapDesc = SwingUtils.showFramedInputDialog(null, 101 - "Provide a map description", 102 - "New Map Description", 103 - JOptionPane.QUESTION_MESSAGE); 100 + String newMapDesc = SwingUtils.getInputDialog() 101 + .setTitle("New Map Description") 102 + .setMessage("Provide a map description") 103 + .setMessageType(JOptionPane.QUESTION_MESSAGE) 104 + .prompt(); 105 + 104 106 newMap.desc = (newMapDesc != null) ? newMapDesc : ""; 105 107 106 108 // save the new map ··· 128 130 Map newMap = new Map(newMapName); 129 131 130 132 // prompt for a description 131 - String newMapDesc = SwingUtils.showFramedInputDialog(null, 132 - "Provide a map description", 133 - "New Map Description", 134 - JOptionPane.QUESTION_MESSAGE); 133 + String newMapDesc = SwingUtils.getInputDialog() 134 + .setTitle("New Map Description") 135 + .setMessage("Provide a map description") 136 + .setMessageType(JOptionPane.QUESTION_MESSAGE) 137 + .prompt(); 138 + 135 139 newMap.desc = (newMapDesc != null) ? newMapDesc : ""; 136 140 137 141 // prompt for textures ··· 160 164 161 165 public static File requestNewMapFile() 162 166 { 163 - String name = SwingUtils.showFramedInputDialog(null, 164 - "Provide a new map name", 165 - "New Map Name", 166 - JOptionPane.QUESTION_MESSAGE); 167 + String name = SwingUtils.getInputDialog() 168 + .setTitle("New Map Name") 169 + .setMessage("Provide a new map name") 170 + .setMessageType(JOptionPane.QUESTION_MESSAGE) 171 + .prompt(); 167 172 168 173 if (name == null) 169 174 return null; ··· 182 187 if (!existing.exists()) 183 188 return existing; 184 189 185 - int response = SwingUtils.showFramedConfirmDialog(null, 186 - name + " already exists. Overwrite it?", 187 - "Map Already Exists", JOptionPane.YES_NO_CANCEL_OPTION); 190 + int choice = SwingUtils.getConfirmDialog() 191 + .setTitle("Map Already Exists") 192 + .setMessage(name + " already exists. Overwrite it?") 193 + .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION) 194 + .choose(); 188 195 189 - return (response == JOptionPane.YES_OPTION) ? existing : null; 196 + return (choice == JOptionPane.YES_OPTION) ? existing : null; 190 197 } 191 198 192 199 private final JList<MapAsset> list;
+30 -15
src/main/java/game/globals/editor/GlobalsEditor.java
··· 38 38 import game.globals.editor.tabs.ItemTab; 39 39 import game.globals.editor.tabs.MoveTab; 40 40 import game.message.Message; 41 - import game.message.editor.MessageGroup; 41 + import game.message.editor.MessageAsset; 42 42 import net.miginfocom.swing.MigLayout; 43 43 import util.DualHashMap; 44 44 import util.IterableListModel; ··· 207 207 @Override 208 208 public void windowClosing(WindowEvent e) 209 209 { 210 - int choice = !tabsHaveChanges() ? JOptionPane.NO_OPTION 211 - : SwingUtils.showFramedConfirmDialog(null, 212 - String.format("Unsaved changes will be lost!%nWould you like to save now?"), 213 - "Warning", JOptionPane.YES_NO_CANCEL_OPTION); 210 + int choice = JOptionPane.NO_OPTION; 211 + 212 + if (tabsHaveChanges()) { 213 + choice = SwingUtils.getConfirmDialog() 214 + .setTitle("Warning") 215 + .setMessage("Unsaved changes will be lost!", "Would you like to save now?") 216 + .choose(); 217 + } 218 + 214 219 switch (choice) { 215 220 case JOptionPane.YES_OPTION: 216 221 saveAllChanges(); ··· 263 268 264 269 item = new JMenuItem("Reload Data"); 265 270 item.addActionListener((e) -> { 266 - int choice = !currentTabHasChanges() ? JOptionPane.OK_OPTION 267 - : SwingUtils.showFramedConfirmDialog(null, 268 - String.format("Any changes will be lost.%nAre you sure you want to reload?"), 269 - "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 271 + int choice = JOptionPane.OK_OPTION; 272 + if (currentTabHasChanges()) { 273 + choice = SwingUtils.getConfirmDialog() 274 + .setTitle("Warning") 275 + .setMessage("Any changes will be lost.", "Are you sure you want to reload?") 276 + .setMessageType(JOptionPane.WARNING_MESSAGE) 277 + .setOptionsType(JOptionPane.YES_NO_OPTION) 278 + .choose(); 279 + } 280 + 270 281 if (choice == JOptionPane.OK_OPTION) 271 282 reloadCurrentTab(); 272 283 }); ··· 276 287 277 288 item = new JMenuItem("Save Changes"); 278 289 item.addActionListener((e) -> { 279 - int choice = !tabsHaveChanges() ? JOptionPane.OK_OPTION 280 - : SwingUtils.showFramedConfirmDialog(null, 281 - String.format("Are you sure you want to overwrite existing data?"), 282 - "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 290 + int choice = JOptionPane.OK_OPTION; 291 + if (tabsHaveChanges()) { 292 + choice = SwingUtils.getConfirmDialog() 293 + .setTitle("Warning") 294 + .setMessage("Are you sure you want to overwrite existing data?") 295 + .setMessageType(JOptionPane.WARNING_MESSAGE) 296 + .setOptionsType(JOptionPane.YES_NO_OPTION) 297 + .choose(); 298 + } 283 299 if (choice == JOptionPane.OK_OPTION) 284 300 saveAllChanges(); 285 301 }); ··· 356 372 messageNameMap.clear(); 357 373 358 374 try { 359 - int sectionID = 0; 360 375 for (AssetHandle ah : AssetManager.getMessages()) { 361 376 Logger.log("Reading messages from: " + ah.getName()); 362 - MessageGroup group = new MessageGroup(ah, sectionID++); 377 + MessageAsset group = new MessageAsset(ah); 363 378 for (Message msg : group.messages) { 364 379 messageNameMap.put("MSG_" + msg.name, msg); 365 380 messageListModel.addElement(msg);
+29 -8
src/main/java/game/globals/editor/tabs/ItemTab.java
··· 42 42 import game.globals.editor.renderers.ItemListRenderer; 43 43 import game.globals.editor.renderers.MessageCellRenderer; 44 44 import game.globals.editor.renderers.PaddedCellRenderer; 45 + import game.map.editor.ui.SwingGUI; 45 46 import game.message.Message; 46 47 import net.miginfocom.swing.MigLayout; 47 48 import util.Logger; ··· 117 118 118 119 @Override 119 120 protected String getTabName() 120 - { return "Items"; } 121 + { 122 + return "Items"; 123 + } 121 124 122 125 @Override 123 126 protected ExpectedAsset getIcon() 124 - { return ExpectedAsset.ICON_FIRE_FLOWER; } 127 + { 128 + return ExpectedAsset.ICON_FIRE_FLOWER; 129 + } 125 130 126 131 @Override 127 132 protected GlobalsCategory getDataType() 128 - { return GlobalsCategory.ITEM_TABLE; } 133 + { 134 + return GlobalsCategory.ITEM_TABLE; 135 + } 129 136 130 137 @Override 131 138 protected void notifyDataChange(GlobalsCategory type) ··· 412 419 ItemRecord item = getSelected(); 413 420 FlagEditorPanel flagPanel = new FlagEditorPanel(item.typeFlags); 414 421 415 - if (JOptionPane.YES_OPTION == SwingUtils.showFramedConfirmDialog( 416 - null, flagPanel, "Set Type Flags", JOptionPane.OK_CANCEL_OPTION)) { 422 + int choice = SwingUtils.getConfirmDialog() 423 + .setParent(SwingGUI.instance()) 424 + .setTitle("Set Type Flags") 425 + .setMessage(flagPanel) 426 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 427 + .choose(); 428 + 429 + if (choice == JOptionPane.YES_OPTION) { 417 430 int newValue = flagPanel.getValue(); 418 431 if (newValue != item.typeFlags.getBits()) { 419 432 item.typeFlags.setBits(newValue); ··· 438 451 ItemRecord item = getSelected(); 439 452 FlagEditorPanel flagPanel = new FlagEditorPanel(item.targetFlags); 440 453 441 - if (JOptionPane.YES_OPTION == SwingUtils.showFramedConfirmDialog( 442 - null, flagPanel, "Set Target Flags", JOptionPane.OK_CANCEL_OPTION)) { 454 + int choice = SwingUtils.getConfirmDialog() 455 + .setParent(SwingGUI.instance()) 456 + .setTitle("Set Target Flags") 457 + .setMessage(flagPanel) 458 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 459 + .choose(); 460 + 461 + if (choice == JOptionPane.YES_OPTION) { 443 462 int newValue = flagPanel.getValue(); 444 463 if (newValue != item.targetFlags.getBits()) { 445 464 item.targetFlags.setBits(newValue); ··· 757 776 758 777 @Override 759 778 protected ListCellRenderer<ItemRecord> getCellRenderer() 760 - { return new ItemListRenderer(editor.data); } 779 + { 780 + return new ItemListRenderer(editor.data); 781 + } 761 782 }
+21 -6
src/main/java/game/globals/editor/tabs/MoveTab.java
··· 30 30 import game.globals.editor.renderers.MessageCellRenderer; 31 31 import game.globals.editor.renderers.MoveListRenderer; 32 32 import game.globals.editor.renderers.PaddedCellRenderer; 33 + import game.map.editor.ui.SwingGUI; 33 34 import game.message.Message; 34 35 import net.miginfocom.swing.MigLayout; 35 36 import util.Logger; ··· 87 88 88 89 @Override 89 90 protected String getTabName() 90 - { return "Moves"; } 91 + { 92 + return "Moves"; 93 + } 91 94 92 95 @Override 93 96 protected ExpectedAsset getIcon() 94 - { return ExpectedAsset.ICON_POWER_JUMP; } 97 + { 98 + return ExpectedAsset.ICON_POWER_JUMP; 99 + } 95 100 96 101 @Override 97 102 protected GlobalsCategory getDataType() 98 - { return GlobalsCategory.MOVE_TABLE; } 103 + { 104 + return GlobalsCategory.MOVE_TABLE; 105 + } 99 106 100 107 @Override 101 108 protected void notifyDataChange(GlobalsCategory type) ··· 377 384 MoveRecord move = getSelected(); 378 385 FlagEditorPanel flagPanel = new FlagEditorPanel(move.targetFlags); 379 386 380 - if (JOptionPane.YES_OPTION == SwingUtils.showFramedConfirmDialog( 381 - null, flagPanel, "Set Flags", JOptionPane.OK_CANCEL_OPTION)) { 387 + int choice = SwingUtils.getConfirmDialog() 388 + .setParent(SwingGUI.instance()) 389 + .setTitle("Set Flags") 390 + .setMessage(flagPanel) 391 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 392 + .choose(); 393 + 394 + if (choice == JOptionPane.YES_OPTION) { 382 395 int newValue = flagPanel.getValue(); 383 396 if (newValue != move.targetFlags.getBits()) { 384 397 move.targetFlags.setBits(newValue); ··· 521 534 522 535 @Override 523 536 protected ListCellRenderer<MoveRecord> getCellRenderer() 524 - { return new MoveListRenderer(); } 537 + { 538 + return new MoveListRenderer(); 539 + } 525 540 }
+3 -3
src/main/java/game/map/editor/EditorShortcut.java
··· 9 9 import javax.swing.JMenuItem; 10 10 import javax.swing.KeyStroke; 11 11 12 - import game.sprite.editor.ShortcutListPanel; 13 - 14 12 /** 15 13 * Key combinations that execute some action when pressed in the editor window 16 14 * (specifically, when the GL canvas has focus). Each can be linked to a checkbox ··· 217 215 } 218 216 219 217 public JCheckBoxMenuItem getCheckBox() 220 - { return checkbox; } 218 + { 219 + return checkbox; 220 + } 221 221 222 222 private static final HashMap<Integer, EditorShortcut> inputKeyMap; 223 223 private static final HashMap<Integer, EditorShortcut> inputCtrlKeyMap;
+100 -54
src/main/java/game/map/editor/MapEditor.java
··· 580 580 } 581 581 582 582 public boolean isLoading() 583 - { return loading; } 583 + { 584 + return loading; 585 + } 584 586 585 587 /** 586 588 * Start running the editor, prompting the user to select a map ··· 865 867 if (crashMap == null) 866 868 return null; 867 869 868 - int choice = SwingUtils.showFramedConfirmDialog(null, 869 - "Found crash data for " + crashMap.getName() + ", would you like to load?", "Crash Recovery", 870 - JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); 870 + int choice = SwingUtils.getConfirmDialog() 871 + .setTitle("Crash Recovery") 872 + .setMessage("Found crash data for " + crashMap.getName(), "Would you like to load it?") 873 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 874 + .setOptionsType(JOptionPane.YES_NO_OPTION) 875 + .choose(); 871 876 872 877 if (choice == JOptionPane.YES_OPTION) 873 878 return crashMap; ··· 894 899 return baseMap; 895 900 } 896 901 897 - gui.notify_OpenDialog(); 898 - int choice = SwingUtils.showFramedConfirmDialog(null, 899 - "Found backup data for " + baseMap.getName() + ", would you like to load it instead?", "Backup Recovery", 900 - JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE); 901 - gui.notify_CloseDialog(); 902 + int choice = SwingUtils.getConfirmDialog() 903 + .setCounter(gui.getDialogCounter()) 904 + .setTitle("Backup Recovery") 905 + .setMessage("Found backup data for " + baseMap.getName(), "Would you like to load it instead?") 906 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 907 + .setOptionsType(JOptionPane.YES_NO_OPTION) 908 + .choose(); 902 909 903 910 if (choice == JOptionPane.YES_OPTION) 904 911 return backupMap; ··· 931 938 Map selectedMap = null; 932 939 933 940 while (true) { 934 - int choice = SwingUtils.showFramedOptionDialog(null, 935 - "Which map would you like to open?", "Choose Map", 936 - JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE, 937 - null, options, "Browse Maps"); 941 + int choice = SwingUtils.getOptionDialog() 942 + .setTitle("Choose Map") 943 + .setMessage("Which map would you like to open?") 944 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 945 + .setOptionsType(JOptionPane.YES_NO_OPTION) 946 + .setOptions(options) 947 + .setDefault("Browse Maps") 948 + .choose(); 938 949 939 950 if (choice == JOptionPane.CLOSED_OPTION) { 940 951 selectedMap = null; ··· 1130 1141 if (!configFile.exists()) { 1131 1142 Config cfg = makeNewConfig(configFile); 1132 1143 if (cfg == null) { 1133 - SwingUtils.showFramedMessageDialog(null, 1134 - "Failed to create new config: \n" + configFile.getAbsolutePath(), 1135 - "Create Config Failed", 1136 - JOptionPane.ERROR_MESSAGE); 1144 + SwingUtils.getErrorDialog() 1145 + .setTitle("Create Config Failed") 1146 + .setMessage("Failed to create new config:", configFile.getAbsolutePath()) 1147 + .show(); 1137 1148 return null; 1138 1149 } 1139 1150 ··· 1146 1157 cfg.readConfig(); 1147 1158 } 1148 1159 catch (IOException e) { 1149 - SwingUtils.showFramedMessageDialog(null, 1150 - "IOException occured while reading config: \n" + configFile.getAbsolutePath(), 1151 - "Load Config Failed", 1152 - JOptionPane.ERROR_MESSAGE); 1160 + SwingUtils.getErrorDialog() 1161 + .setTitle("Load Config Failed") 1162 + .setMessage("IOException occured while reading config:", configFile.getAbsolutePath()) 1163 + .show(); 1153 1164 return null; 1154 1165 } 1155 1166 return cfg; ··· 1420 1431 } 1421 1432 1422 1433 public EditorMode getEditorMode() 1423 - { return editorMode; } 1434 + { 1435 + return editorMode; 1436 + } 1424 1437 1425 1438 public Selection<?> getSelectionForCurrentMode() 1426 1439 { ··· 1441 1454 } 1442 1455 1443 1456 public List<EditorObject> getEditorObjects() 1444 - { return editorObjects; } 1457 + { 1458 + return editorObjects; 1459 + } 1445 1460 1446 1461 public void addEditorObject(EditorObject obj) 1447 1462 { ··· 1454 1469 } 1455 1470 1456 1471 public long getFrame() 1457 - { return frameCounter; } 1472 + { 1473 + return frameCounter; 1474 + } 1458 1475 1459 1476 public double getDeltaTime() 1460 - { return deltaTime; } 1477 + { 1478 + return deltaTime; 1479 + } 1461 1480 1462 1481 public double getTotalTime() 1463 - { return time; } 1482 + { 1483 + return time; 1484 + } 1464 1485 1465 1486 /** 1466 1487 * These methods allow the GUI to submit events to the editor. ··· 1517 1538 Logger.log("Successfully compiled " + shapeMap.getName() + "_shape"); 1518 1539 } 1519 1540 catch (BuildException be) { 1520 - SwingUtilities.invokeLater(() -> { 1521 - SwingUtils.showFramedMessageDialog(gui, be.getMessage(), 1522 - "Geometry Build Failed", JOptionPane.ERROR_MESSAGE, Environment.ICON_ERROR); 1523 - }); 1541 + SwingUtils.getErrorDialog() 1542 + .setParent(gui) 1543 + .setTitle("Shape Build Failed") 1544 + .setMessage(be.getMessage()) 1545 + .showLater(); 1524 1546 } 1525 1547 catch (IOException ioe) { 1526 1548 Logger.log("Build failed: IOException. Check log for more information.", Priority.ERROR); ··· 1535 1557 Logger.log("Successfully compiled " + hitMap.getName() + "_hit"); 1536 1558 } 1537 1559 catch (BuildException be) { 1538 - SwingUtilities.invokeLater(() -> { 1539 - SwingUtils.showFramedMessageDialog(gui, be.getMessage(), 1540 - "Collision Build Failed", JOptionPane.ERROR_MESSAGE, Environment.ICON_ERROR); 1541 - }); 1560 + SwingUtils.getErrorDialog() 1561 + .setParent(gui) 1562 + .setTitle("Collision Build Failed") 1563 + .setMessage(be.getMessage()) 1564 + .showLater(); 1542 1565 } 1543 1566 catch (IOException ioe) { 1544 1567 Logger.log("Build failed: IOException. Check log for more information.", Priority.ERROR); ··· 1705 1728 List<Model> models = selectionManager.getSelectedObjects(Model.class); 1706 1729 if (models.size() > 0) { 1707 1730 SwingUtilities.invokeLater(() -> { 1708 - 1709 1731 JComboBox<RenderMode> selectionBox = new JComboBox<>(RenderMode.getEditorModes()); 1710 1732 selectionBox.setSelectedItem(models.get(models.size() - 1).renderMode.get()); 1711 - gui.notify_OpenDialog(); 1712 - int choice = SwingUtils.showFramedConfirmDialog(gui, selectionBox, "Set Render Mode", 1713 - JOptionPane.OK_CANCEL_OPTION, 1714 - JOptionPane.PLAIN_MESSAGE); 1715 - gui.notify_CloseDialog(); 1733 + 1734 + int choice = SwingUtils.getConfirmDialog() 1735 + .setParent(gui) 1736 + .setCounter(gui.getDialogCounter()) 1737 + .setTitle("Set Render Mode") 1738 + .setMessage(selectionBox) 1739 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1740 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 1741 + .choose(); 1742 + 1716 1743 RenderMode selectedMode = (RenderMode) selectionBox.getSelectedItem(); 1717 1744 1718 1745 if (choice == JOptionPane.YES_OPTION && selectedMode != null) { ··· 3243 3270 } 3244 3271 3245 3272 public boolean isPlayInEditorMode() 3246 - { return isPlayInEditorMode; } 3273 + { 3274 + return isPlayInEditorMode; 3275 + } 3247 3276 3248 3277 public PerspCameraMode getCameraMode() 3249 - { return perspCameraMode; } 3278 + { 3279 + return perspCameraMode; 3280 + } 3250 3281 3251 3282 public CameraController getCameraController() 3252 3283 { ··· 3667 3698 loadedTextures = TextureManager.load(map.texName); 3668 3699 3669 3700 while (!loadedTextures) { 3670 - int choice = SwingUtils.showFramedConfirmDialog(gui, 3671 - "Could not open texture archive \"" + map.texName + "\", select a different one?", 3672 - "Missing Texture Archive", 3673 - JOptionPane.YES_NO_OPTION); 3701 + int choice = SwingUtils.getConfirmDialog() 3702 + .setParent(gui) 3703 + .setTitle("Missing Texture Archive") 3704 + .setMessage("Could not open texture archive \"" + map.texName + "\", select a different one?") 3705 + .setOptionsType(JOptionPane.YES_NO_OPTION) 3706 + .choose(); 3674 3707 3675 3708 if (choice == JOptionPane.YES_OPTION) { 3676 3709 File texFile = SelectTexDialog.showPrompt(); ··· 3893 3926 } 3894 3927 3895 3928 public Map getGeometryMap() 3896 - { return shapeOverride == null ? map : shapeOverride; } 3929 + { 3930 + return shapeOverride == null ? map : shapeOverride; 3931 + } 3897 3932 3898 3933 public Map getCollisionMap() 3899 - { return hitOverride == null ? map : hitOverride; } 3934 + { 3935 + return hitOverride == null ? map : hitOverride; 3936 + } 3900 3937 3901 3938 private void openMap(Map newMap, boolean thumbnailMode) 3902 3939 { ··· 4092 4129 } 4093 4130 4094 4131 public Vector3f getCursorPosition() 4095 - { return cursor3D != null ? cursor3D.getPosition() : new Vector3f(); } 4132 + { 4133 + return cursor3D != null ? cursor3D.getPosition() : new Vector3f(); 4134 + } 4096 4135 4097 4136 private void findObject() 4098 4137 { ··· 4641 4680 } 4642 4681 4643 4682 public float getDefaultUVScale() 4644 - { return uvScale; } 4683 + { 4684 + return uvScale; 4685 + } 4645 4686 4646 4687 public float getNormalsLength() 4647 - { return normalsLength; } 4688 + { 4689 + return normalsLength; 4690 + } 4648 4691 4649 4692 public double getRotationSnap() 4650 - { return rotationSnapIncrement; } 4693 + { 4694 + return rotationSnapIncrement; 4695 + } 4651 4696 4652 4697 public boolean debugModeEnabled() 4653 4698 { ··· 4662 4707 public void displayStackTrace(Throwable t, String errorMessage) 4663 4708 { 4664 4709 SwingUtilities.invokeLater(() -> { 4665 - gui.notify_OpenDialog(); 4666 4710 Toolkit.getDefaultToolkit().beep(); 4667 4711 Logger.logError(errorMessage); 4712 + 4713 + gui.getDialogCounter().increment(); 4668 4714 StarRodMain.displayStackTrace(t); 4669 - gui.notify_CloseDialog(); 4715 + gui.getDialogCounter().decrement(); 4670 4716 }); 4671 4717 } 4672 4718
+80 -81
src/main/java/game/map/editor/common/BaseEditor.java
··· 44 44 import app.StarRodException; 45 45 import app.StarRodMain; 46 46 import app.SwingUtils; 47 + import app.SwingUtils.DialogBuilder; 48 + import app.SwingUtils.OpenDialogCounter; 47 49 import app.config.Config; 48 50 import app.config.Options; 49 51 import app.config.Options.Scope; ··· 94 96 // editor state 95 97 protected volatile boolean modified = false; 96 98 private volatile boolean closeRequested = false; 97 - private volatile int openDialogs = 0; 99 + private volatile OpenDialogCounter openDialogs = new OpenDialogCounter(); 98 100 99 101 protected boolean glWindowGrabsMouse; 100 102 protected boolean glWindowHaltsForDialogs; ··· 209 211 time = t0 / 1e9; 210 212 211 213 // gl canvas acquires focus on mouseover 212 - if (glWindowGrabsMouse && !glCanvas.hasFocus() && mouse.hasLocation() && openDialogs == 0) { 214 + if (glWindowGrabsMouse && !glCanvas.hasFocus() && mouse.hasLocation() && openDialogs.isZero()) { 213 215 java.awt.EventQueue.invokeLater(() -> { 214 216 glCanvas.requestFocusInWindow(); 215 217 }); ··· 350 352 @Override 351 353 public void windowClosing(WindowEvent e) 352 354 { 353 - openDialogs++; 355 + openDialogs.increment(); 354 356 closeRequested = !modified || promptForSave(); 355 357 if (!closeRequested) 356 - openDialogs--; 358 + openDialogs.decrement(); 357 359 } 358 360 }); 359 361 ··· 418 420 } 419 421 420 422 if (!success) { 421 - openDialogs++; 422 - String[] options = { "Copy to Clipboard" }; 423 - int selection = SwingUtils.showFramedOptionDialog(null, 424 - logScrollPane, 425 - "Editor Log", 426 - JOptionPane.YES_NO_CANCEL_OPTION, 427 - JOptionPane.PLAIN_MESSAGE, 428 - Environment.ICON_DEFAULT, 429 - options, 430 - options[0]); 431 - openDialogs--; 423 + openDialogs.increment(); 424 + int choice = SwingUtils.getOptionDialog() 425 + .setTitle("Editor Log") 426 + .setMessage(logScrollPane) 427 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 428 + .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION) 429 + .setIcon(Environment.ICON_DEFAULT) 430 + .setOptions("Copy to Clipboard") 431 + .choose(); 432 + openDialogs.decrement(); 432 433 433 - if (selection == 0) { 434 + if (choice == 0) { 434 435 StringSelection stringSelection = new StringSelection(logTextArea.getText()); 435 436 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); 436 437 cb.setContents(stringSelection, null); ··· 444 445 if (!configFile.exists()) { 445 446 Config cfg = makeNewConfig(scope, configFile); 446 447 if (cfg == null) { 447 - SwingUtils.showFramedMessageDialog(null, 448 - "Failed to create new config: \n" + configFile.getAbsolutePath(), 449 - "Create Config Failed", 450 - JOptionPane.ERROR_MESSAGE); 448 + SwingUtils.getErrorDialog() 449 + .setTitle("Create Config Failed") 450 + .setMessage("Failed to create new config:", configFile.getAbsolutePath()) 451 + .show(); 451 452 return null; 452 453 } 453 454 ··· 460 461 cfg.readConfig(); 461 462 } 462 463 catch (IOException e) { 463 - SwingUtils.showFramedMessageDialog(null, 464 - "IOException occured while reading config: \n" + configFile.getAbsolutePath(), 465 - "Load Config Failed", 466 - JOptionPane.ERROR_MESSAGE); 464 + SwingUtils.getErrorDialog() 465 + .setTitle("Load Config Failed") 466 + .setMessage("IOException occured while reading config:", configFile.getAbsolutePath()) 467 + .show(); 467 468 return null; 468 469 } 469 470 return cfg; ··· 488 489 } 489 490 490 491 protected Config getConfig() 491 - { return config; } 492 + { 493 + return config; 494 + } 492 495 493 496 private final boolean promptForSave() 494 497 { 495 - openDialogs++; 496 - int response = SwingUtils.showFramedConfirmDialog(frame, 497 - String.format("Unsaved changes will be lost! %nWould you like to save now?"), 498 - "Warning", JOptionPane.YES_NO_CANCEL_OPTION); 499 - openDialogs--; 498 + openDialogs.increment(); 500 499 501 - switch (response) { 500 + int choice = SwingUtils.getConfirmDialog() 501 + .setTitle("Warning") 502 + .setMessage("Unsaved changes will be lost!", "Would you like to save now?") 503 + .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION) 504 + .choose(); 505 + 506 + openDialogs.decrement(); 507 + 508 + switch (choice) { 502 509 case JOptionPane.YES_OPTION: 503 510 saveChanges(); 504 511 break; ··· 512 519 return true; 513 520 } 514 521 515 - protected final void showMessageDialog(Object message, String title) 522 + protected final DialogBuilder getMessageDialog(String title, Object message) 516 523 { 517 - openDialogs++; 518 - SwingUtils.showFramedMessageDialog(frame, 519 - message, title, 520 - JOptionPane.PLAIN_MESSAGE); 521 - openDialogs--; 524 + return SwingUtils.getMessageDialog() 525 + .setParent(frame) 526 + .setTitle(title) 527 + .setMessage(message) 528 + .setCounter(openDialogs); 522 529 } 523 530 524 - protected final int showConfirmDialog(Object message, String title) 525 - { 526 - openDialogs++; 527 - int userAction = SwingUtils.showFramedConfirmDialog(frame, 528 - message, title, 529 - JOptionPane.OK_CANCEL_OPTION, 530 - JOptionPane.PLAIN_MESSAGE); 531 - openDialogs--; 532 - return userAction; 533 - } 534 - 535 - protected final int showConfirmDialog(Object message, String title, int optionType) 531 + protected final DialogBuilder getConfirmDialog(String title, Object message) 536 532 { 537 - openDialogs++; 538 - int userAction = SwingUtils.showFramedConfirmDialog(frame, 539 - message, title, optionType, 540 - JOptionPane.PLAIN_MESSAGE); 541 - openDialogs--; 542 - return userAction; 533 + return SwingUtils.getConfirmDialog() 534 + .setParent(frame) 535 + .setTitle(title) 536 + .setMessage(message) 537 + .setCounter(openDialogs) 538 + .setMessageType(JOptionPane.PLAIN_MESSAGE); 543 539 } 544 540 545 - protected final int showOptionDialog(Object message, String title, Object[] options) 541 + protected final DialogBuilder getOptionDialog(String title, Object message) 546 542 { 547 - openDialogs++; 548 - int userAction = SwingUtils.showFramedOptionDialog(frame, 549 - message, title, 550 - JOptionPane.PLAIN_MESSAGE, 551 - JOptionPane.PLAIN_MESSAGE, 552 - null, 553 - options, 554 - options[0]); 555 - openDialogs--; 556 - return userAction; 543 + return SwingUtils.getOptionDialog() 544 + .setParent(frame) 545 + .setTitle(title) 546 + .setMessage(message) 547 + .setCounter(openDialogs) 548 + .setMessageType(JOptionPane.PLAIN_MESSAGE); 557 549 } 558 550 559 551 /** ··· 588 580 */ 589 581 590 582 public final long getFrameCount() 591 - { return frameCounter; } 583 + { 584 + return frameCounter; 585 + } 592 586 593 587 public final double getTime() 594 - { return time; } 588 + { 589 + return time; 590 + } 595 591 596 592 public final double getDeltaTime() 597 - { return deltaTime; } 593 + { 594 + return deltaTime; 595 + } 598 596 599 597 public final int glCanvasWidth() 600 598 { ··· 613 611 614 612 protected final void showErrorDialog(String title, String msg) 615 613 { 616 - SwingUtilities.invokeLater(() -> { 617 - SwingUtils.showFramedMessageDialog(frame, 618 - msg, title, 619 - JOptionPane.ERROR_MESSAGE, 620 - Environment.ICON_ERROR); 621 - }); 614 + SwingUtils.getErrorDialog() 615 + .setParent(frame) 616 + .setTitle(title) 617 + .setMessage(msg) 618 + .showLater(); 622 619 } 623 620 624 621 protected final void showStackTrace(Throwable t) 625 622 { 626 - openDialogs++; 623 + openDialogs.increment(); 627 624 StarRodMain.displayStackTrace(t); 628 - openDialogs--; 625 + openDialogs.decrement(); 629 626 } 630 627 631 628 protected final JFrame getFrame() 632 - { return frame; } 629 + { 630 + return frame; 631 + } 633 632 634 633 public boolean areDialogsOpen() 635 634 { 636 - return openDialogs > 0; 635 + return !openDialogs.isZero(); 637 636 } 638 637 639 638 public final void incrementDialogsOpen() 640 639 { 641 - openDialogs++; 640 + openDialogs.increment(); 642 641 } 643 642 644 643 public final void decrementDialogsOpen() 645 644 { 646 - openDialogs--; 645 + openDialogs.decrement(); 647 646 } 648 647 649 648 /**
+2 -2
src/main/java/game/map/editor/ui/ShorcutListPanel.java src/main/java/game/map/editor/ui/MapShortcutsPanel.java
··· 8 8 9 9 import net.miginfocom.swing.MigLayout; 10 10 11 - public class ShorcutListPanel extends JPanel 11 + public class MapShortcutsPanel extends JPanel 12 12 { 13 - public ShorcutListPanel() 13 + public MapShortcutsPanel() 14 14 { 15 15 setLayout(new MigLayout("fill")); 16 16
+117 -82
src/main/java/game/map/editor/ui/SwingGUI.java
··· 50 50 51 51 import app.Environment; 52 52 import app.SwingUtils; 53 + import app.SwingUtils.OpenDialogCounter; 53 54 import app.config.PreferencesPanel; 54 55 import assets.AssetHandle; 55 56 import assets.AssetManager; ··· 120 121 // for different EditorStates: modify, texture, and vertex paint. 121 122 122 123 private volatile boolean closeRequested = false; 123 - private volatile int openDialogCount = 0; 124 + private volatile OpenDialogCounter openDialogCount = new OpenDialogCounter(); 124 125 private volatile List<JPopupMenu> popups = new LinkedList<>(); 125 126 126 127 private HashMap<String, GuiCommand> commandMap; ··· 214 215 @Override 215 216 public void windowClosing(WindowEvent e) 216 217 { 217 - openDialogCount++; 218 + openDialogCount.increment(); 218 219 closeRequested = (!editor.map.modified || promptForSave()) && (!ProjectDatabase.SpriteShading.modified || promptSaveShading()); 219 220 if (!closeRequested) 220 - openDialogCount--; 221 + openDialogCount.decrement(); 222 + ; 221 223 } 222 224 }); 223 225 ··· 277 279 } 278 280 279 281 if (!success) { 280 - editor.gui.notify_OpenDialog(); 281 - String[] options = { "Copy to Clipboard" }; 282 - int selection = SwingUtils.showFramedOptionDialog(null, 283 - logScrollPane, 284 - "Editor Log", 285 - JOptionPane.YES_NO_CANCEL_OPTION, 286 - JOptionPane.PLAIN_MESSAGE, 287 - Environment.ICON_DEFAULT, 288 - options, 289 - options[0]); 290 - editor.gui.notify_CloseDialog(); 282 + int choice = SwingUtils.getOptionDialog() 283 + .setParent(this) 284 + .setCounter(openDialogCount) 285 + .setTitle("Editor Log") 286 + .setMessage(logScrollPane) 287 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 288 + .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION) 289 + .setIcon(Environment.ICON_DEFAULT) 290 + .setOptions("Copy to Clipboard") 291 + .choose(); 291 292 292 - if (selection == 0) { 293 + if (choice == 0) { 293 294 StringSelection stringSelection = new StringSelection(logTextArea.getText()); 294 295 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); 295 296 cb.setContents(stringSelection, null); ··· 381 382 } 382 383 383 384 public boolean isModalDialogOpen() 384 - { return openDialogCount > 0; } 385 + { 386 + return !openDialogCount.isZero(); 387 + } 388 + 389 + public OpenDialogCounter getDialogCounter() 390 + { 391 + return openDialogCount; 392 + } 385 393 386 394 public void registerPopupMenu(JPopupMenu menu) 387 395 { ··· 397 405 } 398 406 399 407 public boolean isCloseRequested() 400 - { return closeRequested; } 408 + { 409 + return closeRequested; 410 + } 401 411 402 412 public boolean promptForSave() 403 413 { 404 - openDialogCount++; 405 - int response = SwingUtils.showFramedConfirmDialog(null, 406 - "Unsaved changes will be lost!\r\nWould you like to save now?\r\n", 407 - "Warning", JOptionPane.YES_NO_CANCEL_OPTION); 408 - openDialogCount--; 414 + int choice = SwingUtils.getConfirmDialog() 415 + .setParent(this) 416 + .setCounter(openDialogCount) 417 + .setTitle("Warning") 418 + .setMessage("Unsaved changes will be lost!", "Would you like to save now?") 419 + .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION) 420 + .choose(); 409 421 410 - switch (response) { 422 + switch (choice) { 411 423 case JOptionPane.YES_OPTION: 412 424 editor.action_SaveMap(); 413 425 case JOptionPane.NO_OPTION: ··· 422 434 423 435 private boolean promptSaveShading() 424 436 { 425 - openDialogCount++; 426 - int response = SwingUtils.showFramedConfirmDialog(null, 427 - "Sprite shading data was changed!\r\nWould you like to save now?\r\n", 428 - "Warning", JOptionPane.YES_NO_CANCEL_OPTION); 429 - openDialogCount--; 437 + int choice = SwingUtils.getConfirmDialog() 438 + .setParent(this) 439 + .setCounter(openDialogCount) 440 + .setTitle("Warning") 441 + .setMessage("Sprite shading data was changed!", "Would you like to save now?") 442 + .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION) 443 + .choose(); 430 444 431 - switch (response) { 445 + switch (choice) { 432 446 case JOptionPane.YES_OPTION: 433 447 editor.action_SaveShading(); 434 448 case JOptionPane.NO_OPTION: ··· 1282 1296 private void prompt_OpenMap() 1283 1297 { 1284 1298 if (!editor.map.modified || promptForSave()) { 1285 - openDialogCount++; 1299 + openDialogCount.increment(); 1286 1300 File mapFile = SelectMapDialog.showPrompt(); 1287 - openDialogCount--; 1301 + openDialogCount.decrement(); 1288 1302 1289 1303 if (mapFile != null) { 1290 1304 editor.doNextFrame(() -> { ··· 1308 1322 1309 1323 private void prompt_SaveMapAs() 1310 1324 { 1311 - openDialogCount++; 1325 + openDialogCount.increment(); 1312 1326 File newMapFile = SelectMapDialog.requestNewMapFile(); 1313 - openDialogCount--; 1327 + openDialogCount.decrement(); 1314 1328 1315 1329 if (newMapFile != null) { 1316 1330 editor.doNextFrame(() -> { ··· 1321 1335 1322 1336 private void prompt_LoadTextureArchive() 1323 1337 { 1324 - openDialogCount++; 1338 + openDialogCount.increment(); 1325 1339 File texFile = SelectTexDialog.showPrompt(); 1326 - openDialogCount--; 1340 + openDialogCount.decrement(); 1327 1341 1328 1342 if (texFile != null) { 1329 1343 String texName = FilenameUtils.getBaseName(texFile.getName()); ··· 1336 1350 1337 1351 private void prompt_ChangeBackground() 1338 1352 { 1339 - openDialogCount++; 1353 + openDialogCount.increment(); 1340 1354 File bgFile = SelectBackgroundDialog.showPrompt(); 1341 - openDialogCount--; 1355 + openDialogCount.decrement(); 1342 1356 1343 1357 if (bgFile != null) { 1344 1358 editor.doNextFrame(() -> { ··· 1356 1370 1357 1371 public void prompt_ImportObjects(MapObjectNode<? extends MapObject> node) 1358 1372 { 1359 - openDialogCount++; 1373 + openDialogCount.increment(); 1360 1374 if (importFileChooser.prompt() == ChooseDialogResult.APPROVE) { 1361 1375 File f = importFileChooser.getSelectedFile(); 1362 1376 editor.map.importFromFile(f, node); 1363 1377 } 1364 - openDialogCount--; 1378 + openDialogCount.decrement(); 1365 1379 } 1366 1380 1367 1381 private void prompt_ExportObjects() ··· 1371 1385 if (selection.isEmpty()) 1372 1386 return; 1373 1387 1374 - openDialogCount++; 1388 + openDialogCount.increment(); 1375 1389 if (exportFileChooser.prompt() == ChooseDialogResult.APPROVE) { 1376 1390 File f = exportFileChooser.getSelectedFile(); 1377 1391 editor.map.exportToFile(f); 1378 1392 } 1379 - openDialogCount--; 1393 + openDialogCount.decrement(); 1380 1394 } 1381 1395 1382 1396 public void prompt_EditTexPanner(TexturePanner panner) ··· 1417 1431 1418 1432 transformSelectionPanel.setSelection(selection); 1419 1433 1420 - openDialogCount++; 1421 - int userAction = SwingUtils.showFramedConfirmDialog(this, transformSelectionPanel, "Transform Selection", JOptionPane.PLAIN_MESSAGE); 1422 - openDialogCount--; 1434 + int choice = SwingUtils.getConfirmDialog() 1435 + .setParent(this) 1436 + .setCounter(openDialogCount) 1437 + .setTitle("Transform Selection") 1438 + .setMessage(transformSelectionPanel) 1439 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1440 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 1441 + .choose(); 1423 1442 1424 - if (userAction == JOptionPane.YES_OPTION) { 1443 + if (choice == JOptionPane.YES_OPTION) { 1425 1444 final TransformMatrix m = transformSelectionPanel.createTransformMatrix(); 1426 1445 if (m != null) { 1427 1446 editor.doNextFrame(() -> { ··· 1435 1454 { 1436 1455 SetPositionPanel panel = new SetPositionPanel(x, y, z); 1437 1456 1438 - openDialogCount++; 1439 - int userAction = SwingUtils.showFramedConfirmDialog(this, panel, "Set Position", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 1440 - openDialogCount--; 1457 + int choice = SwingUtils.getConfirmDialog() 1458 + .setParent(this) 1459 + .setCounter(openDialogCount) 1460 + .setTitle("Set Position") 1461 + .setMessage(panel) 1462 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1463 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 1464 + .choose(); 1441 1465 1442 - if (userAction == JOptionPane.YES_OPTION) { 1466 + if (choice == JOptionPane.YES_OPTION) { 1443 1467 return panel.getVector(); 1444 1468 } 1445 1469 else { ··· 1564 1588 1565 1589 public void prompt_CreateMarker(MapObjectNode<Marker> parent) 1566 1590 { 1567 - openDialogCount++; 1568 - int userAction = SwingUtils.showFramedConfirmDialog(this, MarkerOptionsPanel.getInstance(), "Create Marker", 1569 - JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 1570 - openDialogCount--; 1591 + int choice = SwingUtils.getConfirmDialog() 1592 + .setParent(this) 1593 + .setCounter(openDialogCount) 1594 + .setTitle("Create Marker") 1595 + .setMessage(MarkerOptionsPanel.getInstance()) 1596 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1597 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 1598 + .choose(); 1571 1599 1572 - if (userAction == JOptionPane.OK_OPTION) { 1600 + if (choice == JOptionPane.OK_OPTION) { 1573 1601 editor.doNextFrame(() -> { 1574 1602 editor.action_CreateMarker( 1575 1603 MarkerOptionsPanel.getMarkerName(), ··· 1581 1609 1582 1610 private void prompt_GenerateUV() 1583 1611 { 1584 - openDialogCount++; 1585 - int userAction = SwingUtils.showFramedConfirmDialog(this, uvOptionsPanel, "UV Projection Options", 1586 - JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 1587 - openDialogCount--; 1612 + int choice = SwingUtils.getConfirmDialog() 1613 + .setParent(this) 1614 + .setCounter(openDialogCount) 1615 + .setTitle("UV Projection Options") 1616 + .setMessage(uvOptionsPanel) 1617 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1618 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 1619 + .choose(); 1588 1620 1589 - if (userAction == JOptionPane.OK_OPTION) { 1621 + if (choice == JOptionPane.OK_OPTION) { 1590 1622 final UVGenerator gen = uvOptionsPanel.getUVGenerator(); 1591 1623 editor.doNextFrame(() -> { 1592 1624 editor.action_GenerateUVs(gen); ··· 1596 1628 1597 1629 public void prompt_ConfirmDialog(Object message, String title, Runnable action) 1598 1630 { 1599 - openDialogCount++; 1600 - int userAction = SwingUtils.showFramedConfirmDialog(this, message, title, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 1601 - openDialogCount--; 1631 + int choice = SwingUtils.getConfirmDialog() 1632 + .setParent(this) 1633 + .setCounter(openDialogCount) 1634 + .setTitle(title) 1635 + .setMessage(message) 1636 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1637 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 1638 + .choose(); 1602 1639 1603 - if (userAction == JOptionPane.OK_OPTION) { 1640 + if (choice == JOptionPane.OK_OPTION) { 1604 1641 action.run(); 1605 1642 } 1606 1643 } 1607 1644 1608 1645 private void prompt_ChooseColor() 1609 1646 { 1610 - openDialogCount++; 1647 + openDialogCount.increment(); 1611 1648 Color c = null; 1612 1649 c = JColorChooser.showDialog(this, "Choose Color", c); 1613 - openDialogCount--; 1650 + openDialogCount.decrement(); 1614 1651 1615 1652 if (c != null) { 1616 1653 PaintManager.setSelectedColor(c); ··· 1618 1655 } 1619 1656 } 1620 1657 1621 - public void notify_OpenDialog() 1622 - { 1623 - openDialogCount++; 1624 - } 1625 - 1626 - public void notify_CloseDialog() 1627 - { 1628 - openDialogCount--; 1629 - } 1630 - 1631 1658 private void showControls() 1632 1659 { 1633 - openDialogCount++; 1634 - SwingUtils.showFramedMessageDialog(this, new ShorcutListPanel(), "Controls and Shortcuts", JOptionPane.PLAIN_MESSAGE); 1635 - openDialogCount--; 1660 + SwingUtils.getMessageDialog() 1661 + .setParent(this) 1662 + .setCounter(openDialogCount) 1663 + .setTitle("Controls and Shortcuts") 1664 + .setMessage(new MapShortcutsPanel()) 1665 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1666 + .show(); 1636 1667 } 1637 1668 1638 1669 private void showPreferences() ··· 1643 1674 PreferencesPanel preferences = new PreferencesPanel(); 1644 1675 preferences.setValues(editor.editorConfig); 1645 1676 1646 - openDialogCount++; 1647 - int choice = SwingUtils.showFramedConfirmDialog(this, preferences, "Editor Preferences", JOptionPane.OK_CANCEL_OPTION, 1648 - JOptionPane.PLAIN_MESSAGE); 1649 - openDialogCount--; 1677 + int choice = SwingUtils.getConfirmDialog() 1678 + .setParent(this) 1679 + .setCounter(openDialogCount) 1680 + .setTitle("Editor Preferences") 1681 + .setMessage(preferences) 1682 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1683 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 1684 + .choose(); 1650 1685 1651 1686 if (choice == JOptionPane.OK_OPTION) { 1652 1687 preferences.getValues(editor.editorConfig);
+13 -6
src/main/java/game/map/editor/ui/dialogs/SaveFileChooser.java
··· 28 28 } 29 29 30 30 public void setCurrentDirectory(File dir) 31 - { currentDirectory = dir; } 31 + { 32 + currentDirectory = dir; 33 + } 32 34 33 35 public ChooseDialogResult prompt(File dir) 34 36 { ··· 66 68 } 67 69 68 70 public File getSelectedFile() 69 - { return selected; } 71 + { 72 + return selected; 73 + } 70 74 71 75 public boolean checkForOverwrite(File f) 72 76 { 73 77 if (!f.exists()) 74 78 return true; 75 - int result = SwingUtils.showFramedConfirmDialog(null, 76 - "Overwrite existing file?", "File Already Exists", 77 - JOptionPane.YES_NO_CANCEL_OPTION); 78 - switch (result) { 79 + 80 + int choice = SwingUtils.getConfirmDialog() 81 + .setTitle("File Already Exists") 82 + .setMessage("Overwrite existing file?") 83 + .choose(); 84 + 85 + switch (choice) { 79 86 case JOptionPane.YES_OPTION: 80 87 return true; 81 88 case JOptionPane.CANCEL_OPTION:
+2 -2
src/main/java/game/map/scripts/LightingPanel.java
··· 103 103 104 104 JButton chooseColorButton = new JButton("Choose"); 105 105 chooseColorButton.addActionListener((e) -> { 106 - SwingGUI.instance().notify_OpenDialog(); 106 + SwingGUI.instance().getDialogCounter().increment(); 107 107 Color c = new Color(lightSet.ambient[0], lightSet.ambient[1], lightSet.ambient[2]); 108 108 c = JColorChooser.showDialog(null, "Choose Ambient Color", c); 109 - SwingGUI.instance().notify_CloseDialog(); 109 + SwingGUI.instance().getDialogCounter().decrement(); 110 110 111 111 if (c != null) 112 112 MapEditor.execute(new SetAmbientColor(lightSet, c.getRed(), c.getGreen(), c.getBlue()));
+7 -6
src/main/java/game/map/scripts/ShadingPanel.java
··· 103 103 104 104 boolean shouldDelete = true; 105 105 if (selected.vanilla) { 106 - SwingGUI.instance().notify_OpenDialog(); 107 - int response = SwingUtils.showFramedConfirmDialog(SwingGUI.instance(), 108 - "Selected profile is vanilla.\r\nAre you sure you want to delete it?\r\n", 109 - "Warning", JOptionPane.YES_NO_CANCEL_OPTION); 110 - SwingGUI.instance().notify_CloseDialog(); 106 + int choice = SwingUtils.getConfirmDialog() 107 + .setParent(SwingGUI.instance()) 108 + .setCounter(SwingGUI.instance().getDialogCounter()) 109 + .setTitle("Warning") 110 + .setMessage("Selected profile is vanilla.", "Are you sure you want to delete it?") 111 + .choose(); 111 112 112 - shouldDelete = (response == JOptionPane.YES_OPTION); 113 + shouldDelete = (choice == JOptionPane.YES_OPTION); 113 114 } 114 115 115 116 if (shouldDelete) {
+4 -4
src/main/java/game/map/scripts/ShadingProfileInfoPanel.java
··· 90 90 if (getData() == null) 91 91 return; 92 92 93 - SwingGUI.instance().notify_OpenDialog(); 93 + SwingGUI.instance().getDialogCounter().increment(); 94 94 Color c = new Color(getData().color.get()); 95 95 c = JColorChooser.showDialog(null, "Choose Ambient Color", c); 96 - SwingGUI.instance().notify_CloseDialog(); 96 + SwingGUI.instance().getDialogCounter().decrement(); 97 97 98 98 if (c != null) 99 99 MapEditor.execute(new SetAmbientColor(getData(), c.getRGB())); ··· 119 119 sourceList.addListSelectionListener((e) -> { 120 120 if(getData() == null) 121 121 return; 122 - 122 + 123 123 MapEditor.instance().selectionManager.deselectLightsFromGUI(getData().sources); 124 124 if(sourceList.getSelectedValue() != null) 125 125 MapEditor.instance().selectionManager.selectLightsFromGUI(sourceList.getSelectedValue()); 126 - 126 + 127 127 }); 128 128 */ 129 129
+2 -2
src/main/java/game/map/scripts/ShadingSourceInfoPanel.java
··· 60 60 if (getData() == null) 61 61 return; 62 62 63 - SwingGUI.instance().notify_OpenDialog(); 63 + SwingGUI.instance().getDialogCounter().increment(); 64 64 Color c = new Color(getData().color.get()); 65 65 c = JColorChooser.showDialog(null, "Choose Ambient Color", c); 66 - SwingGUI.instance().notify_CloseDialog(); 66 + SwingGUI.instance().getDialogCounter().decrement(); 67 67 68 68 if (c != null) 69 69 MapEditor.execute(new SetLightColor(getData(), c.getRGB()));
+27 -15
src/main/java/game/map/scripts/generators/foliage/FoliageInfoPanel.java
··· 440 440 SwingGUI gui = MapEditor.instance().gui; 441 441 FoliageModelEditor editorPanel = new FoliageModelEditor(MapEditor.instance().map, folMdl); 442 442 443 - gui.notify_OpenDialog(); 444 - int userAction = SwingUtils.showFramedConfirmDialog(gui, editorPanel, "Edit Foliage Model", 445 - JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 446 - gui.notify_CloseDialog(); 443 + int choice = SwingUtils.getConfirmDialog() 444 + .setParent(gui) 445 + .setCounter(gui.getDialogCounter()) 446 + .setTitle("Edit Foliage Model") 447 + .setMessage(editorPanel) 448 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 449 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 450 + .choose(); 447 451 448 - if (userAction == JOptionPane.OK_OPTION) 452 + if (choice == JOptionPane.OK_OPTION) 449 453 MapEditor.execute(folMdl.modelName.mutator(editorPanel.getValue())); 450 454 } 451 455 ··· 454 458 SwingGUI gui = MapEditor.instance().gui; 455 459 FoliageVectorEditor editorPanel = new FoliageVectorEditor(MapEditor.instance().map, folVec); 456 460 457 - gui.notify_OpenDialog(); 458 - int userAction = SwingUtils.showFramedConfirmDialog(gui, editorPanel, "Edit Foliage Model", 459 - JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 460 - gui.notify_CloseDialog(); 461 + int choice = SwingUtils.getConfirmDialog() 462 + .setParent(gui) 463 + .setCounter(gui.getDialogCounter()) 464 + .setTitle("Edit Foliage Model") 465 + .setMessage(editorPanel) 466 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 467 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 468 + .choose(); 461 469 462 - if (userAction == JOptionPane.OK_OPTION) 470 + if (choice == JOptionPane.OK_OPTION) 463 471 MapEditor.execute(folVec.modelName.mutator(editorPanel.getValue())); 464 472 } 465 473 ··· 468 476 SwingGUI gui = MapEditor.instance().gui; 469 477 FoliageDropEditor editorPanel = new FoliageDropEditor(MapEditor.instance().map, folDrop); 470 478 471 - gui.notify_OpenDialog(); 472 - int userAction = SwingUtils.showFramedConfirmDialog(gui, editorPanel, "Edit Foliage Drop", 473 - JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE); 474 - gui.notify_CloseDialog(); 479 + int choice = SwingUtils.getConfirmDialog() 480 + .setParent(gui) 481 + .setCounter(gui.getDialogCounter()) 482 + .setTitle("Edit Foliage Model") 483 + .setMessage(editorPanel) 484 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 485 + .setOptionsType(JOptionPane.OK_CANCEL_OPTION) 486 + .choose(); 475 487 476 - if (userAction == JOptionPane.OK_OPTION) 488 + if (choice == JOptionPane.OK_OPTION) 477 489 MapEditor.execute(new EditFoliageDrop(folDrop, editorPanel.getEditedDrop())); 478 490 } 479 491 }
+5 -3
src/main/java/game/map/shape/Light.java
··· 107 107 } 108 108 109 109 public LightPanel getPanel() 110 - { return panel; } 110 + { 111 + return panel; 112 + } 111 113 112 114 public static class LightPanel extends JPanel 113 115 { ··· 160 162 161 163 JButton chooseColorButton = new JButton("Choose"); 162 164 chooseColorButton.addActionListener((e) -> { 163 - SwingGUI.instance().notify_OpenDialog(); 165 + SwingGUI.instance().getDialogCounter().increment(); 164 166 Color c = new Color(light.color[0], light.color[1], light.color[2]); 165 167 c = JColorChooser.showDialog(null, "Choose Light Color", c); 166 - SwingGUI.instance().notify_CloseDialog(); 168 + SwingGUI.instance().getDialogCounter().decrement(); 167 169 168 170 if (c != null) 169 171 MapEditor.execute(new SetLightColor(light, c.getRed(), c.getGreen(), c.getBlue()));
+5 -9
src/main/java/game/message/Message.java
··· 9 9 import app.input.Line; 10 10 import app.input.PatchFileParser.PatchUnit; 11 11 import game.message.StringConstants.ControlCharacter; 12 - import game.message.editor.MessageGroup; 12 + import game.message.editor.MessageAsset; 13 13 import util.ui.FilterListable; 14 14 15 15 public class Message implements FilterListable 16 16 { 17 - public final MessageGroup source; 17 + public final MessageAsset source; 18 18 public final PatchUnit unit; 19 19 20 20 public int startLineNum = -1; ··· 38 38 public String name; 39 39 40 40 // loading from asset 41 - public Message(MessageGroup res, PatchUnit unit, int section, int index, String name) 41 + public Message(MessageAsset res, PatchUnit unit, int section, int index, String name) 42 42 { 43 43 this.source = res; 44 44 this.unit = unit; ··· 54 54 } 55 55 56 56 // created in editor 57 - public Message(MessageGroup res, int section, int index, String name) 57 + public Message(MessageAsset res) 58 58 { 59 59 this.source = res; 60 60 this.unit = null; 61 61 62 - this.section = section; 63 - this.index = index; 64 - this.name = name; 65 - 66 - name = "NewString"; 62 + name = "NewMessage"; 67 63 markup = "[END]"; 68 64 previewText = ""; 69 65 }
+18 -21
src/main/java/game/message/StringEncoder.java
··· 26 26 import game.message.StringConstants.StringFunction; 27 27 import game.message.StringConstants.StringStyle; 28 28 import game.message.StringConstants.StringVoice; 29 - import game.message.editor.MessageGroup; 30 - import game.message.editor.StringTokenizer; 31 - import game.message.editor.StringTokenizer.Sequence; 29 + import game.message.editor.MessageAsset; 30 + import game.message.editor.MessageTokenizer; 31 + import game.message.editor.MessageTokenizer.Sequence; 32 32 import util.CaseInsensitiveMap; 33 33 import util.DualHashMap; 34 34 import util.MathUtil; ··· 108 108 addArgU8(name, i); 109 109 } 110 110 111 - public static List<Message> parseMessages(MessageGroup group) throws IOException 111 + public static List<Message> parseMessages(MessageAsset group) throws IOException 112 112 { 113 113 List<Message> messages = new ArrayList<>(); 114 114 ··· 130 130 int index = 0xFFFF; 131 131 String name = ""; 132 132 133 - if (unit.declaration.numTokens() == 2) { 134 - if (!declareLine.getString(1).matches("\\S+")) 135 - throw new InputFileException(declareLine, "String name could not be parsed: %n%s", declareLine.trimmedInput()); 133 + if (unit.declaration.numTokens() == 3) { 134 + if (!declareLine.getString(2).matches("\\(.+\\)")) 135 + throw new InputFileException(declareLine, "String ID could not be parsed: %n%s", declareLine.trimmedInput()); 136 136 137 - name = declareLine.getString(1); 137 + section = declareLine.getHex(1); 138 + name = declareLine.getString(2); 139 + name = name.substring(1, name.length() - 1); 138 140 } 139 141 // LEGACY SUPPORT: #message | #string : section : index : (name) 140 142 else if (unit.declaration.numTokens() == 4) { 141 143 if (!declareLine.getString(3).matches("\\(.+\\)")) 142 144 throw new InputFileException(declareLine, "String name could not be parsed: %n%s", declareLine.trimmedInput()); 143 145 146 + section = declareLine.getHex(1); 147 + index = declareLine.getHex(2); 144 148 name = declareLine.getString(3); 145 149 name = name.substring(1, name.length() - 1); 146 150 } 147 - // LEGACY SUPPORT: #message | #string : section : index | (name) 148 - else if (unit.declaration.numTokens() == 3) { 149 - if (!declareLine.getString(2).matches("\\(.+\\)")) 150 - throw new InputFileException(declareLine, "String ID could not be parsed: %n%s", declareLine.trimmedInput()); 151 - 152 - name = declareLine.getString(2); 153 - name = name.substring(1, name.length() - 1); 151 + else { 152 + throw new InputFileException(declareLine, "String declaration could not be parsed: %n%s", declareLine.trimmedInput()); 154 153 } 155 - else 156 - throw new InputFileException(declareLine, "String declaration could not be parsed: %n%s", declareLine.trimmedInput()); 157 154 158 155 // parse lines 159 156 ··· 204 201 { 205 202 StringEncoder builder = new StringEncoder(); 206 203 builder.vars = vars; 207 - ArrayList<Sequence> sequences = StringTokenizer.tokenize(text); 204 + ArrayList<Sequence> sequences = MessageTokenizer.tokenize(text); 208 205 encode(builder, sequences, false); 209 206 return sequences; 210 207 } ··· 214 211 { 215 212 StringEncoder builder = new StringEncoder(); 216 213 builder.allowFontChange = false; 217 - ArrayList<Sequence> sequences = StringTokenizer.tokenize(text); 214 + ArrayList<Sequence> sequences = MessageTokenizer.tokenize(text); 218 215 encode(builder, sequences, throwsExceptions); 219 216 return getBuffer(sequences, false); 220 217 } ··· 223 220 public static ByteBuffer encode(String text) 224 221 { 225 222 StringEncoder builder = new StringEncoder(); 226 - ArrayList<Sequence> sequences = StringTokenizer.tokenize(text); 223 + ArrayList<Sequence> sequences = MessageTokenizer.tokenize(text); 227 224 encode(builder, sequences, true); 228 225 return getBuffer(sequences, false); 229 226 } ··· 232 229 public static ByteBuffer encodeLines(List<Line> lines) 233 230 { 234 231 StringEncoder builder = new StringEncoder(); 235 - ArrayList<Sequence> sequences = StringTokenizer.tokenize(lines); 232 + ArrayList<Sequence> sequences = MessageTokenizer.tokenize(lines); 236 233 encode(builder, sequences, true); 237 234 return getBuffer(sequences, true); 238 235 }
+29 -12
src/main/java/game/message/editor/AssetListTab.java
··· 3 3 import java.awt.Component; 4 4 import java.io.IOException; 5 5 import java.util.ArrayList; 6 - import java.util.List; 7 6 8 7 import javax.swing.BorderFactory; 9 8 import javax.swing.JButton; ··· 17 16 import app.SwingUtils; 18 17 import assets.AssetHandle; 19 18 import assets.AssetManager; 19 + import game.message.Message; 20 20 import net.miginfocom.swing.MigLayout; 21 21 import util.Logger; 22 22 import util.ui.FilteredListPanel; 23 23 24 24 public class AssetListTab extends JPanel 25 25 { 26 - private FilteredListPanel<MessageGroup> filteredList; 26 + private final FilteredListPanel<MessageAsset> filteredList; 27 + private final ArrayList<MessageAsset> assets; 27 28 28 29 public AssetListTab(MessageEditor editor, MessageListTab listPanel) 29 30 { 31 + assets = new ArrayList<>(); 32 + 30 33 filteredList = new FilteredListPanel<>(new AssetCellRenderer()) { 31 34 @Override 32 - public String getFilterableText(MessageGroup group) 35 + public String getFilterableText(MessageAsset group) 33 36 { 34 37 if (group != null) { 35 38 return FilenameUtils.getBaseName(group.asset.getName()); ··· 40 43 } 41 44 42 45 @Override 43 - public void handleSelection(MessageGroup asset) 46 + public void handleSelection(MessageAsset asset) 44 47 { 45 - listPanel.setStrings((asset == null) ? null : asset.messages); 48 + listPanel.setAsset(asset); 46 49 } 47 50 }; 48 51 ··· 84 87 85 88 public void fullReload() 86 89 { 87 - List<MessageGroup> resources = new ArrayList<>(); 90 + assets.clear(); 88 91 89 92 try { 90 - int sectionID = 0; 91 93 for (AssetHandle ah : AssetManager.getMessages()) { 92 94 Logger.log("Reading messages from: " + ah.getName()); 93 - resources.add(new MessageGroup(ah, sectionID++)); 95 + assets.add(new MessageAsset(ah)); 94 96 } 95 97 } 96 98 catch (IOException e) { 97 99 Logger.logError(e.getMessage()); 98 100 } 99 101 100 - filteredList.setContent(resources); 102 + filteredList.setContent(assets); 103 + } 104 + 105 + public boolean hasMessage(String name) 106 + { 107 + if (name == null) 108 + return false; 109 + 110 + for (MessageAsset asset : assets) { 111 + for (Message msg : asset.messages) { 112 + if (name.equals(msg.name)) 113 + return true; 114 + } 115 + } 116 + 117 + return false; 101 118 } 102 119 103 - public static class AssetCellRenderer extends JPanel implements ListCellRenderer<MessageGroup> 120 + public static class AssetCellRenderer extends JPanel implements ListCellRenderer<MessageAsset> 104 121 { 105 122 private final JLabel nameLabel; 106 123 ··· 117 134 118 135 @Override 119 136 public Component getListCellRendererComponent( 120 - JList<? extends MessageGroup> list, 121 - MessageGroup group, 137 + JList<? extends MessageAsset> list, 138 + MessageAsset group, 122 139 int index, 123 140 boolean isSelected, 124 141 boolean cellHasFocus)
+46 -35
src/main/java/game/message/editor/MessageEditor.java
··· 90 90 import game.message.StringConstants.StringStyle; 91 91 import game.message.StringConstants.StringVoice; 92 92 import game.message.StringEncoder; 93 - import game.message.editor.StringTokenizer.Sequence; 93 + import game.message.editor.MessageTokenizer.Sequence; 94 94 import game.texture.ImageConverter; 95 95 import game.texture.Tile; 96 96 import net.miginfocom.swing.MigLayout; ··· 132 132 133 133 // tool settings 134 134 135 - private final StringPrinter printer = new StringPrinter(this); 136 - private StringRenderer renderer; 135 + private final MessagePrinter printer = new MessagePrinter(this); 136 + private MessageRenderer renderer; 137 137 private JPanel editorPanel; 138 138 139 - private AssetListTab resourcePanel; 140 - private MessageListTab stringListPanel; 139 + private AssetListTab assetListTab; 140 + private MessageListTab messageListTab; 141 141 private JTextPane inputTextPane; 142 142 private JTabbedPane tabs; 143 143 ··· 182 182 private volatile boolean ignoreDocumentFormatChanges = false; 183 183 184 184 // IO 185 - public ArrayList<MessageGroup> resourcesToSave = new ArrayList<>(); 185 + public ArrayList<MessageAsset> resourcesToSave = new ArrayList<>(); 186 186 187 187 public static enum PollResult 188 188 { ··· 215 215 216 216 readVarImage(MessageBoxes.Graphic.Letter_Peach.getFile()); 217 217 218 - resourcePanel.fullReload(); 218 + assetListTab.fullReload(); 219 219 setString(null); 220 220 221 221 Logger.log("Loaded string editor."); ··· 393 393 private void handleSaving() 394 394 { 395 395 if (!resourcesToSave.isEmpty()) { 396 - ArrayList<MessageGroup> saved = new ArrayList<>(); 396 + ArrayList<MessageAsset> saved = new ArrayList<>(); 397 397 398 - for (MessageGroup res : resourcesToSave) { 398 + for (MessageAsset res : resourcesToSave) { 399 399 res.saveChanges(); 400 400 saved.add(res); 401 401 } ··· 936 936 modified = true; 937 937 workingString.setModified(); 938 938 } 939 - resourcePanel.repaint(); 940 - stringListPanel.repaint(); 939 + assetListTab.repaint(); 940 + messageListTab.repaint(); 941 941 } 942 942 } 943 943 ··· 976 976 addEditorMenu(menuBar); 977 977 addOptionsMenu(menuBar); 978 978 979 - stringListPanel = new MessageListTab(this); 980 - resourcePanel = new AssetListTab(this, stringListPanel); 979 + messageListTab = new MessageListTab(this); 980 + assetListTab = new AssetListTab(this, messageListTab); 981 981 982 982 tabs = new JTabbedPane(); 983 - createTab(tabs, "Assets", resourcePanel); 984 - createTab(tabs, "Messages", stringListPanel); 983 + createTab(tabs, "Assets", assetListTab); 984 + createTab(tabs, "Messages", messageListTab); 985 985 createTab(tabs, "Variables", makeVariablesTab()); 986 986 987 987 // wrap input pane in a scroll pane to let us scroll ··· 1034 1034 } 1035 1035 } 1036 1036 1037 + public boolean hasMessage(String name) 1038 + { 1039 + return assetListTab.hasMessage(name); 1040 + } 1041 + 1037 1042 private static void createTab(JTabbedPane tabs, String name, Container contents) 1038 1043 { 1039 1044 JLabel lbl = SwingUtils.getLabel(name, 12); ··· 1126 1131 textArea.append(String.format("%n")); 1127 1132 1128 1133 super.incrementDialogsOpen(); 1129 - String[] options = { "Copy to Clipboard" }; 1130 - int selection = SwingUtils.showFramedOptionDialog(null, 1131 - detailScrollPane, 1132 - "Patch for Loading Image", 1133 - JOptionPane.YES_NO_CANCEL_OPTION, 1134 - JOptionPane.PLAIN_MESSAGE, 1135 - Environment.ICON_DEFAULT, 1136 - options, 1137 - options[0]); 1134 + int choice = SwingUtils.getOptionDialog() 1135 + .setTitle("Code for Loading Image") 1136 + .setMessage(detailScrollPane) 1137 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1138 + .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION) 1139 + .setIcon(Environment.ICON_DEFAULT) 1140 + .setOptions("Copy to Clipboard") 1141 + .choose(); 1138 1142 super.decrementDialogsOpen(); 1139 1143 1140 - if (selection == 0) { 1144 + if (choice == 0) { 1141 1145 StringSelection stringSelection = new StringSelection(textArea.getText()); 1142 1146 Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); 1143 1147 cb.setContents(stringSelection, null); ··· 1238 1242 awtKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK); 1239 1243 item.setAccelerator(awtKeyStroke); 1240 1244 item.addActionListener((e) -> { 1241 - resourcePanel.saveChanges(); 1245 + assetListTab.saveChanges(); 1242 1246 }); 1243 1247 menu.add(item); 1244 1248 ··· 1301 1305 item = new JMenuItem("View Tips"); 1302 1306 item.addActionListener((e) -> { 1303 1307 incrementDialogsOpen(); 1304 - SwingUtils.showFramedMessageDialog(getFrame(), new ControlsPanel(), "Controls", JOptionPane.PLAIN_MESSAGE); 1308 + 1309 + SwingUtils.getMessageDialog() 1310 + .setParent(getFrame()) 1311 + .setTitle("Message Editor Pro Tips") 1312 + .setMessage(new MessageTipsPanel()) 1313 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1314 + .show(); 1315 + 1305 1316 decrementDialogsOpen(); 1306 1317 }); 1307 1318 menu.add(item); ··· 1329 1340 @Override 1330 1341 protected void saveChanges() 1331 1342 { 1332 - resourcePanel.saveChanges(); 1343 + assetListTab.saveChanges(); 1333 1344 handleSaving(); 1334 1345 } 1335 1346 ··· 1337 1348 public void glInit() 1338 1349 { 1339 1350 try { 1340 - renderer = new StringRenderer(this); 1351 + renderer = new MessageRenderer(this); 1341 1352 } 1342 1353 catch (Throwable t) { 1343 1354 StarRodMain.displayStackTrace(t); ··· 1361 1372 } 1362 1373 1363 1374 public boolean isCullingEnabled() 1364 - { return cbCulling.isSelected(); } 1375 + { 1376 + return cbCulling.isSelected(); 1377 + } 1365 1378 1366 - public static class ControlsPanel extends JPanel 1379 + public static class MessageTipsPanel extends JPanel 1367 1380 { 1368 - public ControlsPanel() 1381 + public MessageTipsPanel() 1369 1382 { 1370 1383 JTextPane tx = new JTextPane(); 1371 1384 tx.setContentType("text/html"); 1372 1385 tx.setText("<html><body>" 1373 - + "<h1>String Editor Tips</h1>" 1374 - + "<p><b>RIGHT CLICK</b> on items in the resource tab to see available actions</p>" 1375 - + "<p>You can insert newline tags in the text field with <b>SHIFT + ENTER</b></p>" 1386 + + "<p>You can quickly insert newline tags with <b>SHIFT + ENTER</b></p>" 1376 1387 + "</body></html>"); 1377 1388 tx.setEditable(false); 1378 1389 add(tx);
+3 -38
src/main/java/game/message/editor/MessageGroup.java src/main/java/game/message/editor/MessageAsset.java
··· 16 16 import game.message.StringEncoder; 17 17 import util.Logger; 18 18 19 - public class MessageGroup 19 + public class MessageAsset 20 20 { 21 21 public AssetHandle asset; 22 22 public List<Message> messages = null; 23 - public final int index; 24 23 25 24 public boolean hasModified; 26 25 public boolean hasError; 27 26 28 - public MessageGroup(AssetHandle asset, int index) 27 + public MessageAsset(AssetHandle asset) 29 28 { 30 29 this.asset = asset; 31 - this.index = index; 32 30 reload(); 33 31 } 34 32 ··· 43 41 44 42 int msgIndex = 0; 45 43 for (Message msg : messages) { 46 - msg.section = this.index; 47 44 msg.index = msgIndex++; 48 45 } 49 46 } 50 47 51 - /* 52 - public void saveChanges() 53 - { 54 - AssetHandle saveAsset = AssetManager.getTopLevel(asset); 55 - 56 - try (PrintWriter pw = IOUtils.getBufferedPrintWriter(saveAsset)) { 57 - for (Message msg : strings) { 58 - pw.println("#message:" + msg.name); 59 - pw.println("{"); 60 - msg.sanitize(); 61 - String[] lines = msg.getMarkup().split("\r?\n"); 62 - for (String line : lines) { 63 - pw.println(msg.leadingTabs + line); 64 - } 65 - pw.println("}"); 66 - pw.println(""); 67 - } 68 - 69 - asset = saveAsset; 70 - hasModified = false; 71 - for (Message msg : strings) { 72 - msg.modified = false; 73 - } 74 - } 75 - catch (IOException e) { 76 - Logger.logError("Failed to save " + asset.getName()); 77 - Logger.printStackTrace(e); 78 - } 79 - } 80 - */ 81 - 82 48 public void saveChanges() 83 49 { 84 50 List<Line> linesIn; ··· 101 67 linesOut = new ArrayList<>((int) (linesIn.size() * 1.2)); 102 68 int currentLine = 0; 103 69 104 - //TODO ensure strings are sorted 105 70 for (Message msg : messages) { 106 71 if (msg.startLineNum <= 0) { 107 72 continue; ··· 158 123 159 124 private void writeString(Message msg, List<String> linesOut) 160 125 { 161 - linesOut.add("#message:" + msg.name); 126 + linesOut.add(String.format("#message:%02X:(%s)", msg.section, msg.name)); 162 127 linesOut.add("{"); 163 128 164 129 msg.sanitize();
+107 -34
src/main/java/game/message/editor/MessageListTab.java
··· 2 2 3 3 import java.awt.Color; 4 4 import java.awt.Component; 5 - import java.io.IOException; 6 - import java.util.ArrayList; 7 - import java.util.List; 5 + import java.awt.Toolkit; 8 6 9 7 import javax.swing.BorderFactory; 10 8 import javax.swing.JButton; ··· 15 13 import javax.swing.ListCellRenderer; 16 14 17 15 import app.SwingUtils; 18 - import assets.AssetHandle; 19 - import assets.AssetManager; 20 16 import game.message.Message; 21 17 import net.miginfocom.swing.MigLayout; 22 18 import util.Logger; ··· 24 20 25 21 public class MessageListTab extends JPanel 26 22 { 27 - private FilteredListPanel<Message> filteredList; 23 + private final MessageEditor editor; 24 + private final FilteredListPanel<Message> filteredList; 25 + 26 + private MessageAsset asset; 28 27 29 28 public MessageListTab(MessageEditor editor) 30 29 { 30 + this.editor = editor; 31 + 31 32 filteredList = new FilteredListPanel<>(new MessageCellRenderer()) { 32 33 @Override 33 34 public String getFilterableText(Message msg) ··· 44 45 } 45 46 }; 46 47 48 + JButton createButton = new JButton("Create"); 49 + createButton.addActionListener((e) -> createMessage()); 50 + 51 + JButton deleteButton = new JButton("Delete"); 52 + deleteButton.addActionListener((e) -> deleteMessage()); 53 + deleteButton.setEnabled(false); //TODO 54 + 47 55 JButton renameButton = new JButton("Rename"); 48 56 renameButton.addActionListener((e) -> renameMessage()); 49 57 50 - JButton createButton = new JButton("Create"); 51 - createButton.addActionListener((e) -> createMessage()); 58 + JButton sectionButton = new JButton("Set Section"); 59 + sectionButton.addActionListener((e) -> setMessageSection()); 52 60 53 61 setLayout(new MigLayout("fill, ins 0")); 54 62 add(filteredList, "grow, pushy, span, wrap"); 55 63 add(renameButton, "sg but, growx, pushx, h 32!, split 2"); 56 - add(createButton, "sg but, growx, pushx"); 64 + add(sectionButton, "sg but, growx, pushx, wrap"); 65 + add(createButton, "sg but, growx, pushx, h 32!, split 2"); 66 + add(deleteButton, "sg but, growx, pushx"); 67 + } 68 + 69 + public void createMessage() 70 + { 71 + if (asset != null) { 72 + 73 + int sectionID = 0; 74 + if (asset.messages.size() > 0) { 75 + sectionID = asset.messages.get(asset.messages.size() - 1).section; 76 + } 77 + 78 + Message msg = new Message(asset); 79 + msg.section = sectionID; 80 + 81 + msg.name = promptForUniqueName(null); 82 + if (msg.name != null) { 83 + asset.messages.add(msg); 84 + filteredList.setContent(asset.messages); 85 + 86 + filteredList.setSelected(msg); 87 + } 88 + } 89 + } 90 + 91 + public void deleteMessage() 92 + { 93 + Message selected = filteredList.getSelected(); 94 + 95 + if (asset != null && selected != null) { 96 + Toolkit.getDefaultToolkit().beep(); 97 + //TODO asset.messages.remove(selected); 98 + } 57 99 } 58 100 59 101 public void renameMessage() 60 102 { 61 - Message msg = filteredList.getSelected(); 62 - if (msg == null) 103 + Message selected = filteredList.getSelected(); 104 + if (selected == null) 63 105 return; 64 106 65 - String newName = promptForUniqueName(msg.name); 107 + String newName = promptForUniqueName(selected.name); 66 108 67 109 if (newName != null) { 68 - msg.name = newName; 110 + selected.name = newName; 69 111 filteredList.repaint(); 70 112 } 71 113 } 72 114 73 - public void createMessage() 115 + public void setMessageSection() 74 116 { 117 + Message selected = filteredList.getSelected(); 118 + if (selected == null) 119 + return; 75 120 76 - List<MessageGroup> resources = new ArrayList<>(); 121 + String newSection = SwingUtils.getInputDialog() 122 + .setTitle("Choose Message Section") 123 + .setMessage("Enter the new message section (hex)") 124 + .setMessageType(JOptionPane.QUESTION_MESSAGE) 125 + .setDefault(String.format("%02X", selected.section)) 126 + .prompt(); 77 127 78 - try { 79 - int sectionID = 0; 80 - for (AssetHandle ah : AssetManager.getMessages()) { 81 - Logger.log("Reading strings from: " + ah.getName()); 82 - resources.add(new MessageGroup(ah, sectionID++)); 128 + if (newSection != null) { 129 + try { 130 + selected.section = Integer.parseInt(newSection, 16); 131 + filteredList.repaint(); 132 + } 133 + catch (NumberFormatException e) { 134 + Toolkit.getDefaultToolkit().beep(); 135 + Logger.logError(newSection + " is not a valid section!"); 83 136 } 84 137 } 85 - catch (IOException e) { 86 - Logger.logError(e.getMessage()); 87 - } 88 - 89 - //TODO filteredList.setContent(resources); 90 138 } 91 139 92 140 public String promptForUniqueName(String originalName) 93 141 { 94 - String name = SwingUtils.showFramedInputDialog(null, 95 - "Provide a message name", 96 - "Name New Message", 97 - JOptionPane.QUESTION_MESSAGE); 142 + while (true) { 143 + String name = SwingUtils.getInputDialog() 144 + .setTitle("Choose Message Name") 145 + .setMessage("Choose a unique message name") 146 + .setMessageType(JOptionPane.QUESTION_MESSAGE) 147 + .setDefault(originalName) 148 + .prompt(); 98 149 99 - if (name == null || name.isBlank()) { 150 + if (name == null || name.isBlank()) { 151 + // empty name provided 152 + return null; 153 + } 154 + 155 + if (originalName != null && name.equals(originalName)) { 156 + // name did not change 157 + return originalName; 158 + } 159 + 160 + if (!editor.hasMessage(name)) { 161 + // name is unique 162 + return name; 163 + } 100 164 165 + SwingUtils.getWarningDialog() 166 + .setTitle("Name Conflict") 167 + .setMessage(name + " is already in use!") 168 + .show(); 101 169 } 102 - 103 - return name; //TODO 104 170 } 105 171 106 - public void setStrings(List<Message> messages) 172 + public void setAsset(MessageAsset asset) 107 173 { 108 - filteredList.setContent(messages); 174 + this.asset = asset; 175 + 176 + if (asset == null) { 177 + filteredList.setContent(null); 178 + } 179 + else { 180 + filteredList.setContent(asset.messages); 181 + } 109 182 } 110 183 111 184 private static class MessageCellRenderer extends JPanel implements ListCellRenderer<Message>
+1200 -33
src/main/java/game/message/editor/MessageRenderer.java
··· 1 1 package game.message.editor; 2 2 3 + import static game.message.StringConstants.StringEffect.*; 4 + import static game.texture.TileFormat.CI_8; 5 + import static org.lwjgl.opengl.GL11.*; 6 + 7 + import java.awt.image.BufferedImage; 8 + import java.io.File; 3 9 import java.io.IOException; 10 + import java.nio.ByteBuffer; 11 + import java.nio.FloatBuffer; 12 + import java.nio.IntBuffer; 13 + import java.util.List; 14 + import java.util.Random; 4 15 16 + import org.lwjgl.BufferUtils; 17 + 18 + import assets.ExpectedAsset; 19 + import game.SimpleItem; 20 + import game.map.Axis; 21 + import game.map.editor.common.MouseInput; 22 + import game.map.editor.geometry.Vector3f; 23 + import game.map.editor.render.PresetColor; 24 + import game.map.editor.render.TextureManager; 25 + import game.map.shape.TransformMatrix; 26 + import game.message.MessageBoxes; 5 27 import game.message.StringConstants; 28 + import game.message.StringConstants.ControlCharacter; 29 + import game.message.StringConstants.StringFunction; 30 + import game.message.StringConstants.StringStyle; 6 31 import game.message.font.FontManager; 7 32 import game.message.font.FontType; 33 + import game.sprite.ImgAsset; 34 + import game.sprite.Sprite; 35 + import game.sprite.SpriteLoader; 36 + import game.sprite.SpriteLoader.SpriteSet; 37 + import game.sprite.SpriteRaster; 38 + import game.texture.ImageConverter; 39 + import game.texture.Palette; 40 + import game.texture.Texture; 41 + import game.texture.Tile; 42 + import renderer.GLUtils; 43 + import renderer.buffers.LineRenderQueue; 44 + import renderer.shaders.BaseShader; 45 + import renderer.shaders.RenderState; 8 46 import renderer.shaders.ShaderManager; 47 + import renderer.shaders.scene.BasicIndexedShader; 48 + import renderer.shaders.scene.BasicSolidShader; 49 + import renderer.shaders.scene.BasicTexturedShader; 9 50 import renderer.shaders.scene.FontShader; 51 + import util.Logger; 10 52 11 53 public class MessageRenderer 12 54 { 13 - private static final int FONT_SIZE_X = 16; 14 - private static final int FONT_SIZE_Y = 16; 55 + private final MessageEditor editor; 56 + 57 + public final TransformMatrix projMatrix; 58 + public final TransformMatrix viewMatrix; 59 + 60 + private int glBackgroundTexID; 61 + private int glNoiseTexID; 62 + 63 + private Random rng; 64 + private boolean useFiltering = true; 65 + 66 + private int frameCounter = 0; 67 + 68 + // extra resources 69 + private final SpriteLoader spriteLoader; 70 + private Tile[] glItemPreviews = null; 71 + 72 + private BufferedImage varImage = null; 73 + private boolean varImageLoaded = false; 74 + private int glVarTexID; 75 + 76 + public MessageRenderer(MessageEditor editor) throws IOException 77 + { 78 + this.editor = editor; 79 + 80 + projMatrix = new TransformMatrix(); 81 + viewMatrix = new TransformMatrix(); 82 + 83 + rng = new Random(); 84 + loadTextures(); 85 + loadItemIcons(); 86 + 87 + spriteLoader = new SpriteLoader(); 88 + } 89 + 90 + public void cleanup() 91 + { 92 + MessageBoxes.glDelete(); 93 + FontManager.glDelete(); 94 + 95 + glDeleteTextures(glBackgroundTexID); 96 + glDeleteTextures(glNoiseTexID); 97 + glDeleteTextures(glVarTexID); 98 + 99 + if (glItemPreviews != null) { 100 + for (Tile tile : glItemPreviews) { 101 + if (tile == null) 102 + continue; 103 + 104 + tile.glDelete(); 105 + tile.palette.glDelete(); 106 + } 107 + } 108 + } 109 + 110 + private void loadTextures() throws IOException 111 + { 112 + Tile img; 113 + BufferedImage bimg; 114 + 115 + glLoadNoise(); 116 + 117 + // background 118 + try { 119 + File imgFile = ExpectedAsset.KMR_BG.getFile(); 120 + img = Tile.load(imgFile, CI_8); 121 + bimg = ImageConverter.convertToBufferedImage(img); 122 + glBackgroundTexID = glLoadImage(bimg); 123 + } 124 + catch (IOException e) { 125 + Logger.logError("Could not load background asset: " + ExpectedAsset.KMR_BG.getPath()); 126 + } 127 + 128 + MessageBoxes.loadImages(); 129 + MessageBoxes.glLoad(); 130 + 131 + FontManager.loadData(); 132 + FontManager.glLoad(); 133 + } 134 + 135 + private void glLoadNoise() 136 + { 137 + BufferedImage bimg = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB); 138 + for (int i = 0; i < 256; i++) 139 + for (int j = 0; j < 256; j++) { 140 + int I = rng.nextInt() & 0xFF; 141 + bimg.setRGB(i, j, (0xFF << 24) | (I << 16) | (I << 8) | I); 142 + } 143 + 144 + ByteBuffer buffer = TextureManager.createByteBuffer(bimg); 145 + 146 + int glID = glGenTextures(); 147 + glBindTexture(GL_TEXTURE_2D, glID); 148 + 149 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 150 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 151 + 152 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 153 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 154 + 155 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bimg.getWidth(), 156 + bimg.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 157 + 158 + glNoiseTexID = glID; 159 + } 160 + 161 + private void loadItemIcons() throws IOException 162 + { 163 + List<SimpleItem> items = game.ProjectDatabase.getItemList(); 164 + 165 + glItemPreviews = new Tile[items.size()]; 166 + for (int i = 0; i < items.size(); i++) { 167 + Tile tile = items.get(i).iconTile; 168 + if (tile == null) 169 + continue; 170 + 171 + tile.glLoad(Texture.WRAP_CLAMP, Texture.WRAP_CLAMP, false); 172 + tile.palette.glLoad(); 173 + 174 + glItemPreviews[i] = tile; 175 + } 176 + 177 + Logger.log("Loaded icon previews"); 178 + } 179 + 180 + public void setVarImage(BufferedImage bimg) 181 + { 182 + if (varImageLoaded) 183 + glDeleteTextures(glVarTexID); 184 + 185 + glVarTexID = glLoadImage(bimg); 186 + varImage = bimg; 187 + varImageLoaded = true; 188 + } 189 + 190 + private static int glLoadImage(BufferedImage bimg) 191 + { 192 + ByteBuffer buffer = TextureManager.createByteBuffer(bimg); 193 + 194 + int glID = glGenTextures(); 195 + glBindTexture(GL_TEXTURE_2D, glID); 196 + 197 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 198 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 199 + 200 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 201 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 202 + 203 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bimg.getWidth(), 204 + bimg.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 205 + 206 + return glID; 207 + } 208 + 209 + private final void drawBackground(int glTexID) 210 + { 211 + projMatrix.ortho(0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f); 212 + RenderState.setProjectionMatrix(projMatrix); 213 + RenderState.setViewMatrix(null); 214 + 215 + float hfov = 105; 216 + float right = (hfov + 360) / 360; 217 + float scaleX = RenderState.getViewportSizeX() / 600.0f; 218 + 219 + BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class); 220 + shader.texture.bind(glTexID); 221 + shader.setXYQuadCoords(0, 0, 1, 1, 0); 222 + shader.setQuadTexCoords(0, 1, right * scaleX, 0); 223 + shader.renderQuad(); 224 + } 225 + 226 + private static void drawGrid(MessagePrinter printer) 227 + { 228 + RenderState.setLineWidth(1.5f); 229 + 230 + int xstart = printer.windowBasePosX + printer.windowTextStartX; 231 + int ystart = printer.windowBasePosY + printer.windowTextStartY; 232 + int xmax = ((printer.clipMaxX - xstart) / 10) * 10; 233 + int ymax = ((printer.clipMaxY - ystart) / 10) * 10; 234 + 235 + for (int i = 0; i <= xmax; i += 10) { 236 + float alpha = ((i % 20) == 0) ? 0.5f : 0.2f; 237 + int v1 = LineRenderQueue.addVertex() 238 + .setPosition(xstart + i, ystart, 0) 239 + .setColor(0.15f, 0.15f, 0.15f, alpha) 240 + .getIndex(); 241 + int v2 = LineRenderQueue.addVertex() 242 + .setPosition(xstart + i, ystart + ymax, 0) 243 + .setColor(0.15f, 0.15f, 0.15f, alpha) 244 + .getIndex(); 245 + LineRenderQueue.addLine(v1, v2); 246 + } 247 + 248 + for (int i = 0; i <= ymax; i += 10) { 249 + float alpha = ((i % 20) == 0) ? 0.5f : 0.2f; 250 + int v1 = LineRenderQueue.addVertex() 251 + .setPosition(xstart, ystart + i, 0) 252 + .setColor(0.15f, 0.15f, 0.15f, alpha) 253 + .getIndex(); 254 + int v2 = LineRenderQueue.addVertex() 255 + .setPosition(xstart + xmax, ystart + i, 0) 256 + .setColor(0.15f, 0.15f, 0.15f, alpha) 257 + .getIndex(); 258 + LineRenderQueue.addLine(v1, v2); 259 + } 260 + 261 + RenderState.setDepthWrite(false); 262 + LineRenderQueue.render(true); 263 + RenderState.setDepthWrite(true); 264 + } 265 + 266 + private static void drawBackgroundGuide(MessagePrinter printer) 267 + { 268 + int v1, v2, v3, v4; 269 + RenderState.setLineWidth(2.0f); 270 + 271 + RenderState.setColor(PresetColor.RED); 272 + v1 = LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(); 273 + v2 = LineRenderQueue.addVertex().setPosition(320, 0, 0).getIndex(); 274 + v3 = LineRenderQueue.addVertex().setPosition(320, 240, 0).getIndex(); 275 + v4 = LineRenderQueue.addVertex().setPosition(0, 240, 0).getIndex(); 276 + LineRenderQueue.addLine(v1, v2, v3, v4, v1); 277 + 278 + RenderState.setColor(PresetColor.BLUE); 279 + v1 = LineRenderQueue.addVertex().setPosition(12, 20, 0).getIndex(); 280 + v2 = LineRenderQueue.addVertex().setPosition(320 - 12, 20, 0).getIndex(); 281 + v3 = LineRenderQueue.addVertex().setPosition(320 - 12, 240 - 20, 0).getIndex(); 282 + v4 = LineRenderQueue.addVertex().setPosition(12, 240 - 20, 0).getIndex(); 283 + LineRenderQueue.addLine(v1, v2, v3, v4, v1); 284 + 285 + // LineRenderQueue.printContents(); 286 + 287 + RenderState.setDepthWrite(false); 288 + LineRenderQueue.render(true); 289 + RenderState.setDepthWrite(true); 290 + } 291 + 292 + private static void drawForegroundGuide(MessagePrinter printer) 293 + { 294 + int v1, v2, v3, v4; 295 + RenderState.setLineWidth(1.5f); 296 + 297 + RenderState.setColor(PresetColor.GREEN); 298 + v1 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX, printer.windowBasePosY, 0).getIndex(); 299 + v2 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX, printer.windowBasePosY + printer.windowSizeY, 0).getIndex(); 300 + v3 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX + printer.windowSizeX, printer.windowBasePosY + printer.windowSizeY, 0) 301 + .getIndex(); 302 + v4 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX + printer.windowSizeX, printer.windowBasePosY, 0).getIndex(); 303 + LineRenderQueue.addLine(v1, v2, v3, v4, v1); 304 + 305 + RenderState.setColor(PresetColor.TEAL); 306 + v1 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX, printer.rewindArrowY, 0).getIndex(); 307 + v2 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX, printer.rewindArrowY + 24, 0).getIndex(); 308 + v3 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX + 24, printer.rewindArrowY + 24, 0).getIndex(); 309 + v4 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX + 24, printer.rewindArrowY, 0).getIndex(); 310 + LineRenderQueue.addLine(v1, v2, v3, v4, v1); 311 + 312 + RenderState.setColor(PresetColor.YELLOW); 313 + v1 = LineRenderQueue.addVertex().setPosition(printer.clipMinX, printer.clipMinY, 0).getIndex(); 314 + v2 = LineRenderQueue.addVertex().setPosition(printer.clipMinX, printer.clipMaxY, 0).getIndex(); 315 + v3 = LineRenderQueue.addVertex().setPosition(printer.clipMaxX, printer.clipMaxY, 0).getIndex(); 316 + v4 = LineRenderQueue.addVertex().setPosition(printer.clipMaxX, printer.clipMinY, 0).getIndex(); 317 + LineRenderQueue.addLine(v1, v2, v3, v4, v1); 318 + 319 + RenderState.setDepthWrite(false); 320 + LineRenderQueue.render(true); 321 + RenderState.setDepthWrite(true); 322 + } 323 + 324 + private static final void drawAxes(float lineWidth) 325 + { 326 + RenderState.setLineWidth(lineWidth); 327 + 328 + RenderState.setColor(PresetColor.RED); 329 + LineRenderQueue.addLine( 330 + LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(), 331 + LineRenderQueue.addVertex().setPosition(Short.MAX_VALUE, 0, 0).getIndex()); 332 + 333 + RenderState.setColor(PresetColor.GREEN); 334 + LineRenderQueue.addLine( 335 + LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(), 336 + LineRenderQueue.addVertex().setPosition(0, Short.MAX_VALUE, 0).getIndex()); 337 + 338 + LineRenderQueue.render(true); 339 + } 340 + 341 + public Vector3f getMousePosition(MouseInput mouse, boolean useDepth) 342 + { 343 + int mouseX = mouse.getPosX(); 344 + int mouseY = mouse.getPosY(); 345 + 346 + int width = editor.glCanvasWidth(); 347 + int height = editor.glCanvasHeight(); 348 + 349 + IntBuffer viewport = BufferUtils.createIntBuffer(16); 350 + viewport.put(0); 351 + viewport.put(0); 352 + viewport.put(width); 353 + viewport.put(height); 354 + viewport.rewind(); 355 + 356 + float winX = mouseX; 357 + float winY = mouseY; 358 + float winZ = 0; 359 + 360 + if (useDepth) { 361 + // this is the expensive part, reading z from the depth buffer 362 + FloatBuffer fb = BufferUtils.createFloatBuffer(1); 363 + glReadPixels(mouseX, mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, fb); 364 + winZ = fb.get(); 365 + } 366 + 367 + FloatBuffer position = BufferUtils.createFloatBuffer(3); 368 + GLUtils.gluUnProject(winX, winY, winZ, viewMatrix.toFloatBuffer(), projMatrix.toFloatBuffer(), viewport, position); 369 + 370 + return new Vector3f(position.get(), position.get(), position.get()); 371 + } 15 372 16 - public static void init() throws IOException 373 + public void render(MouseInput mouse, MessagePrinter printer, float cameraX, float cameraY, float cameraZoom, float cameraYaw) 17 374 { 18 - if (!FontManager.isLoaded()) 19 - FontManager.loadData(); 375 + assert (printer != null); 376 + 377 + drawBackground(glBackgroundTexID); 378 + 379 + float halfW = (editor.glCanvasWidth() / 2.0f) * cameraZoom; 380 + float halfH = (editor.glCanvasHeight() / 2.0f) * cameraZoom; 381 + projMatrix.ortho(-halfW, halfW, halfH, -halfH, 1, 0x20000); 382 + // projMatrix.perspective(60, (float)editor.glCanvasWidth() / editor.glCanvasHeight(), 1, 0x2000); 383 + RenderState.setProjectionMatrix(projMatrix); 384 + 385 + viewMatrix.setIdentity(); 386 + viewMatrix.translate(new Vector3f(-cameraX, -cameraY, -400.0f * cameraZoom)); 387 + viewMatrix.rotate(Axis.Y, cameraYaw); 388 + RenderState.setViewMatrix(viewMatrix); 389 + RenderState.setModelMatrix(null); 390 + 391 + if (editor.shouldShowViewportGuides()) 392 + drawBackgroundGuide(printer); 393 + 394 + // drawAxes(1.0f); 395 + 396 + DrawState state = new DrawState(printer); 397 + state.useCulling = editor.isCullingEnabled(); 398 + 399 + printer.drawMessageBox(); 400 + 401 + FontShader shader = ShaderManager.use(FontShader.class); 402 + shader.enableFiltering.set(useFiltering); 403 + shader.fadeAlpha.set(1.0f); 404 + 405 + float scrollY = printer.scrollAmount * (state.currentFont.chars.defaultY * state.stringScaleY + printer.style.lineOffset); 406 + int printOffsetX = 0; 407 + int printOffsetY = -(int) (scrollY); 408 + 409 + state.printPosX = 0; 410 + state.printPosY = 0; 411 + printer.drawBuffer.rewind(); 412 + 413 + read_buf: 414 + while (printer.drawBuffer.position() < printer.printPos) { 415 + byte charByte = printer.drawBuffer.get(); 416 + int charInt = charByte & 0xFF; 417 + 418 + if (charInt == MessagePrinter.PAGE_END_MARK) { 419 + continue; 420 + } 421 + else if (charInt == MessagePrinter.BUFFER_FILL) { 422 + break; // end of string 423 + } 424 + else if (charInt < 0xF0) { 425 + int charWidth = MessageUtil.getCharWidth(state.currentFont, state.fontVariant, charInt, state.stringScaleX, state.charWidthOverride, 426 + 0); 427 + if (charInt < state.currentFont.chars.numChars) 428 + renderChar(printer, state, printOffsetX, printOffsetY, charInt); 429 + state.printPosX += charWidth; 430 + } 431 + else if (charInt == 0xF7 || charInt == 0xF8 || charInt == 0xF9) { 432 + int charWidth = MessageUtil.getCharWidth(state.currentFont, state.fontVariant, charInt, state.stringScaleX, state.charWidthOverride, 433 + 0); 434 + state.printPosX += charWidth; 435 + } 436 + else { 437 + switch (ControlCharacter.decodeMap.get(charByte)) { 438 + case ENDL: // 0xF0 439 + state.printPosX = 0; 440 + state.printPosY += state.currentFont.chars.defaultY * state.stringScaleY + printer.style.lineOffset; 441 + break; 442 + 443 + case NEXT: // 0xFB 444 + break; 445 + 446 + case WAIT: // 0xF1 447 + throw new IllegalStateException(this.getClass().getSimpleName() + " should not encounter WAIT"); 448 + 449 + case PAUSE: // 0xF2 450 + printer.drawBuffer.get(); 451 + throw new IllegalStateException(this.getClass().getSimpleName() + " should not encounter PAUSE"); 452 + 453 + case VARIANT0: // 0xF3 454 + case VARIANT1: // 0xF4 455 + case VARIANT2: // 0xF5 456 + case VARIANT3: // 0xF6 457 + state.fontVariant = charInt - 0xF3; 458 + break; 459 + 460 + // 0xF7-0xF9 are spaces 461 + // 0xFA = unknown 462 + 463 + case STYLE: // 0xFC 464 + handleStyle(printer, state); 465 + break; 466 + 467 + case END: // 0xFD 468 + break read_buf; 469 + 470 + // 0xFE = unused afaik 471 + case FUNC: // 0xFF 472 + handleFunction(printer, state, printOffsetX, printOffsetY); 473 + break; 474 + } 475 + } 476 + } 477 + 478 + frameCounter++; 479 + 480 + RenderState.setModelMatrix(null); 481 + if (editor.shouldShowGrid()) 482 + drawGrid(printer); 483 + 484 + // drawForegroundGuide(printer); 485 + 486 + drawUI(mouse, printer); 487 + } 488 + 489 + private void drawUI(MouseInput mouse, MessagePrinter printer) 490 + { 491 + // set UI matrices 492 + TransformMatrix mtx = TransformMatrix.identity(); 493 + mtx.ortho(0, editor.glCanvasWidth(), 0, editor.glCanvasHeight(), -1, 1); 494 + RenderState.setProjectionMatrix(mtx); 495 + RenderState.setViewMatrix(null); 496 + RenderState.setModelMatrix(null); 497 + 498 + RenderState.enableDepthTest(false); 499 + 500 + if (mouse.hasLocation()) { 501 + Vector3f worldPos = getMousePosition(mouse, false); 502 + int mx = Math.round(worldPos.x) - (printer.windowBasePosX + printer.windowTextStartX); 503 + int my = Math.round(worldPos.y) - (printer.windowBasePosY + printer.windowTextStartY); 504 + drawString(0x14, 8, editor.glCanvasHeight() - 4, 16, String.format("Cursor Pos: %3d, %2d", mx, my)); 505 + } 506 + 507 + float bufferFillPercent = 100.0f * printer.compiledLength / MessagePrinter.MAX_LENGTH; 508 + 509 + if (bufferFillPercent > 100.0f) { 510 + drawString(0x12, 176, editor.glCanvasHeight() - 4, 16, String.format("ERROR: String buffer at %.1f%% capacity! (%d/%d)", 511 + bufferFillPercent, printer.compiledLength, MessagePrinter.MAX_LENGTH)); 512 + } 513 + else if (bufferFillPercent > 75.0f) { 514 + int palID = 5; 515 + if (bufferFillPercent > 90.0f) 516 + palID = 6; 517 + if (bufferFillPercent > 95.0f) 518 + palID = 7; 519 + drawString(palID, 176, editor.glCanvasHeight() - 4, 16, String.format("WARNING: String buffer at %.1f%% capacity! (%d/%d)", 520 + bufferFillPercent, printer.compiledLength, MessagePrinter.MAX_LENGTH)); 521 + } 522 + 523 + RenderState.enableDepthTest(true); 524 + } 525 + 526 + private void handleStyle(MessagePrinter printer, DrawState state) 527 + { 528 + switch (StringStyle.decodeMap.get(printer.drawBuffer.get())) { 529 + case RIGHT: 530 + case LEFT: 531 + case CENTER: 532 + case TATTLE: 533 + case CHOICE: 534 + state.textColor = 0xA; 535 + break; 536 + case INSPECT: 537 + case UPGRADE: 538 + case NARRATE: 539 + case STYLE_F: 540 + state.textColor = 0; 541 + break; 542 + case SIGN: 543 + state.textColor = 0x18; 544 + break; 545 + case LAMPPOST: 546 + state.textColor = 0x1C; 547 + break; 548 + case POSTCARD: 549 + case POPUP: 550 + case STYLE_B: 551 + state.textColor = 0; 552 + break; 553 + case EPILOGUE: 554 + state.textColor = 0; 555 + break; 556 + } 557 + } 558 + 559 + private void handleFunction(MessagePrinter printer, DrawState state, int relativePosX, int relativePosY) 560 + { 561 + int startX = state.getScreenPosX(relativePosX); 562 + int startY = state.getScreenPosY(relativePosY); 563 + StringFunction func = StringFunction.decodeMap.get(printer.drawBuffer.get()); 564 + 565 + switch (func) { 566 + case CURSOR: 567 + case OPTION: 568 + case SET_CANCEL: 569 + case END_CHOICE: 570 + printer.drawBuffer.get(); 571 + break; // completely ignored by editor 572 + 573 + case VAR: 574 + printer.drawBuffer.get(); 575 + break; // already handled during encoding 576 + 577 + case FONT: 578 + int fontType = (printer.drawBuffer.get() & 0xFF); 579 + switch (fontType) { 580 + case 0: 581 + state.currentFont = FontType.Normal; 582 + break; 583 + case 1: 584 + state.currentFont = FontType.Menus; 585 + break; 586 + case 2: 587 + state.currentFont = FontType.Menus; 588 + break; 589 + case 3: 590 + state.currentFont = FontType.Title; 591 + break; 592 + case 4: 593 + state.currentFont = FontType.Subtitle; 594 + break; 595 + } 596 + break; 597 + 598 + case VARIANT: 599 + state.fontVariant = (printer.drawBuffer.get() & 0xFF); 600 + break; 601 + 602 + case ANIM_DONE: 603 + if (printer.hasAnim()) { 604 + int spriteID = printer.getAnimSprite(); 605 + int rasterID = printer.getAnimRaster(); 606 + 607 + Sprite npc = spriteLoader.getSprite(SpriteSet.Npc, spriteID); 608 + if (npc != null && !npc.areTexturesLoaded()) 609 + npc.loadTextures(); 610 + 611 + if (npc != null && npc.rasters.getSize() > rasterID) { 612 + BasicIndexedShader shader = ShaderManager.use(BasicIndexedShader.class); 613 + SpriteRaster raster = npc.rasters.get(rasterID); 614 + ImgAsset front = raster.getFront(); 615 + if (front != null) { 616 + front.img.glBind(shader.texture); 617 + front.getPalette().glBind(shader.palette); 618 + drawClippedQuad(shader, state, startX, startX + front.img.width, startY, startY + front.img.height); 619 + } 620 + } 621 + else { 622 + BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class); 623 + float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f; 624 + shader.baseColor.set(1.0f, f, f, 1.0f); 625 + drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x40); 626 + } 627 + } 628 + break; 629 + 630 + case IMAGE: 631 + printer.drawBuffer.get(); // index -- ignored 632 + int posX = printer.drawBuffer.getShort() & 0xFFFF; 633 + int posY = printer.drawBuffer.get() & 0xFF; 634 + int border = printer.drawBuffer.get() & 0xFF; 635 + int alpha = printer.drawBuffer.get() & 0xFF; 636 + int alphaStep = printer.drawBuffer.get() & 0xFF; 637 + 638 + if (varImageLoaded) { 639 + BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class); 640 + shader.texture.bind(glVarTexID); 641 + shader.multiplyBaseColor.set(true); 642 + shader.baseColor.set(1.0f, 1.0f, 1.0f, alpha / 255.0f); 643 + drawQuad(shader, posX, posX + varImage.getWidth(), posY, posY + varImage.getHeight()); 644 + } 645 + else { 646 + BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class); 647 + float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f; 648 + shader.baseColor.set(1.0f, f, f, alpha / 255.0f); 649 + drawQuad(shader, posX, posX + 150, posY, posY + 105); 650 + } 651 + break; 652 + 653 + case HIDE_IMAGE: 654 + printer.drawBuffer.get(); // fade out time 655 + break; 656 + 657 + case INLINE_IMAGE: 658 + printer.drawBuffer.get(); // index -- ignored 659 + 660 + if (varImageLoaded) { 661 + BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class); 662 + shader.texture.bind(glVarTexID); 663 + drawClippedQuad(shader, state, startX, startX + varImage.getWidth(), startY, startY + varImage.getHeight()); 664 + } 665 + else { 666 + BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class); 667 + float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f; 668 + shader.baseColor.set(1.0f, f, f, 1.0f); 669 + drawClippedQuad(shader, state, startX, startX + 0x40, startY, startY + 0x40); 670 + } 671 + break; 672 + 673 + case ITEM_ICON: 674 + int upperItemID = (printer.drawBuffer.get() & 0xFF); 675 + int lowerItemID = (printer.drawBuffer.get() & 0xFF); 676 + int itemID = (upperItemID << 8) | lowerItemID; 20 677 21 - if (!FontManager.isReadyForGL()) 22 - FontManager.glLoad(); 678 + if (glItemPreviews != null && glItemPreviews.length > itemID && glItemPreviews[itemID] != null) { 679 + BasicIndexedShader shader = ShaderManager.use(BasicIndexedShader.class); 680 + glItemPreviews[itemID].glBind(shader.texture); 681 + glItemPreviews[itemID].palette.glBind(shader.palette); 682 + drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x20); 683 + } 684 + else { 685 + BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class); 686 + float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f; 687 + shader.baseColor.set(1.0f, f, f, 1.0f); 688 + drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x20); 689 + } 690 + break; 691 + 692 + case COLOR: 693 + state.textColor = (printer.drawBuffer.get() & 0xFF); 694 + if (state.textColor < 0) 695 + state.textColor = 0; 696 + int numPals = state.currentFont.chars.numPals; 697 + if (state.textColor >= numPals) 698 + state.textColor = numPals - 1; 699 + break; 700 + 701 + case PUSH_COLOR: 702 + state.savedColor = state.textColor; 703 + break; 704 + case POP_COLOR: 705 + state.textColor = state.savedColor; 706 + break; 707 + 708 + case PUSH_POS: 709 + state.savedPosX = state.printPosX; 710 + state.savedPosY = state.printPosY; 711 + break; 712 + case POP_POS: 713 + state.printPosX = state.savedPosX; 714 + state.printPosY = state.savedPosY; 715 + break; 716 + 717 + case SPACING: 718 + state.charWidthOverride = (printer.drawBuffer.get() & 0xFF); 719 + break; 720 + 721 + case SIZE: 722 + int sx = (printer.drawBuffer.get() & 0xFF); 723 + int sy = (printer.drawBuffer.get() & 0xFF); 724 + state.stringScaleX = sx / 16.0f; 725 + state.stringScaleY = sy / 16.0f; 726 + state.charScaleX = state.stringScaleX; 727 + state.charScaleY = state.stringScaleY; 728 + break; 729 + case SIZE_RESET: 730 + state.stringScaleX = 1.0f; 731 + state.stringScaleY = 1.0f; 732 + state.charScaleX = state.stringScaleX; 733 + state.charScaleY = state.stringScaleY; 734 + break; 735 + 736 + case SET_X: // [80129EB4] 737 + int upper = (printer.drawBuffer.get() & 0xFF); 738 + int lower = (printer.drawBuffer.get() & 0xFF); 739 + state.printPosX = (upper << 8) | lower; 740 + break; 741 + case SET_Y: // [80129ED8] 742 + state.printPosY = (printer.drawBuffer.get() & 0xFF); 743 + break; 744 + case RIGHT: // [80129F0C] 745 + state.printPosX += (printer.drawBuffer.get() & 0xFF); 746 + break; 747 + case DOWN: // [80129F38] 748 + state.printPosY += (printer.drawBuffer.get() & 0xFF); 749 + break; 750 + case UP: // [80129F64] 751 + state.printPosY -= (printer.drawBuffer.get() & 0xFF); 752 + break; 753 + case CENTER_X: // [8012AAEC] 754 + state.centerPos = (printer.drawBuffer.get() & 0xFF); 755 + break; 756 + 757 + case START_FX: 758 + int startFXType = (printer.drawBuffer.get() & 0xFF); 759 + state.effectActive[startFXType] = true; 760 + switch (startFXType) { 761 + case 0x2: 762 + state.effectActive[3] = false; 763 + break; 764 + case 0x3: 765 + state.effectActive[2] = false; 766 + state.fadeNoiseAlpha = (printer.drawBuffer.get() & 0xFF) / 255.0f; 767 + break; 768 + case 0x5: 769 + state.fadeJitterArg = (printer.drawBuffer.get() & 0xFF); 770 + break; 771 + case 0x7: 772 + state.fadeAlpha = (printer.drawBuffer.get() & 0xFF) / 255.0f; 773 + break; 774 + case 0x6: 775 + case 0x9: 776 + state.savedFxColor = state.textColor; 777 + break; 778 + case 0xC: 779 + case 0xD: 780 + state.savedFxCharScaleX = state.charScaleX; 781 + state.savedFxCharScaleY = state.charScaleY; 782 + break; 783 + } 784 + break; 785 + 786 + case END_FX: 787 + int endFXType = (printer.drawBuffer.get() & 0xFF); 788 + // restore saved state (if it has been saved) 789 + if (state.effectActive[endFXType]) { 790 + switch (endFXType) { 791 + case 0x2: 792 + case 0x3: 793 + // end clears the flags for these, 794 + // but will not stop the effect since its 795 + // part of the display list 796 + break; 797 + case 0x6: 798 + case 0x9: 799 + state.textColor = state.savedFxColor; 800 + state.effectActive[endFXType] = false; 801 + break; 802 + case 0xC: 803 + case 0xD: 804 + state.charScaleX = state.savedFxCharScaleX; 805 + state.charScaleY = state.savedFxCharScaleY; 806 + state.effectActive[endFXType] = false; 807 + break; 808 + default: 809 + state.effectActive[endFXType] = false; 810 + } 811 + } 812 + break; 813 + 814 + case FUNC_03: 815 + //XXX unknown, some graphics state reset? 816 + break; 817 + 818 + case SETVOICE: 819 + case VOICE: 820 + case VOLUME: 821 + case SPEED: 822 + case SCROLL: 823 + case DELAY_OFF: 824 + case DELAY_ON: 825 + case SKIP_OFF: 826 + case INPUT_OFF: 827 + case INPUT_ON: 828 + case ENABLE_CDOWN: 829 + break; // irrelevant to renderer 830 + 831 + case SET_REWIND: 832 + printer.drawBuffer.get(); 833 + break; // irrelevant to renderer 834 + 835 + case YIELD: 836 + break; 837 + 838 + case SET_CURSOR: 839 + break; 840 + 841 + case ANIM_SPRITE: 842 + case ANIM_DELAY: 843 + case ANIM_LOOP: 844 + throw new IllegalStateException("LOGIC ERROR: " + func.name + " in encodeFunctionArgs!"); 845 + } 23 846 } 24 847 25 - public void drawString(int posX, int posY, int size, String text) 848 + public void drawString(int palID, int posX, int posY, int size, String text) 26 849 { 27 850 FontShader shader = ShaderManager.use(FontShader.class); 28 851 shader.noiseMode.set(0); 29 852 shader.fadeAlpha.set(1.0f); 30 853 shader.enableDropShadow.set(false); 31 854 855 + FontType font = FontType.Normal; 856 + 32 857 for (char c : text.toCharArray()) { 33 858 int index = StringConstants.getIndex(c, true); 34 859 if (index < 0) 35 860 continue; 36 861 37 - int endX = posX + (int) (FONT_SIZE_X * size / 16.0f); 38 - int endY = posY - (int) (FONT_SIZE_Y * size / 16.0f); 39 - int charWidth = getCharWidth(FontType.Normal, 0, index, size / 16.0f); 862 + int endX = posX + (int) (font.chars.defaultX * size / 16.0f); 863 + int endY = posY - (int) (font.chars.defaultY * size / 16.0f); 864 + int charWidth = MessageUtil.getCharWidth(font, 0, index, size / 16.0f, 0, 0); 40 865 41 - if (index < FontType.Normal.chars.numChars) { 42 - FontType.Normal.chars.images[index].glBind(shader.texture); 43 - FontType.Normal.chars.palettes[0x14].glBind(shader.palette); 44 - shader.setQuadTexCoords(0, 0, 1, 1); 45 - shader.setXYQuadCoords(posX, posY, endX, endY, 0); // y flipped 46 - shader.renderQuad(); 866 + if (index < font.chars.numChars) { 867 + font.chars.images[index].glBind(shader.texture); 868 + font.chars.palettes[palID].glBind(shader.palette); 869 + drawQuad(shader, posX, endX, posY, endY); 47 870 } 48 871 posX += charWidth; 49 872 } 50 873 } 51 874 52 - private static int getCharWidth(FontType font, int subfont, int index, float stringScale) 875 + private void renderChar(MessagePrinter printer, DrawState state, int relativePosX, int relativePosY, int charIndex) 53 876 { 54 - if (index < 0xFA) { 55 - int width; 56 - if ((index == 0xF7) || (index == 0xF8) || (index == 0xF9)) 57 - width = font.fullspaceWidth[subfont]; 877 + FontShader shader = ShaderManager.use(FontShader.class); 878 + 879 + int[] lookahead = new int[4]; 880 + for (int i = 0; i < lookahead.length; i++) 881 + lookahead[i] = (printer.drawBuffer.get() & 0xFF); 882 + printer.drawBuffer.position(printer.drawBuffer.position() - lookahead.length); 883 + 884 + //XXX correct? 885 + state.charScaleX = state.stringScaleX; 886 + state.charScaleY = state.stringScaleY; 887 + float alpha = 1.0f; 888 + 889 + if (state.effectActive[BLUR.code]) // 0x20 890 + { 891 + // fade code from [8012ADC4] 892 + alpha = 0.35f; 893 + } 894 + 895 + if (state.effectActive[SHAKE.code]) { 896 + // code from [8012AE50] 897 + relativePosX += rng.nextInt() % 2; 898 + relativePosY += rng.nextInt() % 2; 899 + } 900 + 901 + if (state.effectActive[WAVE.code]) // 0x2 902 + { 903 + // code from [8012AEBC] 904 + double dsx = state.stringScaleX - 1.0; 905 + double dsy = state.stringScaleY - 1.0; 906 + 907 + //NOTE: game uses a message-specific 'local' frame counter here 908 + double angle = frameCounter * (int) (20.0 - dsx * 5.0) - state.visibleCharCount * (int) (45.0 - dsx * 15.0); 909 + relativePosX += Math.cos(Math.toRadians(angle)) * (dsx + 1.6); 910 + relativePosY += Math.cos(Math.toRadians(angle + 270.0)) * (dsy + 1.6); 911 + } 912 + if (state.effectActive[GLOBAL_WAVE.code]) // 0x200 913 + { 914 + // code from [8012B0BC] 915 + double dsx = state.stringScaleX - 1.0; 916 + double dsy = state.stringScaleY - 1.0; 917 + 918 + //NOTE: game uses a 'global' frame counter shared by all messages here 919 + double angle = frameCounter * (int) (20.0 - dsx * 5.0) - state.visibleCharCount * 45.0; 920 + relativePosX += Math.cos(Math.toRadians(angle)) * (dsx + 1.6); 921 + relativePosY += Math.cos(Math.toRadians(angle + 270.0)) * (dsy + 1.6); 922 + } 923 + 924 + if (state.effectActive[RAINBOW.code] || state.effectActive[GLOBAL_RAINBOW.code]) // 0x440 -- either rainbow 925 + { 926 + // code from [8012B1B4] 927 + 928 + // NOTE: global overrides local here, but they cant stack so we dont need to represent it 929 + int i = Math.abs(state.visibleCharCount - frameCounter / 3); 930 + state.textColor = i % 10; // original code: = i + (i / 10) * -10; 931 + } 932 + 933 + // properly respect precedence of these effects 934 + if (state.effectActive[RISE_PRINT.code] || state.effectActive[GROW_PRINT.code]) { 935 + if (!printer.donePrinting 936 + && (lookahead[0] != ControlCharacter.ENDL.code) && (lookahead[1] != ControlCharacter.ENDL.code) 937 + && (lookahead[2] != ControlCharacter.ENDL.code) && (lookahead[3] != ControlCharacter.ENDL.code)) { 938 + if (state.effectActive[RISE_PRINT.code]) { 939 + // from [8012B4F0] 940 + float dummyScale = 0.25f; //XXX needed to match, unknown why 941 + if (lookahead[0] == MessagePrinter.BUFFER_FILL) { 942 + state.charScaleX = 1.7f * state.stringScaleX; 943 + state.charScaleY = 1.7f * state.stringScaleY; 944 + relativePosX -= 6.0f * state.stringScaleY; 945 + relativePosY -= dummyScale * 6.0f * state.stringScaleY; 946 + } 947 + else if (lookahead[1] == MessagePrinter.BUFFER_FILL) { 948 + state.charScaleX = 1.4f * state.stringScaleX; 949 + state.charScaleY = 1.4f * state.stringScaleY; 950 + relativePosX -= 3.0f * state.stringScaleY; 951 + relativePosY -= dummyScale * 3.0f * state.stringScaleY; 952 + } 953 + else if (lookahead[2] == MessagePrinter.BUFFER_FILL) { 954 + state.charScaleX = 1.2f * state.stringScaleX; 955 + state.charScaleY = 1.2f * state.stringScaleY; 956 + relativePosX -= 2.0f * state.stringScaleY; 957 + relativePosY -= dummyScale * 2.0f * state.stringScaleY; 958 + } 959 + } 960 + else if (state.effectActive[GROW_PRINT.code]) { 961 + // from [8012B740] 962 + if (lookahead[0] == MessagePrinter.BUFFER_FILL) { 963 + state.charScaleX = 0.3f * state.stringScaleX; 964 + state.charScaleY = 0.3f * state.stringScaleY; 965 + relativePosX += 5; 966 + relativePosY += 5; 967 + } 968 + else if (lookahead[1] == MessagePrinter.BUFFER_FILL) { 969 + state.charScaleX = 0.5f * state.stringScaleX; 970 + state.charScaleY = 0.5f * state.stringScaleY; 971 + relativePosX += 3; 972 + relativePosY += 3; 973 + } 974 + else if (lookahead[2] == MessagePrinter.BUFFER_FILL) { 975 + state.charScaleX = 0.75f * state.stringScaleX; 976 + state.charScaleY = 0.75f * state.stringScaleY; 977 + relativePosX += 2; 978 + relativePosY += 2; 979 + } 980 + } 981 + } 982 + } 983 + else if (state.effectActive[SIZE_JITTER.code] || state.effectActive[SIZE_WAVE.code]) { 984 + float scale = 1.0f; 985 + 986 + if (state.effectActive[SIZE_JITTER.code]) // 0x2000 -- size jitter 987 + { 988 + // code from [8012B8BC] 989 + scale = 0.75f + 0.5f * (rng.nextInt(101) / 100.0f); 990 + } 991 + else if (state.effectActive[SIZE_WAVE.code]) // 0x4000 -- size wave 992 + { 993 + // code from [8012BA24] 994 + int i = (frameCounter - state.visibleCharCount) * 15; 995 + scale = 1.0f + 0.25f * (float) Math.cos(Math.toRadians(i + ((i >> 3) / 45) * 360.0)); 996 + } 997 + 998 + state.charScaleX *= scale; 999 + state.charScaleY *= scale; 1000 + 1001 + if (scale >= 1.0) { 1002 + // [8012BACC] 1003 + int posOffset = (int) (scale * 8.0 - 8.5); 1004 + relativePosX -= posOffset; 1005 + relativePosY -= posOffset; 1006 + } 1007 + else { 1008 + // [8012BB7C] 1009 + int posOffset = (int) (8.0 - 8.0 * scale); 1010 + relativePosX += posOffset; 1011 + relativePosY += posOffset; 1012 + } 1013 + } 1014 + 1015 + shader.noiseMode.set(0); // initial value 1016 + 1017 + if (state.effectActive[DITHER_FADE.code]) //0x80 -- fade 1018 + { 1019 + alpha *= state.fadeAlpha; 1020 + shader.noiseMode.set(7); 1021 + shader.noiseAlpha.set(state.fadeAlpha); 1022 + shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat()); 1023 + } 1024 + else { 1025 + if (state.effectActive[NOISE_OUTLINE.code]) // 0x04 -- noise 1026 + { 1027 + shader.noiseMode.set(2); 1028 + shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat()); 1029 + 1030 + // add Gfx: 1031 + // SET_COMBINE FC70FEE1 FFFFF3F9 1032 + 1033 + // color: G_CCMUX_NOISE * G_CCMUX_TEXEL0 1034 + // alpha: G_ACMUX_TEXEL0 1035 + } 1036 + 1037 + if (state.effectActive[STATIC.code]) // 0x10000 -- faded noise 1038 + { 1039 + shader.noiseMode.set(3); 1040 + shader.noiseAlpha.set(state.fadeNoiseAlpha); 1041 + shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat()); 1042 + 1043 + // add Gfx: 1044 + // SET_ENVCOLOR FB000000 arg << 0x18 | arg << 0x10 | arg << 8; 1045 + // SET_COMBINE FC72FEE5 11FCF279 1046 + 1047 + // color: (G_CCMUX_NOISE - G_CCMUX_TEXEL0) * G_CCMUX_ENVIRONMENT + G_CCMUX_TEXEL0 1048 + // alpha: G_ACMUX_TEXEL0 1049 + } 1050 + } 1051 + 1052 + shader.fadeAlpha.set(alpha); 1053 + 1054 + int baseOffset = 0; 1055 + if (state.fontVariant < state.currentFont.numVariants && state.fontVariant >= 0) 1056 + baseOffset = state.currentFont.baseHeightOffset[state.fontVariant]; 1057 + 1058 + int startX = state.getScreenPosX(relativePosX); 1059 + int startY = state.getScreenPosY(relativePosY + baseOffset); 1060 + int endX = startX + (int) (state.currentFont.chars.defaultX * state.charScaleX); 1061 + int endY = startY + (int) (state.currentFont.chars.defaultY * state.charScaleY); 1062 + 1063 + if (state.effectActive[DROP_SHADOW.code]) // 0x8000 -- drop shadow 1064 + { 1065 + shader.enableDropShadow.set(true); 1066 + drawFontQuad(shader, state, 1067 + state.currentFont.chars.images[charIndex], 1068 + state.currentFont.chars.palettes[state.getColor()], 1069 + startX + 2, endX + 2, startY + 2, endY + 2); 1070 + shader.enableDropShadow.set(false); 1071 + } 1072 + 1073 + if (state.effectActive[BLUR.code]) // 0x20 -- FadedJitter 1074 + { 1075 + // code from [8012BDF4] 1076 + for (int i = 0; i < 5; i++) { 1077 + int jx = (state.fadeJitterArg == 2) ? 0 : rng.nextInt(3) - 1; 1078 + int jy = (state.fadeJitterArg == 1) ? 0 : rng.nextInt(3) - 1; 1079 + 1080 + drawFontQuad(shader, state, 1081 + state.currentFont.chars.images[charIndex], 1082 + state.currentFont.chars.palettes[state.getColor()], 1083 + startX + jx, endX + jx, startY + jy, endY + jy); 1084 + } 1085 + } 1086 + else { 1087 + drawFontQuad(shader, state, 1088 + state.currentFont.chars.images[charIndex], 1089 + state.currentFont.chars.palettes[state.getColor()], 1090 + startX, endX, startY, endY); 1091 + } 1092 + 1093 + state.visibleCharCount++; 1094 + } 1095 + 1096 + private static class DrawState 1097 + { 1098 + public final MessagePrinter printer; 1099 + 1100 + private FontType currentFont = FontType.Normal; 1101 + public int fontVariant = 0; 1102 + 1103 + private boolean[] effectActive; 1104 + private float fadeAlpha = 1.0f; 1105 + private float fadeNoiseAlpha = 0; 1106 + private int fadeJitterArg = 0; 1107 + 1108 + private int textColor = 0xA; 1109 + 1110 + private int visibleCharCount = 0; 1111 + 1112 + private boolean useCulling = true; 1113 + 1114 + private int printPosX = 0; 1115 + private int printPosY = 0; 1116 + 1117 + private int centerPos = 0; 1118 + 1119 + private int savedColor; 1120 + private int savedPosX = 0; 1121 + private int savedPosY = 0; 1122 + private int savedFxColor = -1; 1123 + private float savedFxCharScaleX = 1.0f; 1124 + private float savedFxCharScaleY = 1.0f; 1125 + 1126 + private int charWidthOverride = 0; 1127 + 1128 + private float charScaleX = 1.0f; 1129 + private float charScaleY = 1.0f; 1130 + 1131 + private float stringScaleX = 1.0f; 1132 + private float stringScaleY = 1.0f; 1133 + 1134 + private DrawState(MessagePrinter printer) 1135 + { 1136 + this.printer = printer; 1137 + effectActive = new boolean[StringConstants.StringEffect.values().length]; 1138 + } 1139 + 1140 + public int getColor() 1141 + { 1142 + switch (currentFont) { 1143 + case Normal: 1144 + case Menus: 1145 + default: 1146 + return textColor; 1147 + case Title: 1148 + case Subtitle: 1149 + return 0; 1150 + } 1151 + } 1152 + 1153 + public int getScreenPosX(int offsetX) 1154 + { 1155 + int centerOffset = 0; 1156 + if (centerPos == 0xFF) 1157 + centerOffset = 160 - (printer.stringWidth / 2); 1158 + else if (centerPos != 0) 1159 + centerOffset = centerPos - (printer.stringWidth / 2); 1160 + 1161 + if (centerOffset == 0) 1162 + return printer.windowBasePosX + printer.windowTextStartX + printPosX + offsetX; 58 1163 else 59 - width = font.chars.widths[index]; 1164 + return centerOffset + printPosX + offsetX; 1165 + } 60 1166 61 - if (index == 0xF7) 62 - return (int) ((width * stringScale) * 0.6); 63 - if (index == 0xF8) 64 - return (int) (width * stringScale); 65 - if (index == 0xF9) 66 - return (int) ((width * stringScale) * 0.5); 67 - if (index >= 0xF0) 68 - return 0; // other control chars 69 - return (int) (width * stringScale); 1167 + public int getScreenPosY(int offsetY) 1168 + { 1169 + return printer.windowBasePosY + printer.windowTextStartY + printPosY + offsetY; 1170 + } 1171 + } 1172 + 1173 + private void drawFontQuad(FontShader shader, DrawState state, Tile img, Palette pal, float x1, float x2, float y1, float y2) 1174 + { 1175 + img.glBind(shader.texture); 1176 + pal.glBind(shader.palette); 1177 + shader.noise.bind(glNoiseTexID); 1178 + drawClippedQuad(shader, state, x1, x2, y1, y2); 1179 + } 1180 + 1181 + private static final void drawClippedQuad(BaseShader shader, DrawState state, float x1, float x2, float y1, float y2) 1182 + { 1183 + if (state.useCulling) 1184 + drawClippedQuad(shader, state.printer, x1, x2, y1, y2); 1185 + else 1186 + drawQuad(shader, x1, x2, y1, y2); 1187 + } 1188 + 1189 + private static final void drawClippedQuad(BaseShader shader, MessagePrinter printer, float x1, float x2, float y1, float y2) 1190 + { 1191 + float x1c = x1; 1192 + float x2c = x2; 1193 + 1194 + float y1c = y1; 1195 + float y2c = y2; 1196 + 1197 + float u1c = 0.0f; 1198 + float u2c = 1.0f; 1199 + 1200 + float v1c = 0.0f; 1201 + float v2c = 1.0f; 1202 + 1203 + assert (x1 < x2); 1204 + assert (y1 < y2); 1205 + 1206 + if ((x2 < printer.clipMinX) || (x1 > printer.clipMaxX) || (y2 < printer.clipMinY) || (y1 > printer.clipMaxY)) 1207 + return; 1208 + 1209 + if (x1 < printer.clipMinX) { 1210 + x1c = printer.clipMinX; 1211 + u1c = ((printer.clipMinX - x1) / (x2 - x1)); 1212 + } 1213 + 1214 + if (x2 > printer.clipMaxX) { 1215 + x2c = printer.clipMaxX; 1216 + u2c = 1.0f - ((x2 - printer.clipMaxX) / (x2 - x1)); 70 1217 } 71 - return 0; 1218 + 1219 + if (y1 < printer.clipMinY) { 1220 + y1c = printer.clipMinY; 1221 + v2c = 1.0f - ((printer.clipMinY - y1) / (y2 - y1)); 1222 + } 1223 + 1224 + if (y2 > printer.clipMaxY) { 1225 + y2c = printer.clipMaxY; 1226 + v1c = ((y2 - printer.clipMaxY) / (y2 - y1)); 1227 + } 1228 + 1229 + shader.setQuadTexCoords(u1c, v1c, u2c, v2c); 1230 + shader.setXYQuadCoords(x1c, y2c, x2c, y1c, 0); // y flipped 1231 + shader.renderQuad(); 1232 + } 1233 + 1234 + private static final void drawQuad(BaseShader shader, float x1, float x2, float y1, float y2) 1235 + { 1236 + shader.setQuadTexCoords(0, 0, 1, 1); 1237 + shader.setXYQuadCoords(x1, y2, x2, y1, 0); // y flipped 1238 + shader.renderQuad(); 72 1239 } 73 1240 }
+73
src/main/java/game/message/editor/SimpleMessageRenderer.java
··· 1 + package game.message.editor; 2 + 3 + import java.io.IOException; 4 + 5 + import game.message.StringConstants; 6 + import game.message.font.FontManager; 7 + import game.message.font.FontType; 8 + import renderer.shaders.ShaderManager; 9 + import renderer.shaders.scene.FontShader; 10 + 11 + public class SimpleMessageRenderer 12 + { 13 + private static final int FONT_SIZE_X = 16; 14 + private static final int FONT_SIZE_Y = 16; 15 + 16 + public static void init() throws IOException 17 + { 18 + if (!FontManager.isLoaded()) 19 + FontManager.loadData(); 20 + 21 + if (!FontManager.isReadyForGL()) 22 + FontManager.glLoad(); 23 + } 24 + 25 + public void drawString(int posX, int posY, int size, String text) 26 + { 27 + FontShader shader = ShaderManager.use(FontShader.class); 28 + shader.noiseMode.set(0); 29 + shader.fadeAlpha.set(1.0f); 30 + shader.enableDropShadow.set(false); 31 + 32 + for (char c : text.toCharArray()) { 33 + int index = StringConstants.getIndex(c, true); 34 + if (index < 0) 35 + continue; 36 + 37 + int endX = posX + (int) (FONT_SIZE_X * size / 16.0f); 38 + int endY = posY - (int) (FONT_SIZE_Y * size / 16.0f); 39 + int charWidth = getCharWidth(FontType.Normal, 0, index, size / 16.0f); 40 + 41 + if (index < FontType.Normal.chars.numChars) { 42 + FontType.Normal.chars.images[index].glBind(shader.texture); 43 + FontType.Normal.chars.palettes[0x14].glBind(shader.palette); 44 + shader.setQuadTexCoords(0, 0, 1, 1); 45 + shader.setXYQuadCoords(posX, posY, endX, endY, 0); // y flipped 46 + shader.renderQuad(); 47 + } 48 + posX += charWidth; 49 + } 50 + } 51 + 52 + private static int getCharWidth(FontType font, int subfont, int index, float stringScale) 53 + { 54 + if (index < 0xFA) { 55 + int width; 56 + if ((index == 0xF7) || (index == 0xF8) || (index == 0xF9)) 57 + width = font.fullspaceWidth[subfont]; 58 + else 59 + width = font.chars.widths[index]; 60 + 61 + if (index == 0xF7) 62 + return (int) ((width * stringScale) * 0.6); 63 + if (index == 0xF8) 64 + return (int) (width * stringScale); 65 + if (index == 0xF9) 66 + return (int) ((width * stringScale) * 0.5); 67 + if (index >= 0xF0) 68 + return 0; // other control chars 69 + return (int) (width * stringScale); 70 + } 71 + return 0; 72 + } 73 + }
+3 -3
src/main/java/game/message/editor/StringPrinter.java src/main/java/game/message/editor/MessagePrinter.java
··· 15 15 import game.message.StringConstants.StringStyle; 16 16 import game.message.StringEncoder; 17 17 import game.message.editor.MessageUtil.StringProperties; 18 - import game.message.editor.StringTokenizer.Sequence; 18 + import game.message.editor.MessageTokenizer.Sequence; 19 19 import util.MathUtil; 20 20 21 - public class StringPrinter 21 + public class MessagePrinter 22 22 { 23 23 private MessageEditor editor; 24 24 ··· 387 387 } 388 388 } 389 389 390 - public StringPrinter(MessageEditor editor) 390 + public MessagePrinter(MessageEditor editor) 391 391 { 392 392 this.editor = editor; 393 393 setStyle(StringStyle.RIGHT, null); // initialize parameters for default window style
-1240
src/main/java/game/message/editor/StringRenderer.java
··· 1 - package game.message.editor; 2 - 3 - import static game.message.StringConstants.StringEffect.*; 4 - import static game.texture.TileFormat.CI_8; 5 - import static org.lwjgl.opengl.GL11.*; 6 - 7 - import java.awt.image.BufferedImage; 8 - import java.io.File; 9 - import java.io.IOException; 10 - import java.nio.ByteBuffer; 11 - import java.nio.FloatBuffer; 12 - import java.nio.IntBuffer; 13 - import java.util.List; 14 - import java.util.Random; 15 - 16 - import org.lwjgl.BufferUtils; 17 - 18 - import assets.ExpectedAsset; 19 - import game.SimpleItem; 20 - import game.map.Axis; 21 - import game.map.editor.common.MouseInput; 22 - import game.map.editor.geometry.Vector3f; 23 - import game.map.editor.render.PresetColor; 24 - import game.map.editor.render.TextureManager; 25 - import game.map.shape.TransformMatrix; 26 - import game.message.MessageBoxes; 27 - import game.message.StringConstants; 28 - import game.message.StringConstants.ControlCharacter; 29 - import game.message.StringConstants.StringFunction; 30 - import game.message.StringConstants.StringStyle; 31 - import game.message.font.FontManager; 32 - import game.message.font.FontType; 33 - import game.sprite.ImgAsset; 34 - import game.sprite.Sprite; 35 - import game.sprite.SpriteLoader; 36 - import game.sprite.SpriteLoader.SpriteSet; 37 - import game.sprite.SpriteRaster; 38 - import game.texture.ImageConverter; 39 - import game.texture.Palette; 40 - import game.texture.Texture; 41 - import game.texture.Tile; 42 - import renderer.GLUtils; 43 - import renderer.buffers.LineRenderQueue; 44 - import renderer.shaders.BaseShader; 45 - import renderer.shaders.RenderState; 46 - import renderer.shaders.ShaderManager; 47 - import renderer.shaders.scene.BasicIndexedShader; 48 - import renderer.shaders.scene.BasicSolidShader; 49 - import renderer.shaders.scene.BasicTexturedShader; 50 - import renderer.shaders.scene.FontShader; 51 - import util.Logger; 52 - 53 - public class StringRenderer 54 - { 55 - private final MessageEditor editor; 56 - 57 - public final TransformMatrix projMatrix; 58 - public final TransformMatrix viewMatrix; 59 - 60 - private int glBackgroundTexID; 61 - private int glNoiseTexID; 62 - 63 - private Random rng; 64 - private boolean useFiltering = true; 65 - 66 - private int frameCounter = 0; 67 - 68 - // extra resources 69 - private final SpriteLoader spriteLoader; 70 - private Tile[] glItemPreviews = null; 71 - 72 - private BufferedImage varImage = null; 73 - private boolean varImageLoaded = false; 74 - private int glVarTexID; 75 - 76 - public StringRenderer(MessageEditor editor) throws IOException 77 - { 78 - this.editor = editor; 79 - 80 - projMatrix = new TransformMatrix(); 81 - viewMatrix = new TransformMatrix(); 82 - 83 - rng = new Random(); 84 - loadTextures(); 85 - loadItemIcons(); 86 - 87 - spriteLoader = new SpriteLoader(); 88 - } 89 - 90 - public void cleanup() 91 - { 92 - MessageBoxes.glDelete(); 93 - FontManager.glDelete(); 94 - 95 - glDeleteTextures(glBackgroundTexID); 96 - glDeleteTextures(glNoiseTexID); 97 - glDeleteTextures(glVarTexID); 98 - 99 - if (glItemPreviews != null) { 100 - for (Tile tile : glItemPreviews) { 101 - if (tile == null) 102 - continue; 103 - 104 - tile.glDelete(); 105 - tile.palette.glDelete(); 106 - } 107 - } 108 - } 109 - 110 - private void loadTextures() throws IOException 111 - { 112 - Tile img; 113 - BufferedImage bimg; 114 - 115 - glLoadNoise(); 116 - 117 - // background 118 - try { 119 - File imgFile = ExpectedAsset.KMR_BG.getFile(); 120 - img = Tile.load(imgFile, CI_8); 121 - bimg = ImageConverter.convertToBufferedImage(img); 122 - glBackgroundTexID = glLoadImage(bimg); 123 - } 124 - catch (IOException e) { 125 - Logger.logError("Could not load background asset: " + ExpectedAsset.KMR_BG.getPath()); 126 - } 127 - 128 - MessageBoxes.loadImages(); 129 - MessageBoxes.glLoad(); 130 - 131 - FontManager.loadData(); 132 - FontManager.glLoad(); 133 - } 134 - 135 - private void glLoadNoise() 136 - { 137 - BufferedImage bimg = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB); 138 - for (int i = 0; i < 256; i++) 139 - for (int j = 0; j < 256; j++) { 140 - int I = rng.nextInt() & 0xFF; 141 - bimg.setRGB(i, j, (0xFF << 24) | (I << 16) | (I << 8) | I); 142 - } 143 - 144 - ByteBuffer buffer = TextureManager.createByteBuffer(bimg); 145 - 146 - int glID = glGenTextures(); 147 - glBindTexture(GL_TEXTURE_2D, glID); 148 - 149 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 150 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 151 - 152 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 153 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 154 - 155 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bimg.getWidth(), 156 - bimg.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 157 - 158 - glNoiseTexID = glID; 159 - } 160 - 161 - private void loadItemIcons() throws IOException 162 - { 163 - List<SimpleItem> items = game.ProjectDatabase.getItemList(); 164 - 165 - glItemPreviews = new Tile[items.size()]; 166 - for (int i = 0; i < items.size(); i++) { 167 - Tile tile = items.get(i).iconTile; 168 - if (tile == null) 169 - continue; 170 - 171 - tile.glLoad(Texture.WRAP_CLAMP, Texture.WRAP_CLAMP, false); 172 - tile.palette.glLoad(); 173 - 174 - glItemPreviews[i] = tile; 175 - } 176 - 177 - Logger.log("Loaded icon previews"); 178 - } 179 - 180 - public void setVarImage(BufferedImage bimg) 181 - { 182 - if (varImageLoaded) 183 - glDeleteTextures(glVarTexID); 184 - 185 - glVarTexID = glLoadImage(bimg); 186 - varImage = bimg; 187 - varImageLoaded = true; 188 - } 189 - 190 - private static int glLoadImage(BufferedImage bimg) 191 - { 192 - ByteBuffer buffer = TextureManager.createByteBuffer(bimg); 193 - 194 - int glID = glGenTextures(); 195 - glBindTexture(GL_TEXTURE_2D, glID); 196 - 197 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 198 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 199 - 200 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 201 - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 202 - 203 - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bimg.getWidth(), 204 - bimg.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 205 - 206 - return glID; 207 - } 208 - 209 - private final void drawBackground(int glTexID) 210 - { 211 - projMatrix.ortho(0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f); 212 - RenderState.setProjectionMatrix(projMatrix); 213 - RenderState.setViewMatrix(null); 214 - 215 - float hfov = 105; 216 - float right = (hfov + 360) / 360; 217 - float scaleX = RenderState.getViewportSizeX() / 600.0f; 218 - 219 - BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class); 220 - shader.texture.bind(glTexID); 221 - shader.setXYQuadCoords(0, 0, 1, 1, 0); 222 - shader.setQuadTexCoords(0, 1, right * scaleX, 0); 223 - shader.renderQuad(); 224 - } 225 - 226 - private static void drawGrid(StringPrinter printer) 227 - { 228 - RenderState.setLineWidth(1.5f); 229 - 230 - int xstart = printer.windowBasePosX + printer.windowTextStartX; 231 - int ystart = printer.windowBasePosY + printer.windowTextStartY; 232 - int xmax = ((printer.clipMaxX - xstart) / 10) * 10; 233 - int ymax = ((printer.clipMaxY - ystart) / 10) * 10; 234 - 235 - for (int i = 0; i <= xmax; i += 10) { 236 - float alpha = ((i % 20) == 0) ? 0.5f : 0.2f; 237 - int v1 = LineRenderQueue.addVertex() 238 - .setPosition(xstart + i, ystart, 0) 239 - .setColor(0.15f, 0.15f, 0.15f, alpha) 240 - .getIndex(); 241 - int v2 = LineRenderQueue.addVertex() 242 - .setPosition(xstart + i, ystart + ymax, 0) 243 - .setColor(0.15f, 0.15f, 0.15f, alpha) 244 - .getIndex(); 245 - LineRenderQueue.addLine(v1, v2); 246 - } 247 - 248 - for (int i = 0; i <= ymax; i += 10) { 249 - float alpha = ((i % 20) == 0) ? 0.5f : 0.2f; 250 - int v1 = LineRenderQueue.addVertex() 251 - .setPosition(xstart, ystart + i, 0) 252 - .setColor(0.15f, 0.15f, 0.15f, alpha) 253 - .getIndex(); 254 - int v2 = LineRenderQueue.addVertex() 255 - .setPosition(xstart + xmax, ystart + i, 0) 256 - .setColor(0.15f, 0.15f, 0.15f, alpha) 257 - .getIndex(); 258 - LineRenderQueue.addLine(v1, v2); 259 - } 260 - 261 - RenderState.setDepthWrite(false); 262 - LineRenderQueue.render(true); 263 - RenderState.setDepthWrite(true); 264 - } 265 - 266 - private static void drawBackgroundGuide(StringPrinter printer) 267 - { 268 - int v1, v2, v3, v4; 269 - RenderState.setLineWidth(2.0f); 270 - 271 - RenderState.setColor(PresetColor.RED); 272 - v1 = LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(); 273 - v2 = LineRenderQueue.addVertex().setPosition(320, 0, 0).getIndex(); 274 - v3 = LineRenderQueue.addVertex().setPosition(320, 240, 0).getIndex(); 275 - v4 = LineRenderQueue.addVertex().setPosition(0, 240, 0).getIndex(); 276 - LineRenderQueue.addLine(v1, v2, v3, v4, v1); 277 - 278 - RenderState.setColor(PresetColor.BLUE); 279 - v1 = LineRenderQueue.addVertex().setPosition(12, 20, 0).getIndex(); 280 - v2 = LineRenderQueue.addVertex().setPosition(320 - 12, 20, 0).getIndex(); 281 - v3 = LineRenderQueue.addVertex().setPosition(320 - 12, 240 - 20, 0).getIndex(); 282 - v4 = LineRenderQueue.addVertex().setPosition(12, 240 - 20, 0).getIndex(); 283 - LineRenderQueue.addLine(v1, v2, v3, v4, v1); 284 - 285 - // LineRenderQueue.printContents(); 286 - 287 - RenderState.setDepthWrite(false); 288 - LineRenderQueue.render(true); 289 - RenderState.setDepthWrite(true); 290 - } 291 - 292 - private static void drawForegroundGuide(StringPrinter printer) 293 - { 294 - int v1, v2, v3, v4; 295 - RenderState.setLineWidth(1.5f); 296 - 297 - RenderState.setColor(PresetColor.GREEN); 298 - v1 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX, printer.windowBasePosY, 0).getIndex(); 299 - v2 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX, printer.windowBasePosY + printer.windowSizeY, 0).getIndex(); 300 - v3 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX + printer.windowSizeX, printer.windowBasePosY + printer.windowSizeY, 0) 301 - .getIndex(); 302 - v4 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX + printer.windowSizeX, printer.windowBasePosY, 0).getIndex(); 303 - LineRenderQueue.addLine(v1, v2, v3, v4, v1); 304 - 305 - RenderState.setColor(PresetColor.TEAL); 306 - v1 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX, printer.rewindArrowY, 0).getIndex(); 307 - v2 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX, printer.rewindArrowY + 24, 0).getIndex(); 308 - v3 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX + 24, printer.rewindArrowY + 24, 0).getIndex(); 309 - v4 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX + 24, printer.rewindArrowY, 0).getIndex(); 310 - LineRenderQueue.addLine(v1, v2, v3, v4, v1); 311 - 312 - RenderState.setColor(PresetColor.YELLOW); 313 - v1 = LineRenderQueue.addVertex().setPosition(printer.clipMinX, printer.clipMinY, 0).getIndex(); 314 - v2 = LineRenderQueue.addVertex().setPosition(printer.clipMinX, printer.clipMaxY, 0).getIndex(); 315 - v3 = LineRenderQueue.addVertex().setPosition(printer.clipMaxX, printer.clipMaxY, 0).getIndex(); 316 - v4 = LineRenderQueue.addVertex().setPosition(printer.clipMaxX, printer.clipMinY, 0).getIndex(); 317 - LineRenderQueue.addLine(v1, v2, v3, v4, v1); 318 - 319 - RenderState.setDepthWrite(false); 320 - LineRenderQueue.render(true); 321 - RenderState.setDepthWrite(true); 322 - } 323 - 324 - private static final void drawAxes(float lineWidth) 325 - { 326 - RenderState.setLineWidth(lineWidth); 327 - 328 - RenderState.setColor(PresetColor.RED); 329 - LineRenderQueue.addLine( 330 - LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(), 331 - LineRenderQueue.addVertex().setPosition(Short.MAX_VALUE, 0, 0).getIndex()); 332 - 333 - RenderState.setColor(PresetColor.GREEN); 334 - LineRenderQueue.addLine( 335 - LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(), 336 - LineRenderQueue.addVertex().setPosition(0, Short.MAX_VALUE, 0).getIndex()); 337 - 338 - LineRenderQueue.render(true); 339 - } 340 - 341 - public Vector3f getMousePosition(MouseInput mouse, boolean useDepth) 342 - { 343 - int mouseX = mouse.getPosX(); 344 - int mouseY = mouse.getPosY(); 345 - 346 - int width = editor.glCanvasWidth(); 347 - int height = editor.glCanvasHeight(); 348 - 349 - IntBuffer viewport = BufferUtils.createIntBuffer(16); 350 - viewport.put(0); 351 - viewport.put(0); 352 - viewport.put(width); 353 - viewport.put(height); 354 - viewport.rewind(); 355 - 356 - float winX = mouseX; 357 - float winY = mouseY; 358 - float winZ = 0; 359 - 360 - if (useDepth) { 361 - // this is the expensive part, reading z from the depth buffer 362 - FloatBuffer fb = BufferUtils.createFloatBuffer(1); 363 - glReadPixels(mouseX, mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, fb); 364 - winZ = fb.get(); 365 - } 366 - 367 - FloatBuffer position = BufferUtils.createFloatBuffer(3); 368 - GLUtils.gluUnProject(winX, winY, winZ, viewMatrix.toFloatBuffer(), projMatrix.toFloatBuffer(), viewport, position); 369 - 370 - return new Vector3f(position.get(), position.get(), position.get()); 371 - } 372 - 373 - public void render(MouseInput mouse, StringPrinter printer, float cameraX, float cameraY, float cameraZoom, float cameraYaw) 374 - { 375 - assert (printer != null); 376 - 377 - drawBackground(glBackgroundTexID); 378 - 379 - float halfW = (editor.glCanvasWidth() / 2.0f) * cameraZoom; 380 - float halfH = (editor.glCanvasHeight() / 2.0f) * cameraZoom; 381 - projMatrix.ortho(-halfW, halfW, halfH, -halfH, 1, 0x20000); 382 - // projMatrix.perspective(60, (float)editor.glCanvasWidth() / editor.glCanvasHeight(), 1, 0x2000); 383 - RenderState.setProjectionMatrix(projMatrix); 384 - 385 - viewMatrix.setIdentity(); 386 - viewMatrix.translate(new Vector3f(-cameraX, -cameraY, -400.0f * cameraZoom)); 387 - viewMatrix.rotate(Axis.Y, cameraYaw); 388 - RenderState.setViewMatrix(viewMatrix); 389 - RenderState.setModelMatrix(null); 390 - 391 - if (editor.shouldShowViewportGuides()) 392 - drawBackgroundGuide(printer); 393 - 394 - // drawAxes(1.0f); 395 - 396 - DrawState state = new DrawState(printer); 397 - state.useCulling = editor.isCullingEnabled(); 398 - 399 - printer.drawMessageBox(); 400 - 401 - FontShader shader = ShaderManager.use(FontShader.class); 402 - shader.enableFiltering.set(useFiltering); 403 - shader.fadeAlpha.set(1.0f); 404 - 405 - float scrollY = printer.scrollAmount * (state.currentFont.chars.defaultY * state.stringScaleY + printer.style.lineOffset); 406 - int printOffsetX = 0; 407 - int printOffsetY = -(int) (scrollY); 408 - 409 - state.printPosX = 0; 410 - state.printPosY = 0; 411 - printer.drawBuffer.rewind(); 412 - 413 - read_buf: 414 - while (printer.drawBuffer.position() < printer.printPos) { 415 - byte charByte = printer.drawBuffer.get(); 416 - int charInt = charByte & 0xFF; 417 - 418 - if (charInt == StringPrinter.PAGE_END_MARK) { 419 - continue; 420 - } 421 - else if (charInt == StringPrinter.BUFFER_FILL) { 422 - break; // end of string 423 - } 424 - else if (charInt < 0xF0) { 425 - int charWidth = MessageUtil.getCharWidth(state.currentFont, state.fontVariant, charInt, state.stringScaleX, state.charWidthOverride, 426 - 0); 427 - if (charInt < state.currentFont.chars.numChars) 428 - renderChar(printer, state, printOffsetX, printOffsetY, charInt); 429 - state.printPosX += charWidth; 430 - } 431 - else if (charInt == 0xF7 || charInt == 0xF8 || charInt == 0xF9) { 432 - int charWidth = MessageUtil.getCharWidth(state.currentFont, state.fontVariant, charInt, state.stringScaleX, state.charWidthOverride, 433 - 0); 434 - state.printPosX += charWidth; 435 - } 436 - else { 437 - switch (ControlCharacter.decodeMap.get(charByte)) { 438 - case ENDL: // 0xF0 439 - state.printPosX = 0; 440 - state.printPosY += state.currentFont.chars.defaultY * state.stringScaleY + printer.style.lineOffset; 441 - break; 442 - 443 - case NEXT: // 0xFB 444 - break; 445 - 446 - case WAIT: // 0xF1 447 - throw new IllegalStateException(this.getClass().getSimpleName() + " should not encounter WAIT"); 448 - 449 - case PAUSE: // 0xF2 450 - printer.drawBuffer.get(); 451 - throw new IllegalStateException(this.getClass().getSimpleName() + " should not encounter PAUSE"); 452 - 453 - case VARIANT0: // 0xF3 454 - case VARIANT1: // 0xF4 455 - case VARIANT2: // 0xF5 456 - case VARIANT3: // 0xF6 457 - state.fontVariant = charInt - 0xF3; 458 - break; 459 - 460 - // 0xF7-0xF9 are spaces 461 - // 0xFA = unknown 462 - 463 - case STYLE: // 0xFC 464 - handleStyle(printer, state); 465 - break; 466 - 467 - case END: // 0xFD 468 - break read_buf; 469 - 470 - // 0xFE = unused afaik 471 - case FUNC: // 0xFF 472 - handleFunction(printer, state, printOffsetX, printOffsetY); 473 - break; 474 - } 475 - } 476 - } 477 - 478 - frameCounter++; 479 - 480 - RenderState.setModelMatrix(null); 481 - if (editor.shouldShowGrid()) 482 - drawGrid(printer); 483 - 484 - // drawForegroundGuide(printer); 485 - 486 - drawUI(mouse, printer); 487 - } 488 - 489 - private void drawUI(MouseInput mouse, StringPrinter printer) 490 - { 491 - // set UI matrices 492 - TransformMatrix mtx = TransformMatrix.identity(); 493 - mtx.ortho(0, editor.glCanvasWidth(), 0, editor.glCanvasHeight(), -1, 1); 494 - RenderState.setProjectionMatrix(mtx); 495 - RenderState.setViewMatrix(null); 496 - RenderState.setModelMatrix(null); 497 - 498 - RenderState.enableDepthTest(false); 499 - 500 - if (mouse.hasLocation()) { 501 - Vector3f worldPos = getMousePosition(mouse, false); 502 - int mx = Math.round(worldPos.x) - (printer.windowBasePosX + printer.windowTextStartX); 503 - int my = Math.round(worldPos.y) - (printer.windowBasePosY + printer.windowTextStartY); 504 - drawString(0x14, 8, editor.glCanvasHeight() - 4, 16, String.format("Cursor Pos: %3d, %2d", mx, my)); 505 - } 506 - 507 - float bufferFillPercent = 100.0f * printer.compiledLength / StringPrinter.MAX_LENGTH; 508 - 509 - if (bufferFillPercent > 100.0f) { 510 - drawString(0x12, 176, editor.glCanvasHeight() - 4, 16, String.format("ERROR: String buffer at %.1f%% capacity! (%d/%d)", 511 - bufferFillPercent, printer.compiledLength, StringPrinter.MAX_LENGTH)); 512 - } 513 - else if (bufferFillPercent > 75.0f) { 514 - int palID = 5; 515 - if (bufferFillPercent > 90.0f) 516 - palID = 6; 517 - if (bufferFillPercent > 95.0f) 518 - palID = 7; 519 - drawString(palID, 176, editor.glCanvasHeight() - 4, 16, String.format("WARNING: String buffer at %.1f%% capacity! (%d/%d)", 520 - bufferFillPercent, printer.compiledLength, StringPrinter.MAX_LENGTH)); 521 - } 522 - 523 - RenderState.enableDepthTest(true); 524 - } 525 - 526 - private void handleStyle(StringPrinter printer, DrawState state) 527 - { 528 - switch (StringStyle.decodeMap.get(printer.drawBuffer.get())) { 529 - case RIGHT: 530 - case LEFT: 531 - case CENTER: 532 - case TATTLE: 533 - case CHOICE: 534 - state.textColor = 0xA; 535 - break; 536 - case INSPECT: 537 - case UPGRADE: 538 - case NARRATE: 539 - case STYLE_F: 540 - state.textColor = 0; 541 - break; 542 - case SIGN: 543 - state.textColor = 0x18; 544 - break; 545 - case LAMPPOST: 546 - state.textColor = 0x1C; 547 - break; 548 - case POSTCARD: 549 - case POPUP: 550 - case STYLE_B: 551 - state.textColor = 0; 552 - break; 553 - case EPILOGUE: 554 - state.textColor = 0; 555 - break; 556 - } 557 - } 558 - 559 - private void handleFunction(StringPrinter printer, DrawState state, int relativePosX, int relativePosY) 560 - { 561 - int startX = state.getScreenPosX(relativePosX); 562 - int startY = state.getScreenPosY(relativePosY); 563 - StringFunction func = StringFunction.decodeMap.get(printer.drawBuffer.get()); 564 - 565 - switch (func) { 566 - case CURSOR: 567 - case OPTION: 568 - case SET_CANCEL: 569 - case END_CHOICE: 570 - printer.drawBuffer.get(); 571 - break; // completely ignored by editor 572 - 573 - case VAR: 574 - printer.drawBuffer.get(); 575 - break; // already handled during encoding 576 - 577 - case FONT: 578 - int fontType = (printer.drawBuffer.get() & 0xFF); 579 - switch (fontType) { 580 - case 0: 581 - state.currentFont = FontType.Normal; 582 - break; 583 - case 1: 584 - state.currentFont = FontType.Menus; 585 - break; 586 - case 2: 587 - state.currentFont = FontType.Menus; 588 - break; 589 - case 3: 590 - state.currentFont = FontType.Title; 591 - break; 592 - case 4: 593 - state.currentFont = FontType.Subtitle; 594 - break; 595 - } 596 - break; 597 - 598 - case VARIANT: 599 - state.fontVariant = (printer.drawBuffer.get() & 0xFF); 600 - break; 601 - 602 - case ANIM_DONE: 603 - if (printer.hasAnim()) { 604 - int spriteID = printer.getAnimSprite(); 605 - int rasterID = printer.getAnimRaster(); 606 - 607 - Sprite npc = spriteLoader.getSprite(SpriteSet.Npc, spriteID); 608 - if (npc != null && !npc.areTexturesLoaded()) 609 - npc.loadTextures(); 610 - 611 - if (npc != null && npc.rasters.getSize() > rasterID) { 612 - BasicIndexedShader shader = ShaderManager.use(BasicIndexedShader.class); 613 - SpriteRaster raster = npc.rasters.get(rasterID); 614 - ImgAsset front = raster.getFront(); 615 - if (front != null) { 616 - front.img.glBind(shader.texture); 617 - front.getPalette().glBind(shader.palette); 618 - drawClippedQuad(shader, state, startX, startX + front.img.width, startY, startY + front.img.height); 619 - } 620 - } 621 - else { 622 - BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class); 623 - float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f; 624 - shader.baseColor.set(1.0f, f, f, 1.0f); 625 - drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x40); 626 - } 627 - } 628 - break; 629 - 630 - case IMAGE: 631 - printer.drawBuffer.get(); // index -- ignored 632 - int posX = printer.drawBuffer.getShort() & 0xFFFF; 633 - int posY = printer.drawBuffer.get() & 0xFF; 634 - int border = printer.drawBuffer.get() & 0xFF; 635 - int alpha = printer.drawBuffer.get() & 0xFF; 636 - int alphaStep = printer.drawBuffer.get() & 0xFF; 637 - 638 - if (varImageLoaded) { 639 - BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class); 640 - shader.texture.bind(glVarTexID); 641 - shader.multiplyBaseColor.set(true); 642 - shader.baseColor.set(1.0f, 1.0f, 1.0f, alpha / 255.0f); 643 - drawQuad(shader, posX, posX + varImage.getWidth(), posY, posY + varImage.getHeight()); 644 - } 645 - else { 646 - BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class); 647 - float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f; 648 - shader.baseColor.set(1.0f, f, f, alpha / 255.0f); 649 - drawQuad(shader, posX, posX + 150, posY, posY + 105); 650 - } 651 - break; 652 - 653 - case HIDE_IMAGE: 654 - printer.drawBuffer.get(); // fade out time 655 - break; 656 - 657 - case INLINE_IMAGE: 658 - printer.drawBuffer.get(); // index -- ignored 659 - 660 - if (varImageLoaded) { 661 - BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class); 662 - shader.texture.bind(glVarTexID); 663 - drawClippedQuad(shader, state, startX, startX + varImage.getWidth(), startY, startY + varImage.getHeight()); 664 - } 665 - else { 666 - BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class); 667 - float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f; 668 - shader.baseColor.set(1.0f, f, f, 1.0f); 669 - drawClippedQuad(shader, state, startX, startX + 0x40, startY, startY + 0x40); 670 - } 671 - break; 672 - 673 - case ITEM_ICON: 674 - int upperItemID = (printer.drawBuffer.get() & 0xFF); 675 - int lowerItemID = (printer.drawBuffer.get() & 0xFF); 676 - int itemID = (upperItemID << 8) | lowerItemID; 677 - 678 - if (glItemPreviews != null && glItemPreviews.length > itemID && glItemPreviews[itemID] != null) { 679 - BasicIndexedShader shader = ShaderManager.use(BasicIndexedShader.class); 680 - glItemPreviews[itemID].glBind(shader.texture); 681 - glItemPreviews[itemID].palette.glBind(shader.palette); 682 - drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x20); 683 - } 684 - else { 685 - BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class); 686 - float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f; 687 - shader.baseColor.set(1.0f, f, f, 1.0f); 688 - drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x20); 689 - } 690 - break; 691 - 692 - case COLOR: 693 - state.textColor = (printer.drawBuffer.get() & 0xFF); 694 - if (state.textColor < 0) 695 - state.textColor = 0; 696 - int numPals = state.currentFont.chars.numPals; 697 - if (state.textColor >= numPals) 698 - state.textColor = numPals - 1; 699 - break; 700 - 701 - case PUSH_COLOR: 702 - state.savedColor = state.textColor; 703 - break; 704 - case POP_COLOR: 705 - state.textColor = state.savedColor; 706 - break; 707 - 708 - case PUSH_POS: 709 - state.savedPosX = state.printPosX; 710 - state.savedPosY = state.printPosY; 711 - break; 712 - case POP_POS: 713 - state.printPosX = state.savedPosX; 714 - state.printPosY = state.savedPosY; 715 - break; 716 - 717 - case SPACING: 718 - state.charWidthOverride = (printer.drawBuffer.get() & 0xFF); 719 - break; 720 - 721 - case SIZE: 722 - int sx = (printer.drawBuffer.get() & 0xFF); 723 - int sy = (printer.drawBuffer.get() & 0xFF); 724 - state.stringScaleX = sx / 16.0f; 725 - state.stringScaleY = sy / 16.0f; 726 - state.charScaleX = state.stringScaleX; 727 - state.charScaleY = state.stringScaleY; 728 - break; 729 - case SIZE_RESET: 730 - state.stringScaleX = 1.0f; 731 - state.stringScaleY = 1.0f; 732 - state.charScaleX = state.stringScaleX; 733 - state.charScaleY = state.stringScaleY; 734 - break; 735 - 736 - case SET_X: // [80129EB4] 737 - int upper = (printer.drawBuffer.get() & 0xFF); 738 - int lower = (printer.drawBuffer.get() & 0xFF); 739 - state.printPosX = (upper << 8) | lower; 740 - break; 741 - case SET_Y: // [80129ED8] 742 - state.printPosY = (printer.drawBuffer.get() & 0xFF); 743 - break; 744 - case RIGHT: // [80129F0C] 745 - state.printPosX += (printer.drawBuffer.get() & 0xFF); 746 - break; 747 - case DOWN: // [80129F38] 748 - state.printPosY += (printer.drawBuffer.get() & 0xFF); 749 - break; 750 - case UP: // [80129F64] 751 - state.printPosY -= (printer.drawBuffer.get() & 0xFF); 752 - break; 753 - case CENTER_X: // [8012AAEC] 754 - state.centerPos = (printer.drawBuffer.get() & 0xFF); 755 - break; 756 - 757 - case START_FX: 758 - int startFXType = (printer.drawBuffer.get() & 0xFF); 759 - state.effectActive[startFXType] = true; 760 - switch (startFXType) { 761 - case 0x2: 762 - state.effectActive[3] = false; 763 - break; 764 - case 0x3: 765 - state.effectActive[2] = false; 766 - state.fadeNoiseAlpha = (printer.drawBuffer.get() & 0xFF) / 255.0f; 767 - break; 768 - case 0x5: 769 - state.fadeJitterArg = (printer.drawBuffer.get() & 0xFF); 770 - break; 771 - case 0x7: 772 - state.fadeAlpha = (printer.drawBuffer.get() & 0xFF) / 255.0f; 773 - break; 774 - case 0x6: 775 - case 0x9: 776 - state.savedFxColor = state.textColor; 777 - break; 778 - case 0xC: 779 - case 0xD: 780 - state.savedFxCharScaleX = state.charScaleX; 781 - state.savedFxCharScaleY = state.charScaleY; 782 - break; 783 - } 784 - break; 785 - 786 - case END_FX: 787 - int endFXType = (printer.drawBuffer.get() & 0xFF); 788 - // restore saved state (if it has been saved) 789 - if (state.effectActive[endFXType]) { 790 - switch (endFXType) { 791 - case 0x2: 792 - case 0x3: 793 - // end clears the flags for these, 794 - // but will not stop the effect since its 795 - // part of the display list 796 - break; 797 - case 0x6: 798 - case 0x9: 799 - state.textColor = state.savedFxColor; 800 - state.effectActive[endFXType] = false; 801 - break; 802 - case 0xC: 803 - case 0xD: 804 - state.charScaleX = state.savedFxCharScaleX; 805 - state.charScaleY = state.savedFxCharScaleY; 806 - state.effectActive[endFXType] = false; 807 - break; 808 - default: 809 - state.effectActive[endFXType] = false; 810 - } 811 - } 812 - break; 813 - 814 - case FUNC_03: 815 - //XXX unknown, some graphics state reset? 816 - break; 817 - 818 - case SETVOICE: 819 - case VOICE: 820 - case VOLUME: 821 - case SPEED: 822 - case SCROLL: 823 - case DELAY_OFF: 824 - case DELAY_ON: 825 - case SKIP_OFF: 826 - case INPUT_OFF: 827 - case INPUT_ON: 828 - case ENABLE_CDOWN: 829 - break; // irrelevant to renderer 830 - 831 - case SET_REWIND: 832 - printer.drawBuffer.get(); 833 - break; // irrelevant to renderer 834 - 835 - case YIELD: 836 - break; 837 - 838 - case SET_CURSOR: 839 - break; 840 - 841 - case ANIM_SPRITE: 842 - case ANIM_DELAY: 843 - case ANIM_LOOP: 844 - throw new IllegalStateException("LOGIC ERROR: " + func.name + " in encodeFunctionArgs!"); 845 - } 846 - } 847 - 848 - public void drawString(int palID, int posX, int posY, int size, String text) 849 - { 850 - FontShader shader = ShaderManager.use(FontShader.class); 851 - shader.noiseMode.set(0); 852 - shader.fadeAlpha.set(1.0f); 853 - shader.enableDropShadow.set(false); 854 - 855 - FontType font = FontType.Normal; 856 - 857 - for (char c : text.toCharArray()) { 858 - int index = StringConstants.getIndex(c, true); 859 - if (index < 0) 860 - continue; 861 - 862 - int endX = posX + (int) (font.chars.defaultX * size / 16.0f); 863 - int endY = posY - (int) (font.chars.defaultY * size / 16.0f); 864 - int charWidth = MessageUtil.getCharWidth(font, 0, index, size / 16.0f, 0, 0); 865 - 866 - if (index < font.chars.numChars) { 867 - font.chars.images[index].glBind(shader.texture); 868 - font.chars.palettes[palID].glBind(shader.palette); 869 - drawQuad(shader, posX, endX, posY, endY); 870 - } 871 - posX += charWidth; 872 - } 873 - } 874 - 875 - private void renderChar(StringPrinter printer, DrawState state, int relativePosX, int relativePosY, int charIndex) 876 - { 877 - FontShader shader = ShaderManager.use(FontShader.class); 878 - 879 - int[] lookahead = new int[4]; 880 - for (int i = 0; i < lookahead.length; i++) 881 - lookahead[i] = (printer.drawBuffer.get() & 0xFF); 882 - printer.drawBuffer.position(printer.drawBuffer.position() - lookahead.length); 883 - 884 - //XXX correct? 885 - state.charScaleX = state.stringScaleX; 886 - state.charScaleY = state.stringScaleY; 887 - float alpha = 1.0f; 888 - 889 - if (state.effectActive[BLUR.code]) // 0x20 890 - { 891 - // fade code from [8012ADC4] 892 - alpha = 0.35f; 893 - } 894 - 895 - if (state.effectActive[SHAKE.code]) { 896 - // code from [8012AE50] 897 - relativePosX += rng.nextInt() % 2; 898 - relativePosY += rng.nextInt() % 2; 899 - } 900 - 901 - if (state.effectActive[WAVE.code]) // 0x2 902 - { 903 - // code from [8012AEBC] 904 - double dsx = state.stringScaleX - 1.0; 905 - double dsy = state.stringScaleY - 1.0; 906 - 907 - //NOTE: game uses a message-specific 'local' frame counter here 908 - double angle = frameCounter * (int) (20.0 - dsx * 5.0) - state.visibleCharCount * (int) (45.0 - dsx * 15.0); 909 - relativePosX += Math.cos(Math.toRadians(angle)) * (dsx + 1.6); 910 - relativePosY += Math.cos(Math.toRadians(angle + 270.0)) * (dsy + 1.6); 911 - } 912 - if (state.effectActive[GLOBAL_WAVE.code]) // 0x200 913 - { 914 - // code from [8012B0BC] 915 - double dsx = state.stringScaleX - 1.0; 916 - double dsy = state.stringScaleY - 1.0; 917 - 918 - //NOTE: game uses a 'global' frame counter shared by all messages here 919 - double angle = frameCounter * (int) (20.0 - dsx * 5.0) - state.visibleCharCount * 45.0; 920 - relativePosX += Math.cos(Math.toRadians(angle)) * (dsx + 1.6); 921 - relativePosY += Math.cos(Math.toRadians(angle + 270.0)) * (dsy + 1.6); 922 - } 923 - 924 - if (state.effectActive[RAINBOW.code] || state.effectActive[GLOBAL_RAINBOW.code]) // 0x440 -- either rainbow 925 - { 926 - // code from [8012B1B4] 927 - 928 - // NOTE: global overrides local here, but they cant stack so we dont need to represent it 929 - int i = Math.abs(state.visibleCharCount - frameCounter / 3); 930 - state.textColor = i % 10; // original code: = i + (i / 10) * -10; 931 - } 932 - 933 - // properly respect precedence of these effects 934 - if (state.effectActive[RISE_PRINT.code] || state.effectActive[GROW_PRINT.code]) { 935 - if (!printer.donePrinting 936 - && (lookahead[0] != ControlCharacter.ENDL.code) && (lookahead[1] != ControlCharacter.ENDL.code) 937 - && (lookahead[2] != ControlCharacter.ENDL.code) && (lookahead[3] != ControlCharacter.ENDL.code)) { 938 - if (state.effectActive[RISE_PRINT.code]) { 939 - // from [8012B4F0] 940 - float dummyScale = 0.25f; //XXX needed to match, unknown why 941 - if (lookahead[0] == StringPrinter.BUFFER_FILL) { 942 - state.charScaleX = 1.7f * state.stringScaleX; 943 - state.charScaleY = 1.7f * state.stringScaleY; 944 - relativePosX -= 6.0f * state.stringScaleY; 945 - relativePosY -= dummyScale * 6.0f * state.stringScaleY; 946 - } 947 - else if (lookahead[1] == StringPrinter.BUFFER_FILL) { 948 - state.charScaleX = 1.4f * state.stringScaleX; 949 - state.charScaleY = 1.4f * state.stringScaleY; 950 - relativePosX -= 3.0f * state.stringScaleY; 951 - relativePosY -= dummyScale * 3.0f * state.stringScaleY; 952 - } 953 - else if (lookahead[2] == StringPrinter.BUFFER_FILL) { 954 - state.charScaleX = 1.2f * state.stringScaleX; 955 - state.charScaleY = 1.2f * state.stringScaleY; 956 - relativePosX -= 2.0f * state.stringScaleY; 957 - relativePosY -= dummyScale * 2.0f * state.stringScaleY; 958 - } 959 - } 960 - else if (state.effectActive[GROW_PRINT.code]) { 961 - // from [8012B740] 962 - if (lookahead[0] == StringPrinter.BUFFER_FILL) { 963 - state.charScaleX = 0.3f * state.stringScaleX; 964 - state.charScaleY = 0.3f * state.stringScaleY; 965 - relativePosX += 5; 966 - relativePosY += 5; 967 - } 968 - else if (lookahead[1] == StringPrinter.BUFFER_FILL) { 969 - state.charScaleX = 0.5f * state.stringScaleX; 970 - state.charScaleY = 0.5f * state.stringScaleY; 971 - relativePosX += 3; 972 - relativePosY += 3; 973 - } 974 - else if (lookahead[2] == StringPrinter.BUFFER_FILL) { 975 - state.charScaleX = 0.75f * state.stringScaleX; 976 - state.charScaleY = 0.75f * state.stringScaleY; 977 - relativePosX += 2; 978 - relativePosY += 2; 979 - } 980 - } 981 - } 982 - } 983 - else if (state.effectActive[SIZE_JITTER.code] || state.effectActive[SIZE_WAVE.code]) { 984 - float scale = 1.0f; 985 - 986 - if (state.effectActive[SIZE_JITTER.code]) // 0x2000 -- size jitter 987 - { 988 - // code from [8012B8BC] 989 - scale = 0.75f + 0.5f * (rng.nextInt(101) / 100.0f); 990 - } 991 - else if (state.effectActive[SIZE_WAVE.code]) // 0x4000 -- size wave 992 - { 993 - // code from [8012BA24] 994 - int i = (frameCounter - state.visibleCharCount) * 15; 995 - scale = 1.0f + 0.25f * (float) Math.cos(Math.toRadians(i + ((i >> 3) / 45) * 360.0)); 996 - } 997 - 998 - state.charScaleX *= scale; 999 - state.charScaleY *= scale; 1000 - 1001 - if (scale >= 1.0) { 1002 - // [8012BACC] 1003 - int posOffset = (int) (scale * 8.0 - 8.5); 1004 - relativePosX -= posOffset; 1005 - relativePosY -= posOffset; 1006 - } 1007 - else { 1008 - // [8012BB7C] 1009 - int posOffset = (int) (8.0 - 8.0 * scale); 1010 - relativePosX += posOffset; 1011 - relativePosY += posOffset; 1012 - } 1013 - } 1014 - 1015 - shader.noiseMode.set(0); // initial value 1016 - 1017 - if (state.effectActive[DITHER_FADE.code]) //0x80 -- fade 1018 - { 1019 - alpha *= state.fadeAlpha; 1020 - shader.noiseMode.set(7); 1021 - shader.noiseAlpha.set(state.fadeAlpha); 1022 - shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat()); 1023 - } 1024 - else { 1025 - if (state.effectActive[NOISE_OUTLINE.code]) // 0x04 -- noise 1026 - { 1027 - shader.noiseMode.set(2); 1028 - shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat()); 1029 - 1030 - // add Gfx: 1031 - // SET_COMBINE FC70FEE1 FFFFF3F9 1032 - 1033 - // color: G_CCMUX_NOISE * G_CCMUX_TEXEL0 1034 - // alpha: G_ACMUX_TEXEL0 1035 - } 1036 - 1037 - if (state.effectActive[STATIC.code]) // 0x10000 -- faded noise 1038 - { 1039 - shader.noiseMode.set(3); 1040 - shader.noiseAlpha.set(state.fadeNoiseAlpha); 1041 - shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat()); 1042 - 1043 - // add Gfx: 1044 - // SET_ENVCOLOR FB000000 arg << 0x18 | arg << 0x10 | arg << 8; 1045 - // SET_COMBINE FC72FEE5 11FCF279 1046 - 1047 - // color: (G_CCMUX_NOISE - G_CCMUX_TEXEL0) * G_CCMUX_ENVIRONMENT + G_CCMUX_TEXEL0 1048 - // alpha: G_ACMUX_TEXEL0 1049 - } 1050 - } 1051 - 1052 - shader.fadeAlpha.set(alpha); 1053 - 1054 - int baseOffset = 0; 1055 - if (state.fontVariant < state.currentFont.numVariants && state.fontVariant >= 0) 1056 - baseOffset = state.currentFont.baseHeightOffset[state.fontVariant]; 1057 - 1058 - int startX = state.getScreenPosX(relativePosX); 1059 - int startY = state.getScreenPosY(relativePosY + baseOffset); 1060 - int endX = startX + (int) (state.currentFont.chars.defaultX * state.charScaleX); 1061 - int endY = startY + (int) (state.currentFont.chars.defaultY * state.charScaleY); 1062 - 1063 - if (state.effectActive[DROP_SHADOW.code]) // 0x8000 -- drop shadow 1064 - { 1065 - shader.enableDropShadow.set(true); 1066 - drawFontQuad(shader, state, 1067 - state.currentFont.chars.images[charIndex], 1068 - state.currentFont.chars.palettes[state.getColor()], 1069 - startX + 2, endX + 2, startY + 2, endY + 2); 1070 - shader.enableDropShadow.set(false); 1071 - } 1072 - 1073 - if (state.effectActive[BLUR.code]) // 0x20 -- FadedJitter 1074 - { 1075 - // code from [8012BDF4] 1076 - for (int i = 0; i < 5; i++) { 1077 - int jx = (state.fadeJitterArg == 2) ? 0 : rng.nextInt(3) - 1; 1078 - int jy = (state.fadeJitterArg == 1) ? 0 : rng.nextInt(3) - 1; 1079 - 1080 - drawFontQuad(shader, state, 1081 - state.currentFont.chars.images[charIndex], 1082 - state.currentFont.chars.palettes[state.getColor()], 1083 - startX + jx, endX + jx, startY + jy, endY + jy); 1084 - } 1085 - } 1086 - else { 1087 - drawFontQuad(shader, state, 1088 - state.currentFont.chars.images[charIndex], 1089 - state.currentFont.chars.palettes[state.getColor()], 1090 - startX, endX, startY, endY); 1091 - } 1092 - 1093 - state.visibleCharCount++; 1094 - } 1095 - 1096 - private static class DrawState 1097 - { 1098 - public final StringPrinter printer; 1099 - 1100 - private FontType currentFont = FontType.Normal; 1101 - public int fontVariant = 0; 1102 - 1103 - private boolean[] effectActive; 1104 - private float fadeAlpha = 1.0f; 1105 - private float fadeNoiseAlpha = 0; 1106 - private int fadeJitterArg = 0; 1107 - 1108 - private int textColor = 0xA; 1109 - 1110 - private int visibleCharCount = 0; 1111 - 1112 - private boolean useCulling = true; 1113 - 1114 - private int printPosX = 0; 1115 - private int printPosY = 0; 1116 - 1117 - private int centerPos = 0; 1118 - 1119 - private int savedColor; 1120 - private int savedPosX = 0; 1121 - private int savedPosY = 0; 1122 - private int savedFxColor = -1; 1123 - private float savedFxCharScaleX = 1.0f; 1124 - private float savedFxCharScaleY = 1.0f; 1125 - 1126 - private int charWidthOverride = 0; 1127 - 1128 - private float charScaleX = 1.0f; 1129 - private float charScaleY = 1.0f; 1130 - 1131 - private float stringScaleX = 1.0f; 1132 - private float stringScaleY = 1.0f; 1133 - 1134 - private DrawState(StringPrinter printer) 1135 - { 1136 - this.printer = printer; 1137 - effectActive = new boolean[StringConstants.StringEffect.values().length]; 1138 - } 1139 - 1140 - public int getColor() 1141 - { 1142 - switch (currentFont) { 1143 - case Normal: 1144 - case Menus: 1145 - default: 1146 - return textColor; 1147 - case Title: 1148 - case Subtitle: 1149 - return 0; 1150 - } 1151 - } 1152 - 1153 - public int getScreenPosX(int offsetX) 1154 - { 1155 - int centerOffset = 0; 1156 - if (centerPos == 0xFF) 1157 - centerOffset = 160 - (printer.stringWidth / 2); 1158 - else if (centerPos != 0) 1159 - centerOffset = centerPos - (printer.stringWidth / 2); 1160 - 1161 - if (centerOffset == 0) 1162 - return printer.windowBasePosX + printer.windowTextStartX + printPosX + offsetX; 1163 - else 1164 - return centerOffset + printPosX + offsetX; 1165 - } 1166 - 1167 - public int getScreenPosY(int offsetY) 1168 - { 1169 - return printer.windowBasePosY + printer.windowTextStartY + printPosY + offsetY; 1170 - } 1171 - } 1172 - 1173 - private void drawFontQuad(FontShader shader, DrawState state, Tile img, Palette pal, float x1, float x2, float y1, float y2) 1174 - { 1175 - img.glBind(shader.texture); 1176 - pal.glBind(shader.palette); 1177 - shader.noise.bind(glNoiseTexID); 1178 - drawClippedQuad(shader, state, x1, x2, y1, y2); 1179 - } 1180 - 1181 - private static final void drawClippedQuad(BaseShader shader, DrawState state, float x1, float x2, float y1, float y2) 1182 - { 1183 - if (state.useCulling) 1184 - drawClippedQuad(shader, state.printer, x1, x2, y1, y2); 1185 - else 1186 - drawQuad(shader, x1, x2, y1, y2); 1187 - } 1188 - 1189 - private static final void drawClippedQuad(BaseShader shader, StringPrinter printer, float x1, float x2, float y1, float y2) 1190 - { 1191 - float x1c = x1; 1192 - float x2c = x2; 1193 - 1194 - float y1c = y1; 1195 - float y2c = y2; 1196 - 1197 - float u1c = 0.0f; 1198 - float u2c = 1.0f; 1199 - 1200 - float v1c = 0.0f; 1201 - float v2c = 1.0f; 1202 - 1203 - assert (x1 < x2); 1204 - assert (y1 < y2); 1205 - 1206 - if ((x2 < printer.clipMinX) || (x1 > printer.clipMaxX) || (y2 < printer.clipMinY) || (y1 > printer.clipMaxY)) 1207 - return; 1208 - 1209 - if (x1 < printer.clipMinX) { 1210 - x1c = printer.clipMinX; 1211 - u1c = ((printer.clipMinX - x1) / (x2 - x1)); 1212 - } 1213 - 1214 - if (x2 > printer.clipMaxX) { 1215 - x2c = printer.clipMaxX; 1216 - u2c = 1.0f - ((x2 - printer.clipMaxX) / (x2 - x1)); 1217 - } 1218 - 1219 - if (y1 < printer.clipMinY) { 1220 - y1c = printer.clipMinY; 1221 - v2c = 1.0f - ((printer.clipMinY - y1) / (y2 - y1)); 1222 - } 1223 - 1224 - if (y2 > printer.clipMaxY) { 1225 - y2c = printer.clipMaxY; 1226 - v1c = ((y2 - printer.clipMaxY) / (y2 - y1)); 1227 - } 1228 - 1229 - shader.setQuadTexCoords(u1c, v1c, u2c, v2c); 1230 - shader.setXYQuadCoords(x1c, y2c, x2c, y1c, 0); // y flipped 1231 - shader.renderQuad(); 1232 - } 1233 - 1234 - private static final void drawQuad(BaseShader shader, float x1, float x2, float y1, float y2) 1235 - { 1236 - shader.setQuadTexCoords(0, 0, 1, 1); 1237 - shader.setXYQuadCoords(x1, y2, x2, y1, 0); // y flipped 1238 - shader.renderQuad(); 1239 - } 1240 - }
+6 -6
src/main/java/game/message/editor/StringTokenizer.java src/main/java/game/message/editor/MessageTokenizer.java
··· 8 8 import app.input.Line; 9 9 import game.message.MessageAnim; 10 10 11 - public class StringTokenizer 11 + public class MessageTokenizer 12 12 { 13 13 public static void main(String[] args) 14 14 { 15 15 String text = "%This [is] [[a] [] TE\\\\\\ST[b"; 16 - (new StringTokenizer(text)).print(); 16 + (new MessageTokenizer(text)).print(); 17 17 } 18 18 19 19 private void print() ··· 28 28 29 29 public static ArrayList<Sequence> tokenize(String text) 30 30 { 31 - return new StringTokenizer(text).sequences; 31 + return new MessageTokenizer(text).sequences; 32 32 } 33 33 34 34 public static ArrayList<Sequence> tokenize(List<Line> lines) 35 35 { 36 - return new StringTokenizer(lines).sequences; 36 + return new MessageTokenizer(lines).sequences; 37 37 } 38 38 39 - private StringTokenizer(String text) 39 + private MessageTokenizer(String text) 40 40 { 41 41 add(text, null); 42 42 } 43 43 44 - private StringTokenizer(List<Line> lines) 44 + private MessageTokenizer(List<Line> lines) 45 45 { 46 46 for (Line line : lines) 47 47 add(line.str, line);
+2 -2
src/main/java/game/sprite/editor/ShortcutListPanel.java src/main/java/game/sprite/editor/SpriteShortcutsPanel.java
··· 8 8 9 9 import net.miginfocom.swing.MigLayout; 10 10 11 - public class ShortcutListPanel extends JPanel 11 + public class SpriteShortcutsPanel extends JPanel 12 12 { 13 - public ShortcutListPanel() 13 + public SpriteShortcutsPanel() 14 14 { 15 15 setLayout(new MigLayout("fill")); 16 16
+20 -9
src/main/java/game/sprite/editor/SpriteEditor.java
··· 611 611 } 612 612 613 613 public SpriteAnimation getAnimation() 614 - { return currentAnim; } 614 + { 615 + return currentAnim; 616 + } 615 617 616 618 private void setComponent(int id, boolean fromTabChange) 617 619 { ··· 649 651 } 650 652 651 653 public ImgAsset getSelectedImage() 652 - { return selectedImgAsset; } 654 + { 655 + return selectedImgAsset; 656 + } 653 657 654 658 private void setPalette(SpritePalette pm) 655 659 { ··· 702 706 if (sprite != null && currentAnim != null && currentComp != null && currentComp.selected) { 703 707 if (currentAnim.components.size() > 1) { 704 708 SwingUtilities.invokeLater(() -> { 705 - if (JOptionPane.YES_OPTION == super.showConfirmDialog("Delete component?", "Confirm")) { 709 + if (JOptionPane.YES_OPTION == super.getConfirmDialog("Confirm", "Delete component?").choose()) { 706 710 invokeLater(() -> { 707 711 currentAnim.components.removeElement(currentComp); 708 712 sprite.recalculateIndices(); ··· 968 972 try { 969 973 int id = SpriteLoader.getMaximumID(spriteSet) + 1; 970 974 SpriteLoader.create(spriteSet, id); 971 - 975 + 972 976 if(spriteSet == SpriteSet.Npc) 973 977 useNpcFiles(id); 974 978 else 975 979 usePlayerFiles(id); 976 - 980 + 977 981 } catch (Throwable t) { 978 982 Logger.logError("Failed to create new sprite."); 979 983 incrementDialogsOpen(); ··· 983 987 }); 984 988 }); 985 989 menu.add(item); 986 - 990 + 987 991 menu.addSeparator(); 988 992 */ 989 993 ··· 1439 1443 return; 1440 1444 1441 1445 ListEditPanel<SpriteAnimation> listPanel = new AnimationListEditPanel(sprite, sprite.animations, this); 1442 - showOptionDialog(listPanel, "Edit " + sprite + " Animations", new String[] { "Done" }); 1446 + getOptionDialog("Edit " + sprite + " Animations", listPanel).setOptions("Done").choose(); 1443 1447 1444 1448 invokeLater(() -> { 1445 1449 setSprite(spriteID, false); ··· 1456 1460 return; 1457 1461 1458 1462 ListEditPanel<SpriteComponent> listPanel = new ComponentListEditPanel(currentAnim, currentAnim.components); 1459 - showOptionDialog(listPanel, "Edit " + currentAnim + " Components", new String[] { "Done" }); 1463 + getOptionDialog("Edit " + currentAnim + " Components", listPanel).setOptions("Done").choose(); 1460 1464 1461 1465 invokeLater(() -> { 1462 1466 sprite.recalculateIndices(); ··· 1474 1478 private void showControls() 1475 1479 { 1476 1480 incrementDialogsOpen(); 1477 - SwingUtils.showFramedMessageDialog(getFrame(), new ShortcutListPanel(), "Controls and Shortcuts", JOptionPane.PLAIN_MESSAGE); 1481 + 1482 + SwingUtils.getMessageDialog() 1483 + .setParent(getFrame()) 1484 + .setTitle("Controls and Shortcuts") 1485 + .setMessage(new SpriteShortcutsPanel()) 1486 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 1487 + .show(); 1488 + 1478 1489 decrementDialogsOpen(); 1479 1490 } 1480 1491
+21 -17
src/main/java/game/texture/editor/ImageEditor.java
··· 53 53 import game.texture.editor.dialogs.ConvertOptionsPanel.ConvertSettings; 54 54 import game.texture.editor.dialogs.ConvertOptionsPanel.ConvertSettings.IntensityMethod; 55 55 import game.texture.editor.dialogs.CreateOptionsPanel; 56 + import game.texture.editor.dialogs.ImageShortcutsPanel; 56 57 import game.texture.editor.dialogs.ImportOptionsPanel; 57 58 import game.texture.editor.dialogs.ResizeOptionsPanel; 58 59 import game.texture.editor.dialogs.ResizeOptionsPanel.ResizeOptions; 59 - import game.texture.editor.dialogs.ShorcutListPanel; 60 60 import net.miginfocom.swing.MigLayout; 61 61 import renderer.buffers.LineRenderQueue; 62 62 import renderer.shaders.RenderState; ··· 302 302 303 303 private void showControls() 304 304 { 305 - JPanel panel = new JPanel(); 306 - panel.add(new ShorcutListPanel()); 307 - 308 305 incrementDialogsOpen(); 309 - SwingUtils.showFramedMessageDialog(getFrame(), new ShorcutListPanel(), "Controls and Shortcuts", JOptionPane.PLAIN_MESSAGE); 306 + 307 + SwingUtils.getMessageDialog() 308 + .setParent(getFrame()) 309 + .setTitle("Controls and Shortcuts") 310 + .setMessage(new ImageShortcutsPanel()) 311 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 312 + .show(); 313 + 310 314 decrementDialogsOpen(); 311 315 } 312 316 ··· 854 858 855 859 private File promptOverwrite(File file) 856 860 { 857 - int choice = showOptionDialog( 858 - "File already exists: \n" + file.getName(), 859 - "Export Image", new String[] { "Overwrite", "Choose File", "Cancel" }); 861 + int choice = getOptionDialog("Export Image", "File already exists: \n" + file.getName()) 862 + .setOptions("Overwrite", "Choose File", "Cancel") 863 + .choose(); 860 864 861 865 if (choice == 0) 862 866 return file; ··· 901 905 assert (SwingUtilities.isEventDispatchThread()); 902 906 903 907 CreateOptionsPanel createOptions = new CreateOptionsPanel(); 904 - int choice = ImageEditor.super.showConfirmDialog(createOptions, "New Image Options"); 908 + int choice = ImageEditor.super.getConfirmDialog("New Image Options", createOptions).choose(); 905 909 if (choice != JOptionPane.OK_OPTION) 906 910 return; 907 911 ··· 964 968 assert (SwingUtilities.isEventDispatchThread()); 965 969 966 970 ImportOptionsPanel importOptions = new ImportOptionsPanel(); 967 - int choice = ImageEditor.super.showConfirmDialog(importOptions, "Import Options"); 971 + int choice = ImageEditor.super.getConfirmDialog("Import Options", importOptions).choose(); 968 972 if (choice != JOptionPane.OK_OPTION) 969 973 return; 970 974 ··· 976 980 } 977 981 catch (ImageFormatException e) { 978 982 if (importOptions.getFormat().type == TileFormat.TYPE_CI) { 979 - choice = ImageEditor.super.showConfirmDialog( 980 - "Image file is not color-indexed. \nWould you like to convert it?", "Incorrect Image Format"); 983 + choice = ImageEditor.super.getConfirmDialog( 984 + "Incorrect Image Format", "Image file is not color-indexed. \nWould you like to convert it?").choose(); 981 985 if (choice != JOptionPane.OK_OPTION) 982 986 return; 983 987 ··· 1012 1016 assert (SwingUtilities.isEventDispatchThread()); 1013 1017 1014 1018 ImportOptionsPanel importOptions = new ImportOptionsPanel(); 1015 - int choice = ImageEditor.super.showConfirmDialog(importOptions, "Import Options"); 1019 + int choice = ImageEditor.super.getConfirmDialog("Import Options", importOptions).choose(); 1016 1020 if (choice != JOptionPane.OK_OPTION) 1017 1021 return null; 1018 1022 ··· 1058 1062 importFileChooser.setDirectoryContaining(image.source.getParentFile()); 1059 1063 if (importFileChooser.prompt() == ChooseDialogResult.APPROVE) { 1060 1064 ImportOptionsPanel importOptions = new ImportOptionsPanel(); 1061 - int choice = ImageEditor.super.showConfirmDialog(importOptions, "Import Options"); 1065 + int choice = ImageEditor.super.getConfirmDialog("Import Options", importOptions).choose(); 1062 1066 if (choice != JOptionPane.OK_OPTION) 1063 1067 return; 1064 1068 ··· 1084 1088 return; 1085 1089 1086 1090 ResizeOptionsPanel resizeOptionsPanel = new ResizeOptionsPanel(); 1087 - int choice = ImageEditor.super.showConfirmDialog(resizeOptionsPanel, "Resize Image Options"); 1091 + int choice = ImageEditor.super.getConfirmDialog("Resize Image Options", resizeOptionsPanel).choose(); 1088 1092 if (choice != JOptionPane.OK_OPTION) 1089 1093 return; 1090 1094 ··· 1103 1107 return; 1104 1108 1105 1109 ConvertOptionsPanel convertOptionsPanel = new ConvertOptionsPanel(); 1106 - int choice = ImageEditor.super.showConfirmDialog(convertOptionsPanel, "Convert Image Options"); 1110 + int choice = ImageEditor.super.getConfirmDialog("Convert Image Options", convertOptionsPanel).choose(); 1107 1111 if (choice != JOptionPane.OK_OPTION) 1108 1112 return; 1109 1113 ··· 1191 1195 else 1192 1196 image.draw(mousePixelX, mousePixelY, pickedPixel); 1193 1197 } 1194 - 1198 + 1195 1199 if(mouseManager.holdingRMB && mousePixelValid) 1196 1200 image.deselect(mousePixelX, mousePixelY); 1197 1201 */
+2 -2
src/main/java/game/texture/editor/dialogs/ShorcutListPanel.java src/main/java/game/texture/editor/dialogs/ImageShortcutsPanel.java
··· 7 7 8 8 import net.miginfocom.swing.MigLayout; 9 9 10 - public class ShorcutListPanel extends JPanel 10 + public class ImageShortcutsPanel extends JPanel 11 11 { 12 - public ShorcutListPanel() 12 + public ImageShortcutsPanel() 13 13 { 14 14 setLayout(new MigLayout("fill", "[50%][50%]")); 15 15
+2 -2
src/main/java/game/worldmap/ShorcutListPanel.java src/main/java/game/worldmap/WorldShortcutsPanel.java
··· 7 7 8 8 import net.miginfocom.swing.MigLayout; 9 9 10 - public class ShorcutListPanel extends JPanel 10 + public class WorldShortcutsPanel extends JPanel 11 11 { 12 - public ShorcutListPanel() 12 + public WorldShortcutsPanel() 13 13 { 14 14 setLayout(new MigLayout("fill", "[45%]32[45%]")); 15 15
+8 -2
src/main/java/game/worldmap/WorldMapEditor.java
··· 667 667 private void showControls() 668 668 { 669 669 incrementDialogsOpen(); 670 - SwingUtils.showFramedMessageDialog(getFrame(), new ShorcutListPanel(), 671 - "Controls and Shortcuts", JOptionPane.PLAIN_MESSAGE); 670 + 671 + SwingUtils.getMessageDialog() 672 + .setParent(getFrame()) 673 + .setTitle("Controls and Shortcuts") 674 + .setMessage(new WorldShortcutsPanel()) 675 + .setMessageType(JOptionPane.PLAIN_MESSAGE) 676 + .show(); 677 + 672 678 decrementDialogsOpen(); 673 679 } 674 680
+7 -2
src/main/java/util/ui/FilteredListPanel.java
··· 52 52 if (evt.getButton() != MouseEvent.BUTTON1) { 53 53 return; 54 54 } 55 - 55 + 56 56 if (evt.getClickCount() == 1) { 57 57 Rectangle rect = list.getCellBounds(0, list.getLastVisibleIndex()); 58 58 if (rect != null && !rect.contains(evt.getPoint())) { 59 59 list.clearSelection(); 60 60 } 61 61 } 62 - 62 + 63 63 if (evt.getClickCount() == 2) { 64 64 Rectangle rect = list.getCellBounds(0, list.getLastVisibleIndex()); 65 65 if (rect != null && rect.contains(evt.getPoint())) { ··· 156 156 157 157 public T getSelected() 158 158 { return list.getSelectedValue(); } 159 + 160 + public void setSelected(T value) 161 + { 162 + list.setSelectedValue(value, true); 163 + } 159 164 }