saved = new ArrayList<>();
- for (MessageGroup res : resourcesToSave) {
+ for (MessageAsset res : resourcesToSave) {
res.saveChanges();
saved.add(res);
}
@@ -936,8 +936,8 @@ public void textChanged(DocumentEvent e)
modified = true;
workingString.setModified();
}
- resourcePanel.repaint();
- stringListPanel.repaint();
+ assetListTab.repaint();
+ messageListTab.repaint();
}
}
@@ -976,12 +976,12 @@ public void actionPerformed(ActionEvent e)
addEditorMenu(menuBar);
addOptionsMenu(menuBar);
- stringListPanel = new MessageListTab(this);
- resourcePanel = new AssetListTab(this, stringListPanel);
+ messageListTab = new MessageListTab(this);
+ assetListTab = new AssetListTab(this, messageListTab);
tabs = new JTabbedPane();
- createTab(tabs, "Assets", resourcePanel);
- createTab(tabs, "Messages", stringListPanel);
+ createTab(tabs, "Assets", assetListTab);
+ createTab(tabs, "Messages", messageListTab);
createTab(tabs, "Variables", makeVariablesTab());
// wrap input pane in a scroll pane to let us scroll
@@ -1034,6 +1034,11 @@ public void redoEDT()
}
}
+ public boolean hasMessage(String name)
+ {
+ return assetListTab.hasMessage(name);
+ }
+
private static void createTab(JTabbedPane tabs, String name, Container contents)
{
JLabel lbl = SwingUtils.getLabel(name, 12);
@@ -1126,18 +1131,17 @@ private JPanel makeVariablesTab()
textArea.append(String.format("%n"));
super.incrementDialogsOpen();
- String[] options = { "Copy to Clipboard" };
- int selection = SwingUtils.showFramedOptionDialog(null,
- detailScrollPane,
- "Patch for Loading Image",
- JOptionPane.YES_NO_CANCEL_OPTION,
- JOptionPane.PLAIN_MESSAGE,
- Environment.ICON_DEFAULT,
- options,
- options[0]);
+ int choice = SwingUtils.getOptionDialog()
+ .setTitle("Code for Loading Image")
+ .setMessage(detailScrollPane)
+ .setMessageType(JOptionPane.PLAIN_MESSAGE)
+ .setOptionsType(JOptionPane.YES_NO_CANCEL_OPTION)
+ .setIcon(Environment.ICON_DEFAULT)
+ .setOptions("Copy to Clipboard")
+ .choose();
super.decrementDialogsOpen();
- if (selection == 0) {
+ if (choice == 0) {
StringSelection stringSelection = new StringSelection(textArea.getText());
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.setContents(stringSelection, null);
@@ -1238,7 +1242,7 @@ private void addFileMenu(JMenuBar menuBar, ActionListener openLogAction)
awtKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
item.setAccelerator(awtKeyStroke);
item.addActionListener((e) -> {
- resourcePanel.saveChanges();
+ assetListTab.saveChanges();
});
menu.add(item);
@@ -1301,7 +1305,14 @@ private void addEditorMenu(JMenuBar menuBar)
item = new JMenuItem("View Tips");
item.addActionListener((e) -> {
incrementDialogsOpen();
- SwingUtils.showFramedMessageDialog(getFrame(), new ControlsPanel(), "Controls", JOptionPane.PLAIN_MESSAGE);
+
+ SwingUtils.getMessageDialog()
+ .setParent(getFrame())
+ .setTitle("Message Editor Pro Tips")
+ .setMessage(new MessageTipsPanel())
+ .setMessageType(JOptionPane.PLAIN_MESSAGE)
+ .show();
+
decrementDialogsOpen();
});
menu.add(item);
@@ -1329,7 +1340,7 @@ private void addOptionsMenu(JMenuBar menuBar)
@Override
protected void saveChanges()
{
- resourcePanel.saveChanges();
+ assetListTab.saveChanges();
handleSaving();
}
@@ -1337,7 +1348,7 @@ protected void saveChanges()
public void glInit()
{
try {
- renderer = new StringRenderer(this);
+ renderer = new MessageRenderer(this);
}
catch (Throwable t) {
StarRodMain.displayStackTrace(t);
@@ -1361,18 +1372,18 @@ public boolean printDelayEnabled()
}
public boolean isCullingEnabled()
- { return cbCulling.isSelected(); }
+ {
+ return cbCulling.isSelected();
+ }
- public static class ControlsPanel extends JPanel
+ public static class MessageTipsPanel extends JPanel
{
- public ControlsPanel()
+ public MessageTipsPanel()
{
JTextPane tx = new JTextPane();
tx.setContentType("text/html");
tx.setText(""
- + "String Editor Tips
"
- + "RIGHT CLICK on items in the resource tab to see available actions
"
- + "You can insert newline tags in the text field with SHIFT + ENTER
"
+ + "You can quickly insert newline tags with SHIFT + ENTER
"
+ "");
tx.setEditable(false);
add(tx);
diff --git a/src/main/java/game/message/editor/MessageListTab.java b/src/main/java/game/message/editor/MessageListTab.java
index 0c1d01d..a7bfca8 100644
--- a/src/main/java/game/message/editor/MessageListTab.java
+++ b/src/main/java/game/message/editor/MessageListTab.java
@@ -2,9 +2,7 @@
import java.awt.Color;
import java.awt.Component;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.JButton;
@@ -15,8 +13,6 @@
import javax.swing.ListCellRenderer;
import app.SwingUtils;
-import assets.AssetHandle;
-import assets.AssetManager;
import game.message.Message;
import net.miginfocom.swing.MigLayout;
import util.Logger;
@@ -24,10 +20,15 @@
public class MessageListTab extends JPanel
{
- private FilteredListPanel filteredList;
+ private final MessageEditor editor;
+ private final FilteredListPanel filteredList;
+
+ private MessageAsset asset;
public MessageListTab(MessageEditor editor)
{
+ this.editor = editor;
+
filteredList = new FilteredListPanel<>(new MessageCellRenderer()) {
@Override
public String getFilterableText(Message msg)
@@ -44,68 +45,140 @@ public void handleSelection(Message msg)
}
};
+ JButton createButton = new JButton("Create");
+ createButton.addActionListener((e) -> createMessage());
+
+ JButton deleteButton = new JButton("Delete");
+ deleteButton.addActionListener((e) -> deleteMessage());
+ deleteButton.setEnabled(false); //TODO
+
JButton renameButton = new JButton("Rename");
renameButton.addActionListener((e) -> renameMessage());
- JButton createButton = new JButton("Create");
- createButton.addActionListener((e) -> createMessage());
+ JButton sectionButton = new JButton("Set Section");
+ sectionButton.addActionListener((e) -> setMessageSection());
setLayout(new MigLayout("fill, ins 0"));
add(filteredList, "grow, pushy, span, wrap");
add(renameButton, "sg but, growx, pushx, h 32!, split 2");
- add(createButton, "sg but, growx, pushx");
+ add(sectionButton, "sg but, growx, pushx, wrap");
+ add(createButton, "sg but, growx, pushx, h 32!, split 2");
+ add(deleteButton, "sg but, growx, pushx");
+ }
+
+ public void createMessage()
+ {
+ if (asset != null) {
+
+ int sectionID = 0;
+ if (asset.messages.size() > 0) {
+ sectionID = asset.messages.get(asset.messages.size() - 1).section;
+ }
+
+ Message msg = new Message(asset);
+ msg.section = sectionID;
+
+ msg.name = promptForUniqueName(null);
+ if (msg.name != null) {
+ asset.messages.add(msg);
+ filteredList.setContent(asset.messages);
+
+ filteredList.setSelected(msg);
+ }
+ }
+ }
+
+ public void deleteMessage()
+ {
+ Message selected = filteredList.getSelected();
+
+ if (asset != null && selected != null) {
+ Toolkit.getDefaultToolkit().beep();
+ //TODO asset.messages.remove(selected);
+ }
}
public void renameMessage()
{
- Message msg = filteredList.getSelected();
- if (msg == null)
+ Message selected = filteredList.getSelected();
+ if (selected == null)
return;
- String newName = promptForUniqueName(msg.name);
+ String newName = promptForUniqueName(selected.name);
if (newName != null) {
- msg.name = newName;
+ selected.name = newName;
filteredList.repaint();
}
}
- public void createMessage()
+ public void setMessageSection()
{
+ Message selected = filteredList.getSelected();
+ if (selected == null)
+ return;
- List resources = new ArrayList<>();
-
- try {
- int sectionID = 0;
- for (AssetHandle ah : AssetManager.getMessages()) {
- Logger.log("Reading strings from: " + ah.getName());
- resources.add(new MessageGroup(ah, sectionID++));
+ String newSection = SwingUtils.getInputDialog()
+ .setTitle("Choose Message Section")
+ .setMessage("Enter the new message section (hex)")
+ .setMessageType(JOptionPane.QUESTION_MESSAGE)
+ .setDefault(String.format("%02X", selected.section))
+ .prompt();
+
+ if (newSection != null) {
+ try {
+ selected.section = Integer.parseInt(newSection, 16);
+ filteredList.repaint();
+ }
+ catch (NumberFormatException e) {
+ Toolkit.getDefaultToolkit().beep();
+ Logger.logError(newSection + " is not a valid section!");
}
}
- catch (IOException e) {
- Logger.logError(e.getMessage());
- }
-
- //TODO filteredList.setContent(resources);
}
public String promptForUniqueName(String originalName)
{
- String name = SwingUtils.showFramedInputDialog(null,
- "Provide a message name",
- "Name New Message",
- JOptionPane.QUESTION_MESSAGE);
+ while (true) {
+ String name = SwingUtils.getInputDialog()
+ .setTitle("Choose Message Name")
+ .setMessage("Choose a unique message name")
+ .setMessageType(JOptionPane.QUESTION_MESSAGE)
+ .setDefault(originalName)
+ .prompt();
+
+ if (name == null || name.isBlank()) {
+ // empty name provided
+ return null;
+ }
- if (name == null || name.isBlank()) {
+ if (originalName != null && name.equals(originalName)) {
+ // name did not change
+ return originalName;
+ }
- }
+ if (!editor.hasMessage(name)) {
+ // name is unique
+ return name;
+ }
- return name; //TODO
+ SwingUtils.getWarningDialog()
+ .setTitle("Name Conflict")
+ .setMessage(name + " is already in use!")
+ .show();
+ }
}
- public void setStrings(List messages)
+ public void setAsset(MessageAsset asset)
{
- filteredList.setContent(messages);
+ this.asset = asset;
+
+ if (asset == null) {
+ filteredList.setContent(null);
+ }
+ else {
+ filteredList.setContent(asset.messages);
+ }
}
private static class MessageCellRenderer extends JPanel implements ListCellRenderer
diff --git a/src/main/java/game/message/editor/StringPrinter.java b/src/main/java/game/message/editor/MessagePrinter.java
similarity index 99%
rename from src/main/java/game/message/editor/StringPrinter.java
rename to src/main/java/game/message/editor/MessagePrinter.java
index fac561e..20e06c4 100644
--- a/src/main/java/game/message/editor/StringPrinter.java
+++ b/src/main/java/game/message/editor/MessagePrinter.java
@@ -15,10 +15,10 @@
import game.message.StringConstants.StringStyle;
import game.message.StringEncoder;
import game.message.editor.MessageUtil.StringProperties;
-import game.message.editor.StringTokenizer.Sequence;
+import game.message.editor.MessageTokenizer.Sequence;
import util.MathUtil;
-public class StringPrinter
+public class MessagePrinter
{
private MessageEditor editor;
@@ -387,7 +387,7 @@ public void drawMessageBox()
}
}
- public StringPrinter(MessageEditor editor)
+ public MessagePrinter(MessageEditor editor)
{
this.editor = editor;
setStyle(StringStyle.RIGHT, null); // initialize parameters for default window style
diff --git a/src/main/java/game/message/editor/MessageRenderer.java b/src/main/java/game/message/editor/MessageRenderer.java
index 89037e2..4f22425 100644
--- a/src/main/java/game/message/editor/MessageRenderer.java
+++ b/src/main/java/game/message/editor/MessageRenderer.java
@@ -1,73 +1,1240 @@
package game.message.editor;
+import static game.message.StringConstants.StringEffect.*;
+import static game.texture.TileFormat.CI_8;
+import static org.lwjgl.opengl.GL11.*;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.List;
+import java.util.Random;
+
+import org.lwjgl.BufferUtils;
+import assets.ExpectedAsset;
+import game.SimpleItem;
+import game.map.Axis;
+import game.map.editor.common.MouseInput;
+import game.map.editor.geometry.Vector3f;
+import game.map.editor.render.PresetColor;
+import game.map.editor.render.TextureManager;
+import game.map.shape.TransformMatrix;
+import game.message.MessageBoxes;
import game.message.StringConstants;
+import game.message.StringConstants.ControlCharacter;
+import game.message.StringConstants.StringFunction;
+import game.message.StringConstants.StringStyle;
import game.message.font.FontManager;
import game.message.font.FontType;
+import game.sprite.ImgAsset;
+import game.sprite.Sprite;
+import game.sprite.SpriteLoader;
+import game.sprite.SpriteLoader.SpriteSet;
+import game.sprite.SpriteRaster;
+import game.texture.ImageConverter;
+import game.texture.Palette;
+import game.texture.Texture;
+import game.texture.Tile;
+import renderer.GLUtils;
+import renderer.buffers.LineRenderQueue;
+import renderer.shaders.BaseShader;
+import renderer.shaders.RenderState;
import renderer.shaders.ShaderManager;
+import renderer.shaders.scene.BasicIndexedShader;
+import renderer.shaders.scene.BasicSolidShader;
+import renderer.shaders.scene.BasicTexturedShader;
import renderer.shaders.scene.FontShader;
+import util.Logger;
public class MessageRenderer
{
- private static final int FONT_SIZE_X = 16;
- private static final int FONT_SIZE_Y = 16;
+ private final MessageEditor editor;
+
+ public final TransformMatrix projMatrix;
+ public final TransformMatrix viewMatrix;
+
+ private int glBackgroundTexID;
+ private int glNoiseTexID;
+
+ private Random rng;
+ private boolean useFiltering = true;
+
+ private int frameCounter = 0;
+
+ // extra resources
+ private final SpriteLoader spriteLoader;
+ private Tile[] glItemPreviews = null;
+
+ private BufferedImage varImage = null;
+ private boolean varImageLoaded = false;
+ private int glVarTexID;
+
+ public MessageRenderer(MessageEditor editor) throws IOException
+ {
+ this.editor = editor;
+
+ projMatrix = new TransformMatrix();
+ viewMatrix = new TransformMatrix();
+
+ rng = new Random();
+ loadTextures();
+ loadItemIcons();
+
+ spriteLoader = new SpriteLoader();
+ }
+
+ public void cleanup()
+ {
+ MessageBoxes.glDelete();
+ FontManager.glDelete();
+
+ glDeleteTextures(glBackgroundTexID);
+ glDeleteTextures(glNoiseTexID);
+ glDeleteTextures(glVarTexID);
+
+ if (glItemPreviews != null) {
+ for (Tile tile : glItemPreviews) {
+ if (tile == null)
+ continue;
+
+ tile.glDelete();
+ tile.palette.glDelete();
+ }
+ }
+ }
+
+ private void loadTextures() throws IOException
+ {
+ Tile img;
+ BufferedImage bimg;
+
+ glLoadNoise();
+
+ // background
+ try {
+ File imgFile = ExpectedAsset.KMR_BG.getFile();
+ img = Tile.load(imgFile, CI_8);
+ bimg = ImageConverter.convertToBufferedImage(img);
+ glBackgroundTexID = glLoadImage(bimg);
+ }
+ catch (IOException e) {
+ Logger.logError("Could not load background asset: " + ExpectedAsset.KMR_BG.getPath());
+ }
+
+ MessageBoxes.loadImages();
+ MessageBoxes.glLoad();
+
+ FontManager.loadData();
+ FontManager.glLoad();
+ }
+
+ private void glLoadNoise()
+ {
+ BufferedImage bimg = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
+ for (int i = 0; i < 256; i++)
+ for (int j = 0; j < 256; j++) {
+ int I = rng.nextInt() & 0xFF;
+ bimg.setRGB(i, j, (0xFF << 24) | (I << 16) | (I << 8) | I);
+ }
+
+ ByteBuffer buffer = TextureManager.createByteBuffer(bimg);
+
+ int glID = glGenTextures();
+ glBindTexture(GL_TEXTURE_2D, glID);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bimg.getWidth(),
+ bimg.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+
+ glNoiseTexID = glID;
+ }
+
+ private void loadItemIcons() throws IOException
+ {
+ List items = game.ProjectDatabase.getItemList();
+
+ glItemPreviews = new Tile[items.size()];
+ for (int i = 0; i < items.size(); i++) {
+ Tile tile = items.get(i).iconTile;
+ if (tile == null)
+ continue;
+
+ tile.glLoad(Texture.WRAP_CLAMP, Texture.WRAP_CLAMP, false);
+ tile.palette.glLoad();
+
+ glItemPreviews[i] = tile;
+ }
+
+ Logger.log("Loaded icon previews");
+ }
+
+ public void setVarImage(BufferedImage bimg)
+ {
+ if (varImageLoaded)
+ glDeleteTextures(glVarTexID);
+
+ glVarTexID = glLoadImage(bimg);
+ varImage = bimg;
+ varImageLoaded = true;
+ }
+
+ private static int glLoadImage(BufferedImage bimg)
+ {
+ ByteBuffer buffer = TextureManager.createByteBuffer(bimg);
+
+ int glID = glGenTextures();
+ glBindTexture(GL_TEXTURE_2D, glID);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bimg.getWidth(),
+ bimg.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+
+ return glID;
+ }
+
+ private final void drawBackground(int glTexID)
+ {
+ projMatrix.ortho(0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f);
+ RenderState.setProjectionMatrix(projMatrix);
+ RenderState.setViewMatrix(null);
+
+ float hfov = 105;
+ float right = (hfov + 360) / 360;
+ float scaleX = RenderState.getViewportSizeX() / 600.0f;
+
+ BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class);
+ shader.texture.bind(glTexID);
+ shader.setXYQuadCoords(0, 0, 1, 1, 0);
+ shader.setQuadTexCoords(0, 1, right * scaleX, 0);
+ shader.renderQuad();
+ }
+
+ private static void drawGrid(MessagePrinter printer)
+ {
+ RenderState.setLineWidth(1.5f);
+
+ int xstart = printer.windowBasePosX + printer.windowTextStartX;
+ int ystart = printer.windowBasePosY + printer.windowTextStartY;
+ int xmax = ((printer.clipMaxX - xstart) / 10) * 10;
+ int ymax = ((printer.clipMaxY - ystart) / 10) * 10;
+
+ for (int i = 0; i <= xmax; i += 10) {
+ float alpha = ((i % 20) == 0) ? 0.5f : 0.2f;
+ int v1 = LineRenderQueue.addVertex()
+ .setPosition(xstart + i, ystart, 0)
+ .setColor(0.15f, 0.15f, 0.15f, alpha)
+ .getIndex();
+ int v2 = LineRenderQueue.addVertex()
+ .setPosition(xstart + i, ystart + ymax, 0)
+ .setColor(0.15f, 0.15f, 0.15f, alpha)
+ .getIndex();
+ LineRenderQueue.addLine(v1, v2);
+ }
+
+ for (int i = 0; i <= ymax; i += 10) {
+ float alpha = ((i % 20) == 0) ? 0.5f : 0.2f;
+ int v1 = LineRenderQueue.addVertex()
+ .setPosition(xstart, ystart + i, 0)
+ .setColor(0.15f, 0.15f, 0.15f, alpha)
+ .getIndex();
+ int v2 = LineRenderQueue.addVertex()
+ .setPosition(xstart + xmax, ystart + i, 0)
+ .setColor(0.15f, 0.15f, 0.15f, alpha)
+ .getIndex();
+ LineRenderQueue.addLine(v1, v2);
+ }
+
+ RenderState.setDepthWrite(false);
+ LineRenderQueue.render(true);
+ RenderState.setDepthWrite(true);
+ }
+
+ private static void drawBackgroundGuide(MessagePrinter printer)
+ {
+ int v1, v2, v3, v4;
+ RenderState.setLineWidth(2.0f);
+
+ RenderState.setColor(PresetColor.RED);
+ v1 = LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex();
+ v2 = LineRenderQueue.addVertex().setPosition(320, 0, 0).getIndex();
+ v3 = LineRenderQueue.addVertex().setPosition(320, 240, 0).getIndex();
+ v4 = LineRenderQueue.addVertex().setPosition(0, 240, 0).getIndex();
+ LineRenderQueue.addLine(v1, v2, v3, v4, v1);
+
+ RenderState.setColor(PresetColor.BLUE);
+ v1 = LineRenderQueue.addVertex().setPosition(12, 20, 0).getIndex();
+ v2 = LineRenderQueue.addVertex().setPosition(320 - 12, 20, 0).getIndex();
+ v3 = LineRenderQueue.addVertex().setPosition(320 - 12, 240 - 20, 0).getIndex();
+ v4 = LineRenderQueue.addVertex().setPosition(12, 240 - 20, 0).getIndex();
+ LineRenderQueue.addLine(v1, v2, v3, v4, v1);
+
+ // LineRenderQueue.printContents();
+
+ RenderState.setDepthWrite(false);
+ LineRenderQueue.render(true);
+ RenderState.setDepthWrite(true);
+ }
+
+ private static void drawForegroundGuide(MessagePrinter printer)
+ {
+ int v1, v2, v3, v4;
+ RenderState.setLineWidth(1.5f);
+
+ RenderState.setColor(PresetColor.GREEN);
+ v1 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX, printer.windowBasePosY, 0).getIndex();
+ v2 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX, printer.windowBasePosY + printer.windowSizeY, 0).getIndex();
+ v3 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX + printer.windowSizeX, printer.windowBasePosY + printer.windowSizeY, 0)
+ .getIndex();
+ v4 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX + printer.windowSizeX, printer.windowBasePosY, 0).getIndex();
+ LineRenderQueue.addLine(v1, v2, v3, v4, v1);
+
+ RenderState.setColor(PresetColor.TEAL);
+ v1 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX, printer.rewindArrowY, 0).getIndex();
+ v2 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX, printer.rewindArrowY + 24, 0).getIndex();
+ v3 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX + 24, printer.rewindArrowY + 24, 0).getIndex();
+ v4 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX + 24, printer.rewindArrowY, 0).getIndex();
+ LineRenderQueue.addLine(v1, v2, v3, v4, v1);
+
+ RenderState.setColor(PresetColor.YELLOW);
+ v1 = LineRenderQueue.addVertex().setPosition(printer.clipMinX, printer.clipMinY, 0).getIndex();
+ v2 = LineRenderQueue.addVertex().setPosition(printer.clipMinX, printer.clipMaxY, 0).getIndex();
+ v3 = LineRenderQueue.addVertex().setPosition(printer.clipMaxX, printer.clipMaxY, 0).getIndex();
+ v4 = LineRenderQueue.addVertex().setPosition(printer.clipMaxX, printer.clipMinY, 0).getIndex();
+ LineRenderQueue.addLine(v1, v2, v3, v4, v1);
+
+ RenderState.setDepthWrite(false);
+ LineRenderQueue.render(true);
+ RenderState.setDepthWrite(true);
+ }
+
+ private static final void drawAxes(float lineWidth)
+ {
+ RenderState.setLineWidth(lineWidth);
+
+ RenderState.setColor(PresetColor.RED);
+ LineRenderQueue.addLine(
+ LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(),
+ LineRenderQueue.addVertex().setPosition(Short.MAX_VALUE, 0, 0).getIndex());
+
+ RenderState.setColor(PresetColor.GREEN);
+ LineRenderQueue.addLine(
+ LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(),
+ LineRenderQueue.addVertex().setPosition(0, Short.MAX_VALUE, 0).getIndex());
+
+ LineRenderQueue.render(true);
+ }
+
+ public Vector3f getMousePosition(MouseInput mouse, boolean useDepth)
+ {
+ int mouseX = mouse.getPosX();
+ int mouseY = mouse.getPosY();
+
+ int width = editor.glCanvasWidth();
+ int height = editor.glCanvasHeight();
+
+ IntBuffer viewport = BufferUtils.createIntBuffer(16);
+ viewport.put(0);
+ viewport.put(0);
+ viewport.put(width);
+ viewport.put(height);
+ viewport.rewind();
+
+ float winX = mouseX;
+ float winY = mouseY;
+ float winZ = 0;
+
+ if (useDepth) {
+ // this is the expensive part, reading z from the depth buffer
+ FloatBuffer fb = BufferUtils.createFloatBuffer(1);
+ glReadPixels(mouseX, mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, fb);
+ winZ = fb.get();
+ }
+
+ FloatBuffer position = BufferUtils.createFloatBuffer(3);
+ GLUtils.gluUnProject(winX, winY, winZ, viewMatrix.toFloatBuffer(), projMatrix.toFloatBuffer(), viewport, position);
+
+ return new Vector3f(position.get(), position.get(), position.get());
+ }
+
+ public void render(MouseInput mouse, MessagePrinter printer, float cameraX, float cameraY, float cameraZoom, float cameraYaw)
+ {
+ assert (printer != null);
+
+ drawBackground(glBackgroundTexID);
+
+ float halfW = (editor.glCanvasWidth() / 2.0f) * cameraZoom;
+ float halfH = (editor.glCanvasHeight() / 2.0f) * cameraZoom;
+ projMatrix.ortho(-halfW, halfW, halfH, -halfH, 1, 0x20000);
+ // projMatrix.perspective(60, (float)editor.glCanvasWidth() / editor.glCanvasHeight(), 1, 0x2000);
+ RenderState.setProjectionMatrix(projMatrix);
+
+ viewMatrix.setIdentity();
+ viewMatrix.translate(new Vector3f(-cameraX, -cameraY, -400.0f * cameraZoom));
+ viewMatrix.rotate(Axis.Y, cameraYaw);
+ RenderState.setViewMatrix(viewMatrix);
+ RenderState.setModelMatrix(null);
+
+ if (editor.shouldShowViewportGuides())
+ drawBackgroundGuide(printer);
+
+ // drawAxes(1.0f);
+
+ DrawState state = new DrawState(printer);
+ state.useCulling = editor.isCullingEnabled();
+
+ printer.drawMessageBox();
+
+ FontShader shader = ShaderManager.use(FontShader.class);
+ shader.enableFiltering.set(useFiltering);
+ shader.fadeAlpha.set(1.0f);
+
+ float scrollY = printer.scrollAmount * (state.currentFont.chars.defaultY * state.stringScaleY + printer.style.lineOffset);
+ int printOffsetX = 0;
+ int printOffsetY = -(int) (scrollY);
+
+ state.printPosX = 0;
+ state.printPosY = 0;
+ printer.drawBuffer.rewind();
+
+ read_buf:
+ while (printer.drawBuffer.position() < printer.printPos) {
+ byte charByte = printer.drawBuffer.get();
+ int charInt = charByte & 0xFF;
+
+ if (charInt == MessagePrinter.PAGE_END_MARK) {
+ continue;
+ }
+ else if (charInt == MessagePrinter.BUFFER_FILL) {
+ break; // end of string
+ }
+ else if (charInt < 0xF0) {
+ int charWidth = MessageUtil.getCharWidth(state.currentFont, state.fontVariant, charInt, state.stringScaleX, state.charWidthOverride,
+ 0);
+ if (charInt < state.currentFont.chars.numChars)
+ renderChar(printer, state, printOffsetX, printOffsetY, charInt);
+ state.printPosX += charWidth;
+ }
+ else if (charInt == 0xF7 || charInt == 0xF8 || charInt == 0xF9) {
+ int charWidth = MessageUtil.getCharWidth(state.currentFont, state.fontVariant, charInt, state.stringScaleX, state.charWidthOverride,
+ 0);
+ state.printPosX += charWidth;
+ }
+ else {
+ switch (ControlCharacter.decodeMap.get(charByte)) {
+ case ENDL: // 0xF0
+ state.printPosX = 0;
+ state.printPosY += state.currentFont.chars.defaultY * state.stringScaleY + printer.style.lineOffset;
+ break;
+
+ case NEXT: // 0xFB
+ break;
+
+ case WAIT: // 0xF1
+ throw new IllegalStateException(this.getClass().getSimpleName() + " should not encounter WAIT");
+
+ case PAUSE: // 0xF2
+ printer.drawBuffer.get();
+ throw new IllegalStateException(this.getClass().getSimpleName() + " should not encounter PAUSE");
+
+ case VARIANT0: // 0xF3
+ case VARIANT1: // 0xF4
+ case VARIANT2: // 0xF5
+ case VARIANT3: // 0xF6
+ state.fontVariant = charInt - 0xF3;
+ break;
+
+ // 0xF7-0xF9 are spaces
+ // 0xFA = unknown
+
+ case STYLE: // 0xFC
+ handleStyle(printer, state);
+ break;
+
+ case END: // 0xFD
+ break read_buf;
+
+ // 0xFE = unused afaik
+ case FUNC: // 0xFF
+ handleFunction(printer, state, printOffsetX, printOffsetY);
+ break;
+ }
+ }
+ }
+
+ frameCounter++;
+
+ RenderState.setModelMatrix(null);
+ if (editor.shouldShowGrid())
+ drawGrid(printer);
+
+ // drawForegroundGuide(printer);
+
+ drawUI(mouse, printer);
+ }
- public static void init() throws IOException
+ private void drawUI(MouseInput mouse, MessagePrinter printer)
{
- if (!FontManager.isLoaded())
- FontManager.loadData();
+ // set UI matrices
+ TransformMatrix mtx = TransformMatrix.identity();
+ mtx.ortho(0, editor.glCanvasWidth(), 0, editor.glCanvasHeight(), -1, 1);
+ RenderState.setProjectionMatrix(mtx);
+ RenderState.setViewMatrix(null);
+ RenderState.setModelMatrix(null);
- if (!FontManager.isReadyForGL())
- FontManager.glLoad();
+ RenderState.enableDepthTest(false);
+
+ if (mouse.hasLocation()) {
+ Vector3f worldPos = getMousePosition(mouse, false);
+ int mx = Math.round(worldPos.x) - (printer.windowBasePosX + printer.windowTextStartX);
+ int my = Math.round(worldPos.y) - (printer.windowBasePosY + printer.windowTextStartY);
+ drawString(0x14, 8, editor.glCanvasHeight() - 4, 16, String.format("Cursor Pos: %3d, %2d", mx, my));
+ }
+
+ float bufferFillPercent = 100.0f * printer.compiledLength / MessagePrinter.MAX_LENGTH;
+
+ if (bufferFillPercent > 100.0f) {
+ drawString(0x12, 176, editor.glCanvasHeight() - 4, 16, String.format("ERROR: String buffer at %.1f%% capacity! (%d/%d)",
+ bufferFillPercent, printer.compiledLength, MessagePrinter.MAX_LENGTH));
+ }
+ else if (bufferFillPercent > 75.0f) {
+ int palID = 5;
+ if (bufferFillPercent > 90.0f)
+ palID = 6;
+ if (bufferFillPercent > 95.0f)
+ palID = 7;
+ drawString(palID, 176, editor.glCanvasHeight() - 4, 16, String.format("WARNING: String buffer at %.1f%% capacity! (%d/%d)",
+ bufferFillPercent, printer.compiledLength, MessagePrinter.MAX_LENGTH));
+ }
+
+ RenderState.enableDepthTest(true);
+ }
+
+ private void handleStyle(MessagePrinter printer, DrawState state)
+ {
+ switch (StringStyle.decodeMap.get(printer.drawBuffer.get())) {
+ case RIGHT:
+ case LEFT:
+ case CENTER:
+ case TATTLE:
+ case CHOICE:
+ state.textColor = 0xA;
+ break;
+ case INSPECT:
+ case UPGRADE:
+ case NARRATE:
+ case STYLE_F:
+ state.textColor = 0;
+ break;
+ case SIGN:
+ state.textColor = 0x18;
+ break;
+ case LAMPPOST:
+ state.textColor = 0x1C;
+ break;
+ case POSTCARD:
+ case POPUP:
+ case STYLE_B:
+ state.textColor = 0;
+ break;
+ case EPILOGUE:
+ state.textColor = 0;
+ break;
+ }
}
- public void drawString(int posX, int posY, int size, String text)
+ private void handleFunction(MessagePrinter printer, DrawState state, int relativePosX, int relativePosY)
+ {
+ int startX = state.getScreenPosX(relativePosX);
+ int startY = state.getScreenPosY(relativePosY);
+ StringFunction func = StringFunction.decodeMap.get(printer.drawBuffer.get());
+
+ switch (func) {
+ case CURSOR:
+ case OPTION:
+ case SET_CANCEL:
+ case END_CHOICE:
+ printer.drawBuffer.get();
+ break; // completely ignored by editor
+
+ case VAR:
+ printer.drawBuffer.get();
+ break; // already handled during encoding
+
+ case FONT:
+ int fontType = (printer.drawBuffer.get() & 0xFF);
+ switch (fontType) {
+ case 0:
+ state.currentFont = FontType.Normal;
+ break;
+ case 1:
+ state.currentFont = FontType.Menus;
+ break;
+ case 2:
+ state.currentFont = FontType.Menus;
+ break;
+ case 3:
+ state.currentFont = FontType.Title;
+ break;
+ case 4:
+ state.currentFont = FontType.Subtitle;
+ break;
+ }
+ break;
+
+ case VARIANT:
+ state.fontVariant = (printer.drawBuffer.get() & 0xFF);
+ break;
+
+ case ANIM_DONE:
+ if (printer.hasAnim()) {
+ int spriteID = printer.getAnimSprite();
+ int rasterID = printer.getAnimRaster();
+
+ Sprite npc = spriteLoader.getSprite(SpriteSet.Npc, spriteID);
+ if (npc != null && !npc.areTexturesLoaded())
+ npc.loadTextures();
+
+ if (npc != null && npc.rasters.getSize() > rasterID) {
+ BasicIndexedShader shader = ShaderManager.use(BasicIndexedShader.class);
+ SpriteRaster raster = npc.rasters.get(rasterID);
+ ImgAsset front = raster.getFront();
+ if (front != null) {
+ front.img.glBind(shader.texture);
+ front.getPalette().glBind(shader.palette);
+ drawClippedQuad(shader, state, startX, startX + front.img.width, startY, startY + front.img.height);
+ }
+ }
+ else {
+ BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class);
+ float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f;
+ shader.baseColor.set(1.0f, f, f, 1.0f);
+ drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x40);
+ }
+ }
+ break;
+
+ case IMAGE:
+ printer.drawBuffer.get(); // index -- ignored
+ int posX = printer.drawBuffer.getShort() & 0xFFFF;
+ int posY = printer.drawBuffer.get() & 0xFF;
+ int border = printer.drawBuffer.get() & 0xFF;
+ int alpha = printer.drawBuffer.get() & 0xFF;
+ int alphaStep = printer.drawBuffer.get() & 0xFF;
+
+ if (varImageLoaded) {
+ BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class);
+ shader.texture.bind(glVarTexID);
+ shader.multiplyBaseColor.set(true);
+ shader.baseColor.set(1.0f, 1.0f, 1.0f, alpha / 255.0f);
+ drawQuad(shader, posX, posX + varImage.getWidth(), posY, posY + varImage.getHeight());
+ }
+ else {
+ BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class);
+ float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f;
+ shader.baseColor.set(1.0f, f, f, alpha / 255.0f);
+ drawQuad(shader, posX, posX + 150, posY, posY + 105);
+ }
+ break;
+
+ case HIDE_IMAGE:
+ printer.drawBuffer.get(); // fade out time
+ break;
+
+ case INLINE_IMAGE:
+ printer.drawBuffer.get(); // index -- ignored
+
+ if (varImageLoaded) {
+ BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class);
+ shader.texture.bind(glVarTexID);
+ drawClippedQuad(shader, state, startX, startX + varImage.getWidth(), startY, startY + varImage.getHeight());
+ }
+ else {
+ BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class);
+ float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f;
+ shader.baseColor.set(1.0f, f, f, 1.0f);
+ drawClippedQuad(shader, state, startX, startX + 0x40, startY, startY + 0x40);
+ }
+ break;
+
+ case ITEM_ICON:
+ int upperItemID = (printer.drawBuffer.get() & 0xFF);
+ int lowerItemID = (printer.drawBuffer.get() & 0xFF);
+ int itemID = (upperItemID << 8) | lowerItemID;
+
+ if (glItemPreviews != null && glItemPreviews.length > itemID && glItemPreviews[itemID] != null) {
+ BasicIndexedShader shader = ShaderManager.use(BasicIndexedShader.class);
+ glItemPreviews[itemID].glBind(shader.texture);
+ glItemPreviews[itemID].palette.glBind(shader.palette);
+ drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x20);
+ }
+ else {
+ BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class);
+ float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f;
+ shader.baseColor.set(1.0f, f, f, 1.0f);
+ drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x20);
+ }
+ break;
+
+ case COLOR:
+ state.textColor = (printer.drawBuffer.get() & 0xFF);
+ if (state.textColor < 0)
+ state.textColor = 0;
+ int numPals = state.currentFont.chars.numPals;
+ if (state.textColor >= numPals)
+ state.textColor = numPals - 1;
+ break;
+
+ case PUSH_COLOR:
+ state.savedColor = state.textColor;
+ break;
+ case POP_COLOR:
+ state.textColor = state.savedColor;
+ break;
+
+ case PUSH_POS:
+ state.savedPosX = state.printPosX;
+ state.savedPosY = state.printPosY;
+ break;
+ case POP_POS:
+ state.printPosX = state.savedPosX;
+ state.printPosY = state.savedPosY;
+ break;
+
+ case SPACING:
+ state.charWidthOverride = (printer.drawBuffer.get() & 0xFF);
+ break;
+
+ case SIZE:
+ int sx = (printer.drawBuffer.get() & 0xFF);
+ int sy = (printer.drawBuffer.get() & 0xFF);
+ state.stringScaleX = sx / 16.0f;
+ state.stringScaleY = sy / 16.0f;
+ state.charScaleX = state.stringScaleX;
+ state.charScaleY = state.stringScaleY;
+ break;
+ case SIZE_RESET:
+ state.stringScaleX = 1.0f;
+ state.stringScaleY = 1.0f;
+ state.charScaleX = state.stringScaleX;
+ state.charScaleY = state.stringScaleY;
+ break;
+
+ case SET_X: // [80129EB4]
+ int upper = (printer.drawBuffer.get() & 0xFF);
+ int lower = (printer.drawBuffer.get() & 0xFF);
+ state.printPosX = (upper << 8) | lower;
+ break;
+ case SET_Y: // [80129ED8]
+ state.printPosY = (printer.drawBuffer.get() & 0xFF);
+ break;
+ case RIGHT: // [80129F0C]
+ state.printPosX += (printer.drawBuffer.get() & 0xFF);
+ break;
+ case DOWN: // [80129F38]
+ state.printPosY += (printer.drawBuffer.get() & 0xFF);
+ break;
+ case UP: // [80129F64]
+ state.printPosY -= (printer.drawBuffer.get() & 0xFF);
+ break;
+ case CENTER_X: // [8012AAEC]
+ state.centerPos = (printer.drawBuffer.get() & 0xFF);
+ break;
+
+ case START_FX:
+ int startFXType = (printer.drawBuffer.get() & 0xFF);
+ state.effectActive[startFXType] = true;
+ switch (startFXType) {
+ case 0x2:
+ state.effectActive[3] = false;
+ break;
+ case 0x3:
+ state.effectActive[2] = false;
+ state.fadeNoiseAlpha = (printer.drawBuffer.get() & 0xFF) / 255.0f;
+ break;
+ case 0x5:
+ state.fadeJitterArg = (printer.drawBuffer.get() & 0xFF);
+ break;
+ case 0x7:
+ state.fadeAlpha = (printer.drawBuffer.get() & 0xFF) / 255.0f;
+ break;
+ case 0x6:
+ case 0x9:
+ state.savedFxColor = state.textColor;
+ break;
+ case 0xC:
+ case 0xD:
+ state.savedFxCharScaleX = state.charScaleX;
+ state.savedFxCharScaleY = state.charScaleY;
+ break;
+ }
+ break;
+
+ case END_FX:
+ int endFXType = (printer.drawBuffer.get() & 0xFF);
+ // restore saved state (if it has been saved)
+ if (state.effectActive[endFXType]) {
+ switch (endFXType) {
+ case 0x2:
+ case 0x3:
+ // end clears the flags for these,
+ // but will not stop the effect since its
+ // part of the display list
+ break;
+ case 0x6:
+ case 0x9:
+ state.textColor = state.savedFxColor;
+ state.effectActive[endFXType] = false;
+ break;
+ case 0xC:
+ case 0xD:
+ state.charScaleX = state.savedFxCharScaleX;
+ state.charScaleY = state.savedFxCharScaleY;
+ state.effectActive[endFXType] = false;
+ break;
+ default:
+ state.effectActive[endFXType] = false;
+ }
+ }
+ break;
+
+ case FUNC_03:
+ //XXX unknown, some graphics state reset?
+ break;
+
+ case SETVOICE:
+ case VOICE:
+ case VOLUME:
+ case SPEED:
+ case SCROLL:
+ case DELAY_OFF:
+ case DELAY_ON:
+ case SKIP_OFF:
+ case INPUT_OFF:
+ case INPUT_ON:
+ case ENABLE_CDOWN:
+ break; // irrelevant to renderer
+
+ case SET_REWIND:
+ printer.drawBuffer.get();
+ break; // irrelevant to renderer
+
+ case YIELD:
+ break;
+
+ case SET_CURSOR:
+ break;
+
+ case ANIM_SPRITE:
+ case ANIM_DELAY:
+ case ANIM_LOOP:
+ throw new IllegalStateException("LOGIC ERROR: " + func.name + " in encodeFunctionArgs!");
+ }
+ }
+
+ public void drawString(int palID, int posX, int posY, int size, String text)
{
FontShader shader = ShaderManager.use(FontShader.class);
shader.noiseMode.set(0);
shader.fadeAlpha.set(1.0f);
shader.enableDropShadow.set(false);
+ FontType font = FontType.Normal;
+
for (char c : text.toCharArray()) {
int index = StringConstants.getIndex(c, true);
if (index < 0)
continue;
- int endX = posX + (int) (FONT_SIZE_X * size / 16.0f);
- int endY = posY - (int) (FONT_SIZE_Y * size / 16.0f);
- int charWidth = getCharWidth(FontType.Normal, 0, index, size / 16.0f);
+ int endX = posX + (int) (font.chars.defaultX * size / 16.0f);
+ int endY = posY - (int) (font.chars.defaultY * size / 16.0f);
+ int charWidth = MessageUtil.getCharWidth(font, 0, index, size / 16.0f, 0, 0);
- if (index < FontType.Normal.chars.numChars) {
- FontType.Normal.chars.images[index].glBind(shader.texture);
- FontType.Normal.chars.palettes[0x14].glBind(shader.palette);
- shader.setQuadTexCoords(0, 0, 1, 1);
- shader.setXYQuadCoords(posX, posY, endX, endY, 0); // y flipped
- shader.renderQuad();
+ if (index < font.chars.numChars) {
+ font.chars.images[index].glBind(shader.texture);
+ font.chars.palettes[palID].glBind(shader.palette);
+ drawQuad(shader, posX, endX, posY, endY);
}
posX += charWidth;
}
}
- private static int getCharWidth(FontType font, int subfont, int index, float stringScale)
+ private void renderChar(MessagePrinter printer, DrawState state, int relativePosX, int relativePosY, int charIndex)
+ {
+ FontShader shader = ShaderManager.use(FontShader.class);
+
+ int[] lookahead = new int[4];
+ for (int i = 0; i < lookahead.length; i++)
+ lookahead[i] = (printer.drawBuffer.get() & 0xFF);
+ printer.drawBuffer.position(printer.drawBuffer.position() - lookahead.length);
+
+ //XXX correct?
+ state.charScaleX = state.stringScaleX;
+ state.charScaleY = state.stringScaleY;
+ float alpha = 1.0f;
+
+ if (state.effectActive[BLUR.code]) // 0x20
+ {
+ // fade code from [8012ADC4]
+ alpha = 0.35f;
+ }
+
+ if (state.effectActive[SHAKE.code]) {
+ // code from [8012AE50]
+ relativePosX += rng.nextInt() % 2;
+ relativePosY += rng.nextInt() % 2;
+ }
+
+ if (state.effectActive[WAVE.code]) // 0x2
+ {
+ // code from [8012AEBC]
+ double dsx = state.stringScaleX - 1.0;
+ double dsy = state.stringScaleY - 1.0;
+
+ //NOTE: game uses a message-specific 'local' frame counter here
+ double angle = frameCounter * (int) (20.0 - dsx * 5.0) - state.visibleCharCount * (int) (45.0 - dsx * 15.0);
+ relativePosX += Math.cos(Math.toRadians(angle)) * (dsx + 1.6);
+ relativePosY += Math.cos(Math.toRadians(angle + 270.0)) * (dsy + 1.6);
+ }
+ if (state.effectActive[GLOBAL_WAVE.code]) // 0x200
+ {
+ // code from [8012B0BC]
+ double dsx = state.stringScaleX - 1.0;
+ double dsy = state.stringScaleY - 1.0;
+
+ //NOTE: game uses a 'global' frame counter shared by all messages here
+ double angle = frameCounter * (int) (20.0 - dsx * 5.0) - state.visibleCharCount * 45.0;
+ relativePosX += Math.cos(Math.toRadians(angle)) * (dsx + 1.6);
+ relativePosY += Math.cos(Math.toRadians(angle + 270.0)) * (dsy + 1.6);
+ }
+
+ if (state.effectActive[RAINBOW.code] || state.effectActive[GLOBAL_RAINBOW.code]) // 0x440 -- either rainbow
+ {
+ // code from [8012B1B4]
+
+ // NOTE: global overrides local here, but they cant stack so we dont need to represent it
+ int i = Math.abs(state.visibleCharCount - frameCounter / 3);
+ state.textColor = i % 10; // original code: = i + (i / 10) * -10;
+ }
+
+ // properly respect precedence of these effects
+ if (state.effectActive[RISE_PRINT.code] || state.effectActive[GROW_PRINT.code]) {
+ if (!printer.donePrinting
+ && (lookahead[0] != ControlCharacter.ENDL.code) && (lookahead[1] != ControlCharacter.ENDL.code)
+ && (lookahead[2] != ControlCharacter.ENDL.code) && (lookahead[3] != ControlCharacter.ENDL.code)) {
+ if (state.effectActive[RISE_PRINT.code]) {
+ // from [8012B4F0]
+ float dummyScale = 0.25f; //XXX needed to match, unknown why
+ if (lookahead[0] == MessagePrinter.BUFFER_FILL) {
+ state.charScaleX = 1.7f * state.stringScaleX;
+ state.charScaleY = 1.7f * state.stringScaleY;
+ relativePosX -= 6.0f * state.stringScaleY;
+ relativePosY -= dummyScale * 6.0f * state.stringScaleY;
+ }
+ else if (lookahead[1] == MessagePrinter.BUFFER_FILL) {
+ state.charScaleX = 1.4f * state.stringScaleX;
+ state.charScaleY = 1.4f * state.stringScaleY;
+ relativePosX -= 3.0f * state.stringScaleY;
+ relativePosY -= dummyScale * 3.0f * state.stringScaleY;
+ }
+ else if (lookahead[2] == MessagePrinter.BUFFER_FILL) {
+ state.charScaleX = 1.2f * state.stringScaleX;
+ state.charScaleY = 1.2f * state.stringScaleY;
+ relativePosX -= 2.0f * state.stringScaleY;
+ relativePosY -= dummyScale * 2.0f * state.stringScaleY;
+ }
+ }
+ else if (state.effectActive[GROW_PRINT.code]) {
+ // from [8012B740]
+ if (lookahead[0] == MessagePrinter.BUFFER_FILL) {
+ state.charScaleX = 0.3f * state.stringScaleX;
+ state.charScaleY = 0.3f * state.stringScaleY;
+ relativePosX += 5;
+ relativePosY += 5;
+ }
+ else if (lookahead[1] == MessagePrinter.BUFFER_FILL) {
+ state.charScaleX = 0.5f * state.stringScaleX;
+ state.charScaleY = 0.5f * state.stringScaleY;
+ relativePosX += 3;
+ relativePosY += 3;
+ }
+ else if (lookahead[2] == MessagePrinter.BUFFER_FILL) {
+ state.charScaleX = 0.75f * state.stringScaleX;
+ state.charScaleY = 0.75f * state.stringScaleY;
+ relativePosX += 2;
+ relativePosY += 2;
+ }
+ }
+ }
+ }
+ else if (state.effectActive[SIZE_JITTER.code] || state.effectActive[SIZE_WAVE.code]) {
+ float scale = 1.0f;
+
+ if (state.effectActive[SIZE_JITTER.code]) // 0x2000 -- size jitter
+ {
+ // code from [8012B8BC]
+ scale = 0.75f + 0.5f * (rng.nextInt(101) / 100.0f);
+ }
+ else if (state.effectActive[SIZE_WAVE.code]) // 0x4000 -- size wave
+ {
+ // code from [8012BA24]
+ int i = (frameCounter - state.visibleCharCount) * 15;
+ scale = 1.0f + 0.25f * (float) Math.cos(Math.toRadians(i + ((i >> 3) / 45) * 360.0));
+ }
+
+ state.charScaleX *= scale;
+ state.charScaleY *= scale;
+
+ if (scale >= 1.0) {
+ // [8012BACC]
+ int posOffset = (int) (scale * 8.0 - 8.5);
+ relativePosX -= posOffset;
+ relativePosY -= posOffset;
+ }
+ else {
+ // [8012BB7C]
+ int posOffset = (int) (8.0 - 8.0 * scale);
+ relativePosX += posOffset;
+ relativePosY += posOffset;
+ }
+ }
+
+ shader.noiseMode.set(0); // initial value
+
+ if (state.effectActive[DITHER_FADE.code]) //0x80 -- fade
+ {
+ alpha *= state.fadeAlpha;
+ shader.noiseMode.set(7);
+ shader.noiseAlpha.set(state.fadeAlpha);
+ shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat());
+ }
+ else {
+ if (state.effectActive[NOISE_OUTLINE.code]) // 0x04 -- noise
+ {
+ shader.noiseMode.set(2);
+ shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat());
+
+ // add Gfx:
+ // SET_COMBINE FC70FEE1 FFFFF3F9
+
+ // color: G_CCMUX_NOISE * G_CCMUX_TEXEL0
+ // alpha: G_ACMUX_TEXEL0
+ }
+
+ if (state.effectActive[STATIC.code]) // 0x10000 -- faded noise
+ {
+ shader.noiseMode.set(3);
+ shader.noiseAlpha.set(state.fadeNoiseAlpha);
+ shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat());
+
+ // add Gfx:
+ // SET_ENVCOLOR FB000000 arg << 0x18 | arg << 0x10 | arg << 8;
+ // SET_COMBINE FC72FEE5 11FCF279
+
+ // color: (G_CCMUX_NOISE - G_CCMUX_TEXEL0) * G_CCMUX_ENVIRONMENT + G_CCMUX_TEXEL0
+ // alpha: G_ACMUX_TEXEL0
+ }
+ }
+
+ shader.fadeAlpha.set(alpha);
+
+ int baseOffset = 0;
+ if (state.fontVariant < state.currentFont.numVariants && state.fontVariant >= 0)
+ baseOffset = state.currentFont.baseHeightOffset[state.fontVariant];
+
+ int startX = state.getScreenPosX(relativePosX);
+ int startY = state.getScreenPosY(relativePosY + baseOffset);
+ int endX = startX + (int) (state.currentFont.chars.defaultX * state.charScaleX);
+ int endY = startY + (int) (state.currentFont.chars.defaultY * state.charScaleY);
+
+ if (state.effectActive[DROP_SHADOW.code]) // 0x8000 -- drop shadow
+ {
+ shader.enableDropShadow.set(true);
+ drawFontQuad(shader, state,
+ state.currentFont.chars.images[charIndex],
+ state.currentFont.chars.palettes[state.getColor()],
+ startX + 2, endX + 2, startY + 2, endY + 2);
+ shader.enableDropShadow.set(false);
+ }
+
+ if (state.effectActive[BLUR.code]) // 0x20 -- FadedJitter
+ {
+ // code from [8012BDF4]
+ for (int i = 0; i < 5; i++) {
+ int jx = (state.fadeJitterArg == 2) ? 0 : rng.nextInt(3) - 1;
+ int jy = (state.fadeJitterArg == 1) ? 0 : rng.nextInt(3) - 1;
+
+ drawFontQuad(shader, state,
+ state.currentFont.chars.images[charIndex],
+ state.currentFont.chars.palettes[state.getColor()],
+ startX + jx, endX + jx, startY + jy, endY + jy);
+ }
+ }
+ else {
+ drawFontQuad(shader, state,
+ state.currentFont.chars.images[charIndex],
+ state.currentFont.chars.palettes[state.getColor()],
+ startX, endX, startY, endY);
+ }
+
+ state.visibleCharCount++;
+ }
+
+ private static class DrawState
{
- if (index < 0xFA) {
- int width;
- if ((index == 0xF7) || (index == 0xF8) || (index == 0xF9))
- width = font.fullspaceWidth[subfont];
+ public final MessagePrinter printer;
+
+ private FontType currentFont = FontType.Normal;
+ public int fontVariant = 0;
+
+ private boolean[] effectActive;
+ private float fadeAlpha = 1.0f;
+ private float fadeNoiseAlpha = 0;
+ private int fadeJitterArg = 0;
+
+ private int textColor = 0xA;
+
+ private int visibleCharCount = 0;
+
+ private boolean useCulling = true;
+
+ private int printPosX = 0;
+ private int printPosY = 0;
+
+ private int centerPos = 0;
+
+ private int savedColor;
+ private int savedPosX = 0;
+ private int savedPosY = 0;
+ private int savedFxColor = -1;
+ private float savedFxCharScaleX = 1.0f;
+ private float savedFxCharScaleY = 1.0f;
+
+ private int charWidthOverride = 0;
+
+ private float charScaleX = 1.0f;
+ private float charScaleY = 1.0f;
+
+ private float stringScaleX = 1.0f;
+ private float stringScaleY = 1.0f;
+
+ private DrawState(MessagePrinter printer)
+ {
+ this.printer = printer;
+ effectActive = new boolean[StringConstants.StringEffect.values().length];
+ }
+
+ public int getColor()
+ {
+ switch (currentFont) {
+ case Normal:
+ case Menus:
+ default:
+ return textColor;
+ case Title:
+ case Subtitle:
+ return 0;
+ }
+ }
+
+ public int getScreenPosX(int offsetX)
+ {
+ int centerOffset = 0;
+ if (centerPos == 0xFF)
+ centerOffset = 160 - (printer.stringWidth / 2);
+ else if (centerPos != 0)
+ centerOffset = centerPos - (printer.stringWidth / 2);
+
+ if (centerOffset == 0)
+ return printer.windowBasePosX + printer.windowTextStartX + printPosX + offsetX;
else
- width = font.chars.widths[index];
-
- if (index == 0xF7)
- return (int) ((width * stringScale) * 0.6);
- if (index == 0xF8)
- return (int) (width * stringScale);
- if (index == 0xF9)
- return (int) ((width * stringScale) * 0.5);
- if (index >= 0xF0)
- return 0; // other control chars
- return (int) (width * stringScale);
- }
- return 0;
+ return centerOffset + printPosX + offsetX;
+ }
+
+ public int getScreenPosY(int offsetY)
+ {
+ return printer.windowBasePosY + printer.windowTextStartY + printPosY + offsetY;
+ }
+ }
+
+ private void drawFontQuad(FontShader shader, DrawState state, Tile img, Palette pal, float x1, float x2, float y1, float y2)
+ {
+ img.glBind(shader.texture);
+ pal.glBind(shader.palette);
+ shader.noise.bind(glNoiseTexID);
+ drawClippedQuad(shader, state, x1, x2, y1, y2);
+ }
+
+ private static final void drawClippedQuad(BaseShader shader, DrawState state, float x1, float x2, float y1, float y2)
+ {
+ if (state.useCulling)
+ drawClippedQuad(shader, state.printer, x1, x2, y1, y2);
+ else
+ drawQuad(shader, x1, x2, y1, y2);
+ }
+
+ private static final void drawClippedQuad(BaseShader shader, MessagePrinter printer, float x1, float x2, float y1, float y2)
+ {
+ float x1c = x1;
+ float x2c = x2;
+
+ float y1c = y1;
+ float y2c = y2;
+
+ float u1c = 0.0f;
+ float u2c = 1.0f;
+
+ float v1c = 0.0f;
+ float v2c = 1.0f;
+
+ assert (x1 < x2);
+ assert (y1 < y2);
+
+ if ((x2 < printer.clipMinX) || (x1 > printer.clipMaxX) || (y2 < printer.clipMinY) || (y1 > printer.clipMaxY))
+ return;
+
+ if (x1 < printer.clipMinX) {
+ x1c = printer.clipMinX;
+ u1c = ((printer.clipMinX - x1) / (x2 - x1));
+ }
+
+ if (x2 > printer.clipMaxX) {
+ x2c = printer.clipMaxX;
+ u2c = 1.0f - ((x2 - printer.clipMaxX) / (x2 - x1));
+ }
+
+ if (y1 < printer.clipMinY) {
+ y1c = printer.clipMinY;
+ v2c = 1.0f - ((printer.clipMinY - y1) / (y2 - y1));
+ }
+
+ if (y2 > printer.clipMaxY) {
+ y2c = printer.clipMaxY;
+ v1c = ((y2 - printer.clipMaxY) / (y2 - y1));
+ }
+
+ shader.setQuadTexCoords(u1c, v1c, u2c, v2c);
+ shader.setXYQuadCoords(x1c, y2c, x2c, y1c, 0); // y flipped
+ shader.renderQuad();
+ }
+
+ private static final void drawQuad(BaseShader shader, float x1, float x2, float y1, float y2)
+ {
+ shader.setQuadTexCoords(0, 0, 1, 1);
+ shader.setXYQuadCoords(x1, y2, x2, y1, 0); // y flipped
+ shader.renderQuad();
}
}
diff --git a/src/main/java/game/message/editor/StringTokenizer.java b/src/main/java/game/message/editor/MessageTokenizer.java
similarity index 95%
rename from src/main/java/game/message/editor/StringTokenizer.java
rename to src/main/java/game/message/editor/MessageTokenizer.java
index 136a41c..0f96ea4 100644
--- a/src/main/java/game/message/editor/StringTokenizer.java
+++ b/src/main/java/game/message/editor/MessageTokenizer.java
@@ -8,12 +8,12 @@
import app.input.Line;
import game.message.MessageAnim;
-public class StringTokenizer
+public class MessageTokenizer
{
public static void main(String[] args)
{
String text = "%This [is] [[a] [] TE\\\\\\ST[b";
- (new StringTokenizer(text)).print();
+ (new MessageTokenizer(text)).print();
}
private void print()
@@ -28,20 +28,20 @@ private void print()
public static ArrayList tokenize(String text)
{
- return new StringTokenizer(text).sequences;
+ return new MessageTokenizer(text).sequences;
}
public static ArrayList tokenize(List lines)
{
- return new StringTokenizer(lines).sequences;
+ return new MessageTokenizer(lines).sequences;
}
- private StringTokenizer(String text)
+ private MessageTokenizer(String text)
{
add(text, null);
}
- private StringTokenizer(List lines)
+ private MessageTokenizer(List lines)
{
for (Line line : lines)
add(line.str, line);
diff --git a/src/main/java/game/message/editor/SimpleMessageRenderer.java b/src/main/java/game/message/editor/SimpleMessageRenderer.java
new file mode 100644
index 0000000..e6b7758
--- /dev/null
+++ b/src/main/java/game/message/editor/SimpleMessageRenderer.java
@@ -0,0 +1,73 @@
+package game.message.editor;
+
+import java.io.IOException;
+
+import game.message.StringConstants;
+import game.message.font.FontManager;
+import game.message.font.FontType;
+import renderer.shaders.ShaderManager;
+import renderer.shaders.scene.FontShader;
+
+public class SimpleMessageRenderer
+{
+ private static final int FONT_SIZE_X = 16;
+ private static final int FONT_SIZE_Y = 16;
+
+ public static void init() throws IOException
+ {
+ if (!FontManager.isLoaded())
+ FontManager.loadData();
+
+ if (!FontManager.isReadyForGL())
+ FontManager.glLoad();
+ }
+
+ public void drawString(int posX, int posY, int size, String text)
+ {
+ FontShader shader = ShaderManager.use(FontShader.class);
+ shader.noiseMode.set(0);
+ shader.fadeAlpha.set(1.0f);
+ shader.enableDropShadow.set(false);
+
+ for (char c : text.toCharArray()) {
+ int index = StringConstants.getIndex(c, true);
+ if (index < 0)
+ continue;
+
+ int endX = posX + (int) (FONT_SIZE_X * size / 16.0f);
+ int endY = posY - (int) (FONT_SIZE_Y * size / 16.0f);
+ int charWidth = getCharWidth(FontType.Normal, 0, index, size / 16.0f);
+
+ if (index < FontType.Normal.chars.numChars) {
+ FontType.Normal.chars.images[index].glBind(shader.texture);
+ FontType.Normal.chars.palettes[0x14].glBind(shader.palette);
+ shader.setQuadTexCoords(0, 0, 1, 1);
+ shader.setXYQuadCoords(posX, posY, endX, endY, 0); // y flipped
+ shader.renderQuad();
+ }
+ posX += charWidth;
+ }
+ }
+
+ private static int getCharWidth(FontType font, int subfont, int index, float stringScale)
+ {
+ if (index < 0xFA) {
+ int width;
+ if ((index == 0xF7) || (index == 0xF8) || (index == 0xF9))
+ width = font.fullspaceWidth[subfont];
+ else
+ width = font.chars.widths[index];
+
+ if (index == 0xF7)
+ return (int) ((width * stringScale) * 0.6);
+ if (index == 0xF8)
+ return (int) (width * stringScale);
+ if (index == 0xF9)
+ return (int) ((width * stringScale) * 0.5);
+ if (index >= 0xF0)
+ return 0; // other control chars
+ return (int) (width * stringScale);
+ }
+ return 0;
+ }
+}
diff --git a/src/main/java/game/message/editor/StringRenderer.java b/src/main/java/game/message/editor/StringRenderer.java
deleted file mode 100644
index 4689437..0000000
--- a/src/main/java/game/message/editor/StringRenderer.java
+++ /dev/null
@@ -1,1240 +0,0 @@
-package game.message.editor;
-
-import static game.message.StringConstants.StringEffect.*;
-import static game.texture.TileFormat.CI_8;
-import static org.lwjgl.opengl.GL11.*;
-
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.FloatBuffer;
-import java.nio.IntBuffer;
-import java.util.List;
-import java.util.Random;
-
-import org.lwjgl.BufferUtils;
-
-import assets.ExpectedAsset;
-import game.SimpleItem;
-import game.map.Axis;
-import game.map.editor.common.MouseInput;
-import game.map.editor.geometry.Vector3f;
-import game.map.editor.render.PresetColor;
-import game.map.editor.render.TextureManager;
-import game.map.shape.TransformMatrix;
-import game.message.MessageBoxes;
-import game.message.StringConstants;
-import game.message.StringConstants.ControlCharacter;
-import game.message.StringConstants.StringFunction;
-import game.message.StringConstants.StringStyle;
-import game.message.font.FontManager;
-import game.message.font.FontType;
-import game.sprite.ImgAsset;
-import game.sprite.Sprite;
-import game.sprite.SpriteLoader;
-import game.sprite.SpriteLoader.SpriteSet;
-import game.sprite.SpriteRaster;
-import game.texture.ImageConverter;
-import game.texture.Palette;
-import game.texture.Texture;
-import game.texture.Tile;
-import renderer.GLUtils;
-import renderer.buffers.LineRenderQueue;
-import renderer.shaders.BaseShader;
-import renderer.shaders.RenderState;
-import renderer.shaders.ShaderManager;
-import renderer.shaders.scene.BasicIndexedShader;
-import renderer.shaders.scene.BasicSolidShader;
-import renderer.shaders.scene.BasicTexturedShader;
-import renderer.shaders.scene.FontShader;
-import util.Logger;
-
-public class StringRenderer
-{
- private final MessageEditor editor;
-
- public final TransformMatrix projMatrix;
- public final TransformMatrix viewMatrix;
-
- private int glBackgroundTexID;
- private int glNoiseTexID;
-
- private Random rng;
- private boolean useFiltering = true;
-
- private int frameCounter = 0;
-
- // extra resources
- private final SpriteLoader spriteLoader;
- private Tile[] glItemPreviews = null;
-
- private BufferedImage varImage = null;
- private boolean varImageLoaded = false;
- private int glVarTexID;
-
- public StringRenderer(MessageEditor editor) throws IOException
- {
- this.editor = editor;
-
- projMatrix = new TransformMatrix();
- viewMatrix = new TransformMatrix();
-
- rng = new Random();
- loadTextures();
- loadItemIcons();
-
- spriteLoader = new SpriteLoader();
- }
-
- public void cleanup()
- {
- MessageBoxes.glDelete();
- FontManager.glDelete();
-
- glDeleteTextures(glBackgroundTexID);
- glDeleteTextures(glNoiseTexID);
- glDeleteTextures(glVarTexID);
-
- if (glItemPreviews != null) {
- for (Tile tile : glItemPreviews) {
- if (tile == null)
- continue;
-
- tile.glDelete();
- tile.palette.glDelete();
- }
- }
- }
-
- private void loadTextures() throws IOException
- {
- Tile img;
- BufferedImage bimg;
-
- glLoadNoise();
-
- // background
- try {
- File imgFile = ExpectedAsset.KMR_BG.getFile();
- img = Tile.load(imgFile, CI_8);
- bimg = ImageConverter.convertToBufferedImage(img);
- glBackgroundTexID = glLoadImage(bimg);
- }
- catch (IOException e) {
- Logger.logError("Could not load background asset: " + ExpectedAsset.KMR_BG.getPath());
- }
-
- MessageBoxes.loadImages();
- MessageBoxes.glLoad();
-
- FontManager.loadData();
- FontManager.glLoad();
- }
-
- private void glLoadNoise()
- {
- BufferedImage bimg = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
- for (int i = 0; i < 256; i++)
- for (int j = 0; j < 256; j++) {
- int I = rng.nextInt() & 0xFF;
- bimg.setRGB(i, j, (0xFF << 24) | (I << 16) | (I << 8) | I);
- }
-
- ByteBuffer buffer = TextureManager.createByteBuffer(bimg);
-
- int glID = glGenTextures();
- glBindTexture(GL_TEXTURE_2D, glID);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bimg.getWidth(),
- bimg.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-
- glNoiseTexID = glID;
- }
-
- private void loadItemIcons() throws IOException
- {
- List items = game.ProjectDatabase.getItemList();
-
- glItemPreviews = new Tile[items.size()];
- for (int i = 0; i < items.size(); i++) {
- Tile tile = items.get(i).iconTile;
- if (tile == null)
- continue;
-
- tile.glLoad(Texture.WRAP_CLAMP, Texture.WRAP_CLAMP, false);
- tile.palette.glLoad();
-
- glItemPreviews[i] = tile;
- }
-
- Logger.log("Loaded icon previews");
- }
-
- public void setVarImage(BufferedImage bimg)
- {
- if (varImageLoaded)
- glDeleteTextures(glVarTexID);
-
- glVarTexID = glLoadImage(bimg);
- varImage = bimg;
- varImageLoaded = true;
- }
-
- private static int glLoadImage(BufferedImage bimg)
- {
- ByteBuffer buffer = TextureManager.createByteBuffer(bimg);
-
- int glID = glGenTextures();
- glBindTexture(GL_TEXTURE_2D, glID);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, bimg.getWidth(),
- bimg.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
-
- return glID;
- }
-
- private final void drawBackground(int glTexID)
- {
- projMatrix.ortho(0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f);
- RenderState.setProjectionMatrix(projMatrix);
- RenderState.setViewMatrix(null);
-
- float hfov = 105;
- float right = (hfov + 360) / 360;
- float scaleX = RenderState.getViewportSizeX() / 600.0f;
-
- BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class);
- shader.texture.bind(glTexID);
- shader.setXYQuadCoords(0, 0, 1, 1, 0);
- shader.setQuadTexCoords(0, 1, right * scaleX, 0);
- shader.renderQuad();
- }
-
- private static void drawGrid(StringPrinter printer)
- {
- RenderState.setLineWidth(1.5f);
-
- int xstart = printer.windowBasePosX + printer.windowTextStartX;
- int ystart = printer.windowBasePosY + printer.windowTextStartY;
- int xmax = ((printer.clipMaxX - xstart) / 10) * 10;
- int ymax = ((printer.clipMaxY - ystart) / 10) * 10;
-
- for (int i = 0; i <= xmax; i += 10) {
- float alpha = ((i % 20) == 0) ? 0.5f : 0.2f;
- int v1 = LineRenderQueue.addVertex()
- .setPosition(xstart + i, ystart, 0)
- .setColor(0.15f, 0.15f, 0.15f, alpha)
- .getIndex();
- int v2 = LineRenderQueue.addVertex()
- .setPosition(xstart + i, ystart + ymax, 0)
- .setColor(0.15f, 0.15f, 0.15f, alpha)
- .getIndex();
- LineRenderQueue.addLine(v1, v2);
- }
-
- for (int i = 0; i <= ymax; i += 10) {
- float alpha = ((i % 20) == 0) ? 0.5f : 0.2f;
- int v1 = LineRenderQueue.addVertex()
- .setPosition(xstart, ystart + i, 0)
- .setColor(0.15f, 0.15f, 0.15f, alpha)
- .getIndex();
- int v2 = LineRenderQueue.addVertex()
- .setPosition(xstart + xmax, ystart + i, 0)
- .setColor(0.15f, 0.15f, 0.15f, alpha)
- .getIndex();
- LineRenderQueue.addLine(v1, v2);
- }
-
- RenderState.setDepthWrite(false);
- LineRenderQueue.render(true);
- RenderState.setDepthWrite(true);
- }
-
- private static void drawBackgroundGuide(StringPrinter printer)
- {
- int v1, v2, v3, v4;
- RenderState.setLineWidth(2.0f);
-
- RenderState.setColor(PresetColor.RED);
- v1 = LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex();
- v2 = LineRenderQueue.addVertex().setPosition(320, 0, 0).getIndex();
- v3 = LineRenderQueue.addVertex().setPosition(320, 240, 0).getIndex();
- v4 = LineRenderQueue.addVertex().setPosition(0, 240, 0).getIndex();
- LineRenderQueue.addLine(v1, v2, v3, v4, v1);
-
- RenderState.setColor(PresetColor.BLUE);
- v1 = LineRenderQueue.addVertex().setPosition(12, 20, 0).getIndex();
- v2 = LineRenderQueue.addVertex().setPosition(320 - 12, 20, 0).getIndex();
- v3 = LineRenderQueue.addVertex().setPosition(320 - 12, 240 - 20, 0).getIndex();
- v4 = LineRenderQueue.addVertex().setPosition(12, 240 - 20, 0).getIndex();
- LineRenderQueue.addLine(v1, v2, v3, v4, v1);
-
- // LineRenderQueue.printContents();
-
- RenderState.setDepthWrite(false);
- LineRenderQueue.render(true);
- RenderState.setDepthWrite(true);
- }
-
- private static void drawForegroundGuide(StringPrinter printer)
- {
- int v1, v2, v3, v4;
- RenderState.setLineWidth(1.5f);
-
- RenderState.setColor(PresetColor.GREEN);
- v1 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX, printer.windowBasePosY, 0).getIndex();
- v2 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX, printer.windowBasePosY + printer.windowSizeY, 0).getIndex();
- v3 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX + printer.windowSizeX, printer.windowBasePosY + printer.windowSizeY, 0)
- .getIndex();
- v4 = LineRenderQueue.addVertex().setPosition(printer.windowBasePosX + printer.windowSizeX, printer.windowBasePosY, 0).getIndex();
- LineRenderQueue.addLine(v1, v2, v3, v4, v1);
-
- RenderState.setColor(PresetColor.TEAL);
- v1 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX, printer.rewindArrowY, 0).getIndex();
- v2 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX, printer.rewindArrowY + 24, 0).getIndex();
- v3 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX + 24, printer.rewindArrowY + 24, 0).getIndex();
- v4 = LineRenderQueue.addVertex().setPosition(printer.rewindArrowX + 24, printer.rewindArrowY, 0).getIndex();
- LineRenderQueue.addLine(v1, v2, v3, v4, v1);
-
- RenderState.setColor(PresetColor.YELLOW);
- v1 = LineRenderQueue.addVertex().setPosition(printer.clipMinX, printer.clipMinY, 0).getIndex();
- v2 = LineRenderQueue.addVertex().setPosition(printer.clipMinX, printer.clipMaxY, 0).getIndex();
- v3 = LineRenderQueue.addVertex().setPosition(printer.clipMaxX, printer.clipMaxY, 0).getIndex();
- v4 = LineRenderQueue.addVertex().setPosition(printer.clipMaxX, printer.clipMinY, 0).getIndex();
- LineRenderQueue.addLine(v1, v2, v3, v4, v1);
-
- RenderState.setDepthWrite(false);
- LineRenderQueue.render(true);
- RenderState.setDepthWrite(true);
- }
-
- private static final void drawAxes(float lineWidth)
- {
- RenderState.setLineWidth(lineWidth);
-
- RenderState.setColor(PresetColor.RED);
- LineRenderQueue.addLine(
- LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(),
- LineRenderQueue.addVertex().setPosition(Short.MAX_VALUE, 0, 0).getIndex());
-
- RenderState.setColor(PresetColor.GREEN);
- LineRenderQueue.addLine(
- LineRenderQueue.addVertex().setPosition(0, 0, 0).getIndex(),
- LineRenderQueue.addVertex().setPosition(0, Short.MAX_VALUE, 0).getIndex());
-
- LineRenderQueue.render(true);
- }
-
- public Vector3f getMousePosition(MouseInput mouse, boolean useDepth)
- {
- int mouseX = mouse.getPosX();
- int mouseY = mouse.getPosY();
-
- int width = editor.glCanvasWidth();
- int height = editor.glCanvasHeight();
-
- IntBuffer viewport = BufferUtils.createIntBuffer(16);
- viewport.put(0);
- viewport.put(0);
- viewport.put(width);
- viewport.put(height);
- viewport.rewind();
-
- float winX = mouseX;
- float winY = mouseY;
- float winZ = 0;
-
- if (useDepth) {
- // this is the expensive part, reading z from the depth buffer
- FloatBuffer fb = BufferUtils.createFloatBuffer(1);
- glReadPixels(mouseX, mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, fb);
- winZ = fb.get();
- }
-
- FloatBuffer position = BufferUtils.createFloatBuffer(3);
- GLUtils.gluUnProject(winX, winY, winZ, viewMatrix.toFloatBuffer(), projMatrix.toFloatBuffer(), viewport, position);
-
- return new Vector3f(position.get(), position.get(), position.get());
- }
-
- public void render(MouseInput mouse, StringPrinter printer, float cameraX, float cameraY, float cameraZoom, float cameraYaw)
- {
- assert (printer != null);
-
- drawBackground(glBackgroundTexID);
-
- float halfW = (editor.glCanvasWidth() / 2.0f) * cameraZoom;
- float halfH = (editor.glCanvasHeight() / 2.0f) * cameraZoom;
- projMatrix.ortho(-halfW, halfW, halfH, -halfH, 1, 0x20000);
- // projMatrix.perspective(60, (float)editor.glCanvasWidth() / editor.glCanvasHeight(), 1, 0x2000);
- RenderState.setProjectionMatrix(projMatrix);
-
- viewMatrix.setIdentity();
- viewMatrix.translate(new Vector3f(-cameraX, -cameraY, -400.0f * cameraZoom));
- viewMatrix.rotate(Axis.Y, cameraYaw);
- RenderState.setViewMatrix(viewMatrix);
- RenderState.setModelMatrix(null);
-
- if (editor.shouldShowViewportGuides())
- drawBackgroundGuide(printer);
-
- // drawAxes(1.0f);
-
- DrawState state = new DrawState(printer);
- state.useCulling = editor.isCullingEnabled();
-
- printer.drawMessageBox();
-
- FontShader shader = ShaderManager.use(FontShader.class);
- shader.enableFiltering.set(useFiltering);
- shader.fadeAlpha.set(1.0f);
-
- float scrollY = printer.scrollAmount * (state.currentFont.chars.defaultY * state.stringScaleY + printer.style.lineOffset);
- int printOffsetX = 0;
- int printOffsetY = -(int) (scrollY);
-
- state.printPosX = 0;
- state.printPosY = 0;
- printer.drawBuffer.rewind();
-
- read_buf:
- while (printer.drawBuffer.position() < printer.printPos) {
- byte charByte = printer.drawBuffer.get();
- int charInt = charByte & 0xFF;
-
- if (charInt == StringPrinter.PAGE_END_MARK) {
- continue;
- }
- else if (charInt == StringPrinter.BUFFER_FILL) {
- break; // end of string
- }
- else if (charInt < 0xF0) {
- int charWidth = MessageUtil.getCharWidth(state.currentFont, state.fontVariant, charInt, state.stringScaleX, state.charWidthOverride,
- 0);
- if (charInt < state.currentFont.chars.numChars)
- renderChar(printer, state, printOffsetX, printOffsetY, charInt);
- state.printPosX += charWidth;
- }
- else if (charInt == 0xF7 || charInt == 0xF8 || charInt == 0xF9) {
- int charWidth = MessageUtil.getCharWidth(state.currentFont, state.fontVariant, charInt, state.stringScaleX, state.charWidthOverride,
- 0);
- state.printPosX += charWidth;
- }
- else {
- switch (ControlCharacter.decodeMap.get(charByte)) {
- case ENDL: // 0xF0
- state.printPosX = 0;
- state.printPosY += state.currentFont.chars.defaultY * state.stringScaleY + printer.style.lineOffset;
- break;
-
- case NEXT: // 0xFB
- break;
-
- case WAIT: // 0xF1
- throw new IllegalStateException(this.getClass().getSimpleName() + " should not encounter WAIT");
-
- case PAUSE: // 0xF2
- printer.drawBuffer.get();
- throw new IllegalStateException(this.getClass().getSimpleName() + " should not encounter PAUSE");
-
- case VARIANT0: // 0xF3
- case VARIANT1: // 0xF4
- case VARIANT2: // 0xF5
- case VARIANT3: // 0xF6
- state.fontVariant = charInt - 0xF3;
- break;
-
- // 0xF7-0xF9 are spaces
- // 0xFA = unknown
-
- case STYLE: // 0xFC
- handleStyle(printer, state);
- break;
-
- case END: // 0xFD
- break read_buf;
-
- // 0xFE = unused afaik
- case FUNC: // 0xFF
- handleFunction(printer, state, printOffsetX, printOffsetY);
- break;
- }
- }
- }
-
- frameCounter++;
-
- RenderState.setModelMatrix(null);
- if (editor.shouldShowGrid())
- drawGrid(printer);
-
- // drawForegroundGuide(printer);
-
- drawUI(mouse, printer);
- }
-
- private void drawUI(MouseInput mouse, StringPrinter printer)
- {
- // set UI matrices
- TransformMatrix mtx = TransformMatrix.identity();
- mtx.ortho(0, editor.glCanvasWidth(), 0, editor.glCanvasHeight(), -1, 1);
- RenderState.setProjectionMatrix(mtx);
- RenderState.setViewMatrix(null);
- RenderState.setModelMatrix(null);
-
- RenderState.enableDepthTest(false);
-
- if (mouse.hasLocation()) {
- Vector3f worldPos = getMousePosition(mouse, false);
- int mx = Math.round(worldPos.x) - (printer.windowBasePosX + printer.windowTextStartX);
- int my = Math.round(worldPos.y) - (printer.windowBasePosY + printer.windowTextStartY);
- drawString(0x14, 8, editor.glCanvasHeight() - 4, 16, String.format("Cursor Pos: %3d, %2d", mx, my));
- }
-
- float bufferFillPercent = 100.0f * printer.compiledLength / StringPrinter.MAX_LENGTH;
-
- if (bufferFillPercent > 100.0f) {
- drawString(0x12, 176, editor.glCanvasHeight() - 4, 16, String.format("ERROR: String buffer at %.1f%% capacity! (%d/%d)",
- bufferFillPercent, printer.compiledLength, StringPrinter.MAX_LENGTH));
- }
- else if (bufferFillPercent > 75.0f) {
- int palID = 5;
- if (bufferFillPercent > 90.0f)
- palID = 6;
- if (bufferFillPercent > 95.0f)
- palID = 7;
- drawString(palID, 176, editor.glCanvasHeight() - 4, 16, String.format("WARNING: String buffer at %.1f%% capacity! (%d/%d)",
- bufferFillPercent, printer.compiledLength, StringPrinter.MAX_LENGTH));
- }
-
- RenderState.enableDepthTest(true);
- }
-
- private void handleStyle(StringPrinter printer, DrawState state)
- {
- switch (StringStyle.decodeMap.get(printer.drawBuffer.get())) {
- case RIGHT:
- case LEFT:
- case CENTER:
- case TATTLE:
- case CHOICE:
- state.textColor = 0xA;
- break;
- case INSPECT:
- case UPGRADE:
- case NARRATE:
- case STYLE_F:
- state.textColor = 0;
- break;
- case SIGN:
- state.textColor = 0x18;
- break;
- case LAMPPOST:
- state.textColor = 0x1C;
- break;
- case POSTCARD:
- case POPUP:
- case STYLE_B:
- state.textColor = 0;
- break;
- case EPILOGUE:
- state.textColor = 0;
- break;
- }
- }
-
- private void handleFunction(StringPrinter printer, DrawState state, int relativePosX, int relativePosY)
- {
- int startX = state.getScreenPosX(relativePosX);
- int startY = state.getScreenPosY(relativePosY);
- StringFunction func = StringFunction.decodeMap.get(printer.drawBuffer.get());
-
- switch (func) {
- case CURSOR:
- case OPTION:
- case SET_CANCEL:
- case END_CHOICE:
- printer.drawBuffer.get();
- break; // completely ignored by editor
-
- case VAR:
- printer.drawBuffer.get();
- break; // already handled during encoding
-
- case FONT:
- int fontType = (printer.drawBuffer.get() & 0xFF);
- switch (fontType) {
- case 0:
- state.currentFont = FontType.Normal;
- break;
- case 1:
- state.currentFont = FontType.Menus;
- break;
- case 2:
- state.currentFont = FontType.Menus;
- break;
- case 3:
- state.currentFont = FontType.Title;
- break;
- case 4:
- state.currentFont = FontType.Subtitle;
- break;
- }
- break;
-
- case VARIANT:
- state.fontVariant = (printer.drawBuffer.get() & 0xFF);
- break;
-
- case ANIM_DONE:
- if (printer.hasAnim()) {
- int spriteID = printer.getAnimSprite();
- int rasterID = printer.getAnimRaster();
-
- Sprite npc = spriteLoader.getSprite(SpriteSet.Npc, spriteID);
- if (npc != null && !npc.areTexturesLoaded())
- npc.loadTextures();
-
- if (npc != null && npc.rasters.getSize() > rasterID) {
- BasicIndexedShader shader = ShaderManager.use(BasicIndexedShader.class);
- SpriteRaster raster = npc.rasters.get(rasterID);
- ImgAsset front = raster.getFront();
- if (front != null) {
- front.img.glBind(shader.texture);
- front.getPalette().glBind(shader.palette);
- drawClippedQuad(shader, state, startX, startX + front.img.width, startY, startY + front.img.height);
- }
- }
- else {
- BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class);
- float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f;
- shader.baseColor.set(1.0f, f, f, 1.0f);
- drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x40);
- }
- }
- break;
-
- case IMAGE:
- printer.drawBuffer.get(); // index -- ignored
- int posX = printer.drawBuffer.getShort() & 0xFFFF;
- int posY = printer.drawBuffer.get() & 0xFF;
- int border = printer.drawBuffer.get() & 0xFF;
- int alpha = printer.drawBuffer.get() & 0xFF;
- int alphaStep = printer.drawBuffer.get() & 0xFF;
-
- if (varImageLoaded) {
- BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class);
- shader.texture.bind(glVarTexID);
- shader.multiplyBaseColor.set(true);
- shader.baseColor.set(1.0f, 1.0f, 1.0f, alpha / 255.0f);
- drawQuad(shader, posX, posX + varImage.getWidth(), posY, posY + varImage.getHeight());
- }
- else {
- BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class);
- float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f;
- shader.baseColor.set(1.0f, f, f, alpha / 255.0f);
- drawQuad(shader, posX, posX + 150, posY, posY + 105);
- }
- break;
-
- case HIDE_IMAGE:
- printer.drawBuffer.get(); // fade out time
- break;
-
- case INLINE_IMAGE:
- printer.drawBuffer.get(); // index -- ignored
-
- if (varImageLoaded) {
- BasicTexturedShader shader = ShaderManager.use(BasicTexturedShader.class);
- shader.texture.bind(glVarTexID);
- drawClippedQuad(shader, state, startX, startX + varImage.getWidth(), startY, startY + varImage.getHeight());
- }
- else {
- BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class);
- float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f;
- shader.baseColor.set(1.0f, f, f, 1.0f);
- drawClippedQuad(shader, state, startX, startX + 0x40, startY, startY + 0x40);
- }
- break;
-
- case ITEM_ICON:
- int upperItemID = (printer.drawBuffer.get() & 0xFF);
- int lowerItemID = (printer.drawBuffer.get() & 0xFF);
- int itemID = (upperItemID << 8) | lowerItemID;
-
- if (glItemPreviews != null && glItemPreviews.length > itemID && glItemPreviews[itemID] != null) {
- BasicIndexedShader shader = ShaderManager.use(BasicIndexedShader.class);
- glItemPreviews[itemID].glBind(shader.texture);
- glItemPreviews[itemID].palette.glBind(shader.palette);
- drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x20);
- }
- else {
- BasicSolidShader shader = ShaderManager.use(BasicSolidShader.class);
- float f = 0.5f + (float) Math.cos(Math.toRadians(16 * frameCounter)) * 0.25f;
- shader.baseColor.set(1.0f, f, f, 1.0f);
- drawClippedQuad(shader, state, startX, startX + 0x20, startY, startY + 0x20);
- }
- break;
-
- case COLOR:
- state.textColor = (printer.drawBuffer.get() & 0xFF);
- if (state.textColor < 0)
- state.textColor = 0;
- int numPals = state.currentFont.chars.numPals;
- if (state.textColor >= numPals)
- state.textColor = numPals - 1;
- break;
-
- case PUSH_COLOR:
- state.savedColor = state.textColor;
- break;
- case POP_COLOR:
- state.textColor = state.savedColor;
- break;
-
- case PUSH_POS:
- state.savedPosX = state.printPosX;
- state.savedPosY = state.printPosY;
- break;
- case POP_POS:
- state.printPosX = state.savedPosX;
- state.printPosY = state.savedPosY;
- break;
-
- case SPACING:
- state.charWidthOverride = (printer.drawBuffer.get() & 0xFF);
- break;
-
- case SIZE:
- int sx = (printer.drawBuffer.get() & 0xFF);
- int sy = (printer.drawBuffer.get() & 0xFF);
- state.stringScaleX = sx / 16.0f;
- state.stringScaleY = sy / 16.0f;
- state.charScaleX = state.stringScaleX;
- state.charScaleY = state.stringScaleY;
- break;
- case SIZE_RESET:
- state.stringScaleX = 1.0f;
- state.stringScaleY = 1.0f;
- state.charScaleX = state.stringScaleX;
- state.charScaleY = state.stringScaleY;
- break;
-
- case SET_X: // [80129EB4]
- int upper = (printer.drawBuffer.get() & 0xFF);
- int lower = (printer.drawBuffer.get() & 0xFF);
- state.printPosX = (upper << 8) | lower;
- break;
- case SET_Y: // [80129ED8]
- state.printPosY = (printer.drawBuffer.get() & 0xFF);
- break;
- case RIGHT: // [80129F0C]
- state.printPosX += (printer.drawBuffer.get() & 0xFF);
- break;
- case DOWN: // [80129F38]
- state.printPosY += (printer.drawBuffer.get() & 0xFF);
- break;
- case UP: // [80129F64]
- state.printPosY -= (printer.drawBuffer.get() & 0xFF);
- break;
- case CENTER_X: // [8012AAEC]
- state.centerPos = (printer.drawBuffer.get() & 0xFF);
- break;
-
- case START_FX:
- int startFXType = (printer.drawBuffer.get() & 0xFF);
- state.effectActive[startFXType] = true;
- switch (startFXType) {
- case 0x2:
- state.effectActive[3] = false;
- break;
- case 0x3:
- state.effectActive[2] = false;
- state.fadeNoiseAlpha = (printer.drawBuffer.get() & 0xFF) / 255.0f;
- break;
- case 0x5:
- state.fadeJitterArg = (printer.drawBuffer.get() & 0xFF);
- break;
- case 0x7:
- state.fadeAlpha = (printer.drawBuffer.get() & 0xFF) / 255.0f;
- break;
- case 0x6:
- case 0x9:
- state.savedFxColor = state.textColor;
- break;
- case 0xC:
- case 0xD:
- state.savedFxCharScaleX = state.charScaleX;
- state.savedFxCharScaleY = state.charScaleY;
- break;
- }
- break;
-
- case END_FX:
- int endFXType = (printer.drawBuffer.get() & 0xFF);
- // restore saved state (if it has been saved)
- if (state.effectActive[endFXType]) {
- switch (endFXType) {
- case 0x2:
- case 0x3:
- // end clears the flags for these,
- // but will not stop the effect since its
- // part of the display list
- break;
- case 0x6:
- case 0x9:
- state.textColor = state.savedFxColor;
- state.effectActive[endFXType] = false;
- break;
- case 0xC:
- case 0xD:
- state.charScaleX = state.savedFxCharScaleX;
- state.charScaleY = state.savedFxCharScaleY;
- state.effectActive[endFXType] = false;
- break;
- default:
- state.effectActive[endFXType] = false;
- }
- }
- break;
-
- case FUNC_03:
- //XXX unknown, some graphics state reset?
- break;
-
- case SETVOICE:
- case VOICE:
- case VOLUME:
- case SPEED:
- case SCROLL:
- case DELAY_OFF:
- case DELAY_ON:
- case SKIP_OFF:
- case INPUT_OFF:
- case INPUT_ON:
- case ENABLE_CDOWN:
- break; // irrelevant to renderer
-
- case SET_REWIND:
- printer.drawBuffer.get();
- break; // irrelevant to renderer
-
- case YIELD:
- break;
-
- case SET_CURSOR:
- break;
-
- case ANIM_SPRITE:
- case ANIM_DELAY:
- case ANIM_LOOP:
- throw new IllegalStateException("LOGIC ERROR: " + func.name + " in encodeFunctionArgs!");
- }
- }
-
- public void drawString(int palID, int posX, int posY, int size, String text)
- {
- FontShader shader = ShaderManager.use(FontShader.class);
- shader.noiseMode.set(0);
- shader.fadeAlpha.set(1.0f);
- shader.enableDropShadow.set(false);
-
- FontType font = FontType.Normal;
-
- for (char c : text.toCharArray()) {
- int index = StringConstants.getIndex(c, true);
- if (index < 0)
- continue;
-
- int endX = posX + (int) (font.chars.defaultX * size / 16.0f);
- int endY = posY - (int) (font.chars.defaultY * size / 16.0f);
- int charWidth = MessageUtil.getCharWidth(font, 0, index, size / 16.0f, 0, 0);
-
- if (index < font.chars.numChars) {
- font.chars.images[index].glBind(shader.texture);
- font.chars.palettes[palID].glBind(shader.palette);
- drawQuad(shader, posX, endX, posY, endY);
- }
- posX += charWidth;
- }
- }
-
- private void renderChar(StringPrinter printer, DrawState state, int relativePosX, int relativePosY, int charIndex)
- {
- FontShader shader = ShaderManager.use(FontShader.class);
-
- int[] lookahead = new int[4];
- for (int i = 0; i < lookahead.length; i++)
- lookahead[i] = (printer.drawBuffer.get() & 0xFF);
- printer.drawBuffer.position(printer.drawBuffer.position() - lookahead.length);
-
- //XXX correct?
- state.charScaleX = state.stringScaleX;
- state.charScaleY = state.stringScaleY;
- float alpha = 1.0f;
-
- if (state.effectActive[BLUR.code]) // 0x20
- {
- // fade code from [8012ADC4]
- alpha = 0.35f;
- }
-
- if (state.effectActive[SHAKE.code]) {
- // code from [8012AE50]
- relativePosX += rng.nextInt() % 2;
- relativePosY += rng.nextInt() % 2;
- }
-
- if (state.effectActive[WAVE.code]) // 0x2
- {
- // code from [8012AEBC]
- double dsx = state.stringScaleX - 1.0;
- double dsy = state.stringScaleY - 1.0;
-
- //NOTE: game uses a message-specific 'local' frame counter here
- double angle = frameCounter * (int) (20.0 - dsx * 5.0) - state.visibleCharCount * (int) (45.0 - dsx * 15.0);
- relativePosX += Math.cos(Math.toRadians(angle)) * (dsx + 1.6);
- relativePosY += Math.cos(Math.toRadians(angle + 270.0)) * (dsy + 1.6);
- }
- if (state.effectActive[GLOBAL_WAVE.code]) // 0x200
- {
- // code from [8012B0BC]
- double dsx = state.stringScaleX - 1.0;
- double dsy = state.stringScaleY - 1.0;
-
- //NOTE: game uses a 'global' frame counter shared by all messages here
- double angle = frameCounter * (int) (20.0 - dsx * 5.0) - state.visibleCharCount * 45.0;
- relativePosX += Math.cos(Math.toRadians(angle)) * (dsx + 1.6);
- relativePosY += Math.cos(Math.toRadians(angle + 270.0)) * (dsy + 1.6);
- }
-
- if (state.effectActive[RAINBOW.code] || state.effectActive[GLOBAL_RAINBOW.code]) // 0x440 -- either rainbow
- {
- // code from [8012B1B4]
-
- // NOTE: global overrides local here, but they cant stack so we dont need to represent it
- int i = Math.abs(state.visibleCharCount - frameCounter / 3);
- state.textColor = i % 10; // original code: = i + (i / 10) * -10;
- }
-
- // properly respect precedence of these effects
- if (state.effectActive[RISE_PRINT.code] || state.effectActive[GROW_PRINT.code]) {
- if (!printer.donePrinting
- && (lookahead[0] != ControlCharacter.ENDL.code) && (lookahead[1] != ControlCharacter.ENDL.code)
- && (lookahead[2] != ControlCharacter.ENDL.code) && (lookahead[3] != ControlCharacter.ENDL.code)) {
- if (state.effectActive[RISE_PRINT.code]) {
- // from [8012B4F0]
- float dummyScale = 0.25f; //XXX needed to match, unknown why
- if (lookahead[0] == StringPrinter.BUFFER_FILL) {
- state.charScaleX = 1.7f * state.stringScaleX;
- state.charScaleY = 1.7f * state.stringScaleY;
- relativePosX -= 6.0f * state.stringScaleY;
- relativePosY -= dummyScale * 6.0f * state.stringScaleY;
- }
- else if (lookahead[1] == StringPrinter.BUFFER_FILL) {
- state.charScaleX = 1.4f * state.stringScaleX;
- state.charScaleY = 1.4f * state.stringScaleY;
- relativePosX -= 3.0f * state.stringScaleY;
- relativePosY -= dummyScale * 3.0f * state.stringScaleY;
- }
- else if (lookahead[2] == StringPrinter.BUFFER_FILL) {
- state.charScaleX = 1.2f * state.stringScaleX;
- state.charScaleY = 1.2f * state.stringScaleY;
- relativePosX -= 2.0f * state.stringScaleY;
- relativePosY -= dummyScale * 2.0f * state.stringScaleY;
- }
- }
- else if (state.effectActive[GROW_PRINT.code]) {
- // from [8012B740]
- if (lookahead[0] == StringPrinter.BUFFER_FILL) {
- state.charScaleX = 0.3f * state.stringScaleX;
- state.charScaleY = 0.3f * state.stringScaleY;
- relativePosX += 5;
- relativePosY += 5;
- }
- else if (lookahead[1] == StringPrinter.BUFFER_FILL) {
- state.charScaleX = 0.5f * state.stringScaleX;
- state.charScaleY = 0.5f * state.stringScaleY;
- relativePosX += 3;
- relativePosY += 3;
- }
- else if (lookahead[2] == StringPrinter.BUFFER_FILL) {
- state.charScaleX = 0.75f * state.stringScaleX;
- state.charScaleY = 0.75f * state.stringScaleY;
- relativePosX += 2;
- relativePosY += 2;
- }
- }
- }
- }
- else if (state.effectActive[SIZE_JITTER.code] || state.effectActive[SIZE_WAVE.code]) {
- float scale = 1.0f;
-
- if (state.effectActive[SIZE_JITTER.code]) // 0x2000 -- size jitter
- {
- // code from [8012B8BC]
- scale = 0.75f + 0.5f * (rng.nextInt(101) / 100.0f);
- }
- else if (state.effectActive[SIZE_WAVE.code]) // 0x4000 -- size wave
- {
- // code from [8012BA24]
- int i = (frameCounter - state.visibleCharCount) * 15;
- scale = 1.0f + 0.25f * (float) Math.cos(Math.toRadians(i + ((i >> 3) / 45) * 360.0));
- }
-
- state.charScaleX *= scale;
- state.charScaleY *= scale;
-
- if (scale >= 1.0) {
- // [8012BACC]
- int posOffset = (int) (scale * 8.0 - 8.5);
- relativePosX -= posOffset;
- relativePosY -= posOffset;
- }
- else {
- // [8012BB7C]
- int posOffset = (int) (8.0 - 8.0 * scale);
- relativePosX += posOffset;
- relativePosY += posOffset;
- }
- }
-
- shader.noiseMode.set(0); // initial value
-
- if (state.effectActive[DITHER_FADE.code]) //0x80 -- fade
- {
- alpha *= state.fadeAlpha;
- shader.noiseMode.set(7);
- shader.noiseAlpha.set(state.fadeAlpha);
- shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat());
- }
- else {
- if (state.effectActive[NOISE_OUTLINE.code]) // 0x04 -- noise
- {
- shader.noiseMode.set(2);
- shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat());
-
- // add Gfx:
- // SET_COMBINE FC70FEE1 FFFFF3F9
-
- // color: G_CCMUX_NOISE * G_CCMUX_TEXEL0
- // alpha: G_ACMUX_TEXEL0
- }
-
- if (state.effectActive[STATIC.code]) // 0x10000 -- faded noise
- {
- shader.noiseMode.set(3);
- shader.noiseAlpha.set(state.fadeNoiseAlpha);
- shader.noiseOffset.set(rng.nextFloat(), rng.nextFloat());
-
- // add Gfx:
- // SET_ENVCOLOR FB000000 arg << 0x18 | arg << 0x10 | arg << 8;
- // SET_COMBINE FC72FEE5 11FCF279
-
- // color: (G_CCMUX_NOISE - G_CCMUX_TEXEL0) * G_CCMUX_ENVIRONMENT + G_CCMUX_TEXEL0
- // alpha: G_ACMUX_TEXEL0
- }
- }
-
- shader.fadeAlpha.set(alpha);
-
- int baseOffset = 0;
- if (state.fontVariant < state.currentFont.numVariants && state.fontVariant >= 0)
- baseOffset = state.currentFont.baseHeightOffset[state.fontVariant];
-
- int startX = state.getScreenPosX(relativePosX);
- int startY = state.getScreenPosY(relativePosY + baseOffset);
- int endX = startX + (int) (state.currentFont.chars.defaultX * state.charScaleX);
- int endY = startY + (int) (state.currentFont.chars.defaultY * state.charScaleY);
-
- if (state.effectActive[DROP_SHADOW.code]) // 0x8000 -- drop shadow
- {
- shader.enableDropShadow.set(true);
- drawFontQuad(shader, state,
- state.currentFont.chars.images[charIndex],
- state.currentFont.chars.palettes[state.getColor()],
- startX + 2, endX + 2, startY + 2, endY + 2);
- shader.enableDropShadow.set(false);
- }
-
- if (state.effectActive[BLUR.code]) // 0x20 -- FadedJitter
- {
- // code from [8012BDF4]
- for (int i = 0; i < 5; i++) {
- int jx = (state.fadeJitterArg == 2) ? 0 : rng.nextInt(3) - 1;
- int jy = (state.fadeJitterArg == 1) ? 0 : rng.nextInt(3) - 1;
-
- drawFontQuad(shader, state,
- state.currentFont.chars.images[charIndex],
- state.currentFont.chars.palettes[state.getColor()],
- startX + jx, endX + jx, startY + jy, endY + jy);
- }
- }
- else {
- drawFontQuad(shader, state,
- state.currentFont.chars.images[charIndex],
- state.currentFont.chars.palettes[state.getColor()],
- startX, endX, startY, endY);
- }
-
- state.visibleCharCount++;
- }
-
- private static class DrawState
- {
- public final StringPrinter printer;
-
- private FontType currentFont = FontType.Normal;
- public int fontVariant = 0;
-
- private boolean[] effectActive;
- private float fadeAlpha = 1.0f;
- private float fadeNoiseAlpha = 0;
- private int fadeJitterArg = 0;
-
- private int textColor = 0xA;
-
- private int visibleCharCount = 0;
-
- private boolean useCulling = true;
-
- private int printPosX = 0;
- private int printPosY = 0;
-
- private int centerPos = 0;
-
- private int savedColor;
- private int savedPosX = 0;
- private int savedPosY = 0;
- private int savedFxColor = -1;
- private float savedFxCharScaleX = 1.0f;
- private float savedFxCharScaleY = 1.0f;
-
- private int charWidthOverride = 0;
-
- private float charScaleX = 1.0f;
- private float charScaleY = 1.0f;
-
- private float stringScaleX = 1.0f;
- private float stringScaleY = 1.0f;
-
- private DrawState(StringPrinter printer)
- {
- this.printer = printer;
- effectActive = new boolean[StringConstants.StringEffect.values().length];
- }
-
- public int getColor()
- {
- switch (currentFont) {
- case Normal:
- case Menus:
- default:
- return textColor;
- case Title:
- case Subtitle:
- return 0;
- }
- }
-
- public int getScreenPosX(int offsetX)
- {
- int centerOffset = 0;
- if (centerPos == 0xFF)
- centerOffset = 160 - (printer.stringWidth / 2);
- else if (centerPos != 0)
- centerOffset = centerPos - (printer.stringWidth / 2);
-
- if (centerOffset == 0)
- return printer.windowBasePosX + printer.windowTextStartX + printPosX + offsetX;
- else
- return centerOffset + printPosX + offsetX;
- }
-
- public int getScreenPosY(int offsetY)
- {
- return printer.windowBasePosY + printer.windowTextStartY + printPosY + offsetY;
- }
- }
-
- private void drawFontQuad(FontShader shader, DrawState state, Tile img, Palette pal, float x1, float x2, float y1, float y2)
- {
- img.glBind(shader.texture);
- pal.glBind(shader.palette);
- shader.noise.bind(glNoiseTexID);
- drawClippedQuad(shader, state, x1, x2, y1, y2);
- }
-
- private static final void drawClippedQuad(BaseShader shader, DrawState state, float x1, float x2, float y1, float y2)
- {
- if (state.useCulling)
- drawClippedQuad(shader, state.printer, x1, x2, y1, y2);
- else
- drawQuad(shader, x1, x2, y1, y2);
- }
-
- private static final void drawClippedQuad(BaseShader shader, StringPrinter printer, float x1, float x2, float y1, float y2)
- {
- float x1c = x1;
- float x2c = x2;
-
- float y1c = y1;
- float y2c = y2;
-
- float u1c = 0.0f;
- float u2c = 1.0f;
-
- float v1c = 0.0f;
- float v2c = 1.0f;
-
- assert (x1 < x2);
- assert (y1 < y2);
-
- if ((x2 < printer.clipMinX) || (x1 > printer.clipMaxX) || (y2 < printer.clipMinY) || (y1 > printer.clipMaxY))
- return;
-
- if (x1 < printer.clipMinX) {
- x1c = printer.clipMinX;
- u1c = ((printer.clipMinX - x1) / (x2 - x1));
- }
-
- if (x2 > printer.clipMaxX) {
- x2c = printer.clipMaxX;
- u2c = 1.0f - ((x2 - printer.clipMaxX) / (x2 - x1));
- }
-
- if (y1 < printer.clipMinY) {
- y1c = printer.clipMinY;
- v2c = 1.0f - ((printer.clipMinY - y1) / (y2 - y1));
- }
-
- if (y2 > printer.clipMaxY) {
- y2c = printer.clipMaxY;
- v1c = ((y2 - printer.clipMaxY) / (y2 - y1));
- }
-
- shader.setQuadTexCoords(u1c, v1c, u2c, v2c);
- shader.setXYQuadCoords(x1c, y2c, x2c, y1c, 0); // y flipped
- shader.renderQuad();
- }
-
- private static final void drawQuad(BaseShader shader, float x1, float x2, float y1, float y2)
- {
- shader.setQuadTexCoords(0, 0, 1, 1);
- shader.setXYQuadCoords(x1, y2, x2, y1, 0); // y flipped
- shader.renderQuad();
- }
-}
diff --git a/src/main/java/game/sprite/editor/SpriteEditor.java b/src/main/java/game/sprite/editor/SpriteEditor.java
index 71e9c3c..5eadf22 100644
--- a/src/main/java/game/sprite/editor/SpriteEditor.java
+++ b/src/main/java/game/sprite/editor/SpriteEditor.java
@@ -611,7 +611,9 @@ private boolean setAnimation(SpriteAnimation animation)
}
public SpriteAnimation getAnimation()
- { return currentAnim; }
+ {
+ return currentAnim;
+ }
private void setComponent(int id, boolean fromTabChange)
{
@@ -649,7 +651,9 @@ private void setComponent(int id, boolean fromTabChange)
}
public ImgAsset getSelectedImage()
- { return selectedImgAsset; }
+ {
+ return selectedImgAsset;
+ }
private void setPalette(SpritePalette pm)
{
@@ -702,7 +706,7 @@ public void keyPress(KeyInputEvent key)
if (sprite != null && currentAnim != null && currentComp != null && currentComp.selected) {
if (currentAnim.components.size() > 1) {
SwingUtilities.invokeLater(() -> {
- if (JOptionPane.YES_OPTION == super.showConfirmDialog("Delete component?", "Confirm")) {
+ if (JOptionPane.YES_OPTION == super.getConfirmDialog("Confirm", "Delete component?").choose()) {
invokeLater(() -> {
currentAnim.components.removeElement(currentComp);
sprite.recalculateIndices();
@@ -968,12 +972,12 @@ private void addOptionsMenu(JMenuBar menuBar, ActionListener openLogAction)
try {
int id = SpriteLoader.getMaximumID(spriteSet) + 1;
SpriteLoader.create(spriteSet, id);
-
+
if(spriteSet == SpriteSet.Npc)
useNpcFiles(id);
else
usePlayerFiles(id);
-
+
} catch (Throwable t) {
Logger.logError("Failed to create new sprite.");
incrementDialogsOpen();
@@ -983,7 +987,7 @@ private void addOptionsMenu(JMenuBar menuBar, ActionListener openLogAction)
});
});
menu.add(item);
-
+
menu.addSeparator();
*/
@@ -1439,7 +1443,7 @@ private void showAnimationsEditorWindow()
return;
ListEditPanel listPanel = new AnimationListEditPanel(sprite, sprite.animations, this);
- showOptionDialog(listPanel, "Edit " + sprite + " Animations", new String[] { "Done" });
+ getOptionDialog("Edit " + sprite + " Animations", listPanel).setOptions("Done").choose();
invokeLater(() -> {
setSprite(spriteID, false);
@@ -1456,7 +1460,7 @@ private void showComponentsEditorWindow()
return;
ListEditPanel listPanel = new ComponentListEditPanel(currentAnim, currentAnim.components);
- showOptionDialog(listPanel, "Edit " + currentAnim + " Components", new String[] { "Done" });
+ getOptionDialog("Edit " + currentAnim + " Components", listPanel).setOptions("Done").choose();
invokeLater(() -> {
sprite.recalculateIndices();
@@ -1474,7 +1478,14 @@ else if (!currentAnim.components.isEmpty())
private void showControls()
{
incrementDialogsOpen();
- SwingUtils.showFramedMessageDialog(getFrame(), new ShortcutListPanel(), "Controls and Shortcuts", JOptionPane.PLAIN_MESSAGE);
+
+ SwingUtils.getMessageDialog()
+ .setParent(getFrame())
+ .setTitle("Controls and Shortcuts")
+ .setMessage(new SpriteShortcutsPanel())
+ .setMessageType(JOptionPane.PLAIN_MESSAGE)
+ .show();
+
decrementDialogsOpen();
}
diff --git a/src/main/java/game/sprite/editor/ShortcutListPanel.java b/src/main/java/game/sprite/editor/SpriteShortcutsPanel.java
similarity index 96%
rename from src/main/java/game/sprite/editor/ShortcutListPanel.java
rename to src/main/java/game/sprite/editor/SpriteShortcutsPanel.java
index 098a680..d2a49b3 100644
--- a/src/main/java/game/sprite/editor/ShortcutListPanel.java
+++ b/src/main/java/game/sprite/editor/SpriteShortcutsPanel.java
@@ -8,9 +8,9 @@
import net.miginfocom.swing.MigLayout;
-public class ShortcutListPanel extends JPanel
+public class SpriteShortcutsPanel extends JPanel
{
- public ShortcutListPanel()
+ public SpriteShortcutsPanel()
{
setLayout(new MigLayout("fill"));
diff --git a/src/main/java/game/texture/editor/ImageEditor.java b/src/main/java/game/texture/editor/ImageEditor.java
index cd760fc..926f628 100644
--- a/src/main/java/game/texture/editor/ImageEditor.java
+++ b/src/main/java/game/texture/editor/ImageEditor.java
@@ -53,10 +53,10 @@
import game.texture.editor.dialogs.ConvertOptionsPanel.ConvertSettings;
import game.texture.editor.dialogs.ConvertOptionsPanel.ConvertSettings.IntensityMethod;
import game.texture.editor.dialogs.CreateOptionsPanel;
+import game.texture.editor.dialogs.ImageShortcutsPanel;
import game.texture.editor.dialogs.ImportOptionsPanel;
import game.texture.editor.dialogs.ResizeOptionsPanel;
import game.texture.editor.dialogs.ResizeOptionsPanel.ResizeOptions;
-import game.texture.editor.dialogs.ShorcutListPanel;
import net.miginfocom.swing.MigLayout;
import renderer.buffers.LineRenderQueue;
import renderer.shaders.RenderState;
@@ -302,11 +302,15 @@ public void setSelectedColor(Color c)
private void showControls()
{
- JPanel panel = new JPanel();
- panel.add(new ShorcutListPanel());
-
incrementDialogsOpen();
- SwingUtils.showFramedMessageDialog(getFrame(), new ShorcutListPanel(), "Controls and Shortcuts", JOptionPane.PLAIN_MESSAGE);
+
+ SwingUtils.getMessageDialog()
+ .setParent(getFrame())
+ .setTitle("Controls and Shortcuts")
+ .setMessage(new ImageShortcutsPanel())
+ .setMessageType(JOptionPane.PLAIN_MESSAGE)
+ .show();
+
decrementDialogsOpen();
}
@@ -854,9 +858,9 @@ private void exportImage()
private File promptOverwrite(File file)
{
- int choice = showOptionDialog(
- "File already exists: \n" + file.getName(),
- "Export Image", new String[] { "Overwrite", "Choose File", "Cancel" });
+ int choice = getOptionDialog("Export Image", "File already exists: \n" + file.getName())
+ .setOptions("Overwrite", "Choose File", "Cancel")
+ .choose();
if (choice == 0)
return file;
@@ -901,7 +905,7 @@ private void newImageEDT()
assert (SwingUtilities.isEventDispatchThread());
CreateOptionsPanel createOptions = new CreateOptionsPanel();
- int choice = ImageEditor.super.showConfirmDialog(createOptions, "New Image Options");
+ int choice = ImageEditor.super.getConfirmDialog("New Image Options", createOptions).choose();
if (choice != JOptionPane.OK_OPTION)
return;
@@ -964,7 +968,7 @@ private void openImageEDT(File file)
assert (SwingUtilities.isEventDispatchThread());
ImportOptionsPanel importOptions = new ImportOptionsPanel();
- int choice = ImageEditor.super.showConfirmDialog(importOptions, "Import Options");
+ int choice = ImageEditor.super.getConfirmDialog("Import Options", importOptions).choose();
if (choice != JOptionPane.OK_OPTION)
return;
@@ -976,8 +980,8 @@ private void openImageEDT(File file)
}
catch (ImageFormatException e) {
if (importOptions.getFormat().type == TileFormat.TYPE_CI) {
- choice = ImageEditor.super.showConfirmDialog(
- "Image file is not color-indexed. \nWould you like to convert it?", "Incorrect Image Format");
+ choice = ImageEditor.super.getConfirmDialog(
+ "Incorrect Image Format", "Image file is not color-indexed. \nWould you like to convert it?").choose();
if (choice != JOptionPane.OK_OPTION)
return;
@@ -1012,7 +1016,7 @@ private Palette getPaletteEDT(File file)
assert (SwingUtilities.isEventDispatchThread());
ImportOptionsPanel importOptions = new ImportOptionsPanel();
- int choice = ImageEditor.super.showConfirmDialog(importOptions, "Import Options");
+ int choice = ImageEditor.super.getConfirmDialog("Import Options", importOptions).choose();
if (choice != JOptionPane.OK_OPTION)
return null;
@@ -1058,7 +1062,7 @@ private void choosePaletteEDT()
importFileChooser.setDirectoryContaining(image.source.getParentFile());
if (importFileChooser.prompt() == ChooseDialogResult.APPROVE) {
ImportOptionsPanel importOptions = new ImportOptionsPanel();
- int choice = ImageEditor.super.showConfirmDialog(importOptions, "Import Options");
+ int choice = ImageEditor.super.getConfirmDialog("Import Options", importOptions).choose();
if (choice != JOptionPane.OK_OPTION)
return;
@@ -1084,7 +1088,7 @@ private void resizeImageEDT()
return;
ResizeOptionsPanel resizeOptionsPanel = new ResizeOptionsPanel();
- int choice = ImageEditor.super.showConfirmDialog(resizeOptionsPanel, "Resize Image Options");
+ int choice = ImageEditor.super.getConfirmDialog("Resize Image Options", resizeOptionsPanel).choose();
if (choice != JOptionPane.OK_OPTION)
return;
@@ -1103,7 +1107,7 @@ private void convertImageEDT()
return;
ConvertOptionsPanel convertOptionsPanel = new ConvertOptionsPanel();
- int choice = ImageEditor.super.showConfirmDialog(convertOptionsPanel, "Convert Image Options");
+ int choice = ImageEditor.super.getConfirmDialog("Convert Image Options", convertOptionsPanel).choose();
if (choice != JOptionPane.OK_OPTION)
return;
@@ -1191,7 +1195,7 @@ public void moveMouse(int dx, int dy)
else
image.draw(mousePixelX, mousePixelY, pickedPixel);
}
-
+
if(mouseManager.holdingRMB && mousePixelValid)
image.deselect(mousePixelX, mousePixelY);
*/
diff --git a/src/main/java/game/texture/editor/dialogs/ShorcutListPanel.java b/src/main/java/game/texture/editor/dialogs/ImageShortcutsPanel.java
similarity index 96%
rename from src/main/java/game/texture/editor/dialogs/ShorcutListPanel.java
rename to src/main/java/game/texture/editor/dialogs/ImageShortcutsPanel.java
index 062fc9b..95ff8b0 100644
--- a/src/main/java/game/texture/editor/dialogs/ShorcutListPanel.java
+++ b/src/main/java/game/texture/editor/dialogs/ImageShortcutsPanel.java
@@ -7,9 +7,9 @@
import net.miginfocom.swing.MigLayout;
-public class ShorcutListPanel extends JPanel
+public class ImageShortcutsPanel extends JPanel
{
- public ShorcutListPanel()
+ public ImageShortcutsPanel()
{
setLayout(new MigLayout("fill", "[50%][50%]"));
diff --git a/src/main/java/game/worldmap/WorldMapEditor.java b/src/main/java/game/worldmap/WorldMapEditor.java
index 5b59c5c..fe23aa7 100644
--- a/src/main/java/game/worldmap/WorldMapEditor.java
+++ b/src/main/java/game/worldmap/WorldMapEditor.java
@@ -667,8 +667,14 @@ private void drawGrid(float lineWidth)
private void showControls()
{
incrementDialogsOpen();
- SwingUtils.showFramedMessageDialog(getFrame(), new ShorcutListPanel(),
- "Controls and Shortcuts", JOptionPane.PLAIN_MESSAGE);
+
+ SwingUtils.getMessageDialog()
+ .setParent(getFrame())
+ .setTitle("Controls and Shortcuts")
+ .setMessage(new WorldShortcutsPanel())
+ .setMessageType(JOptionPane.PLAIN_MESSAGE)
+ .show();
+
decrementDialogsOpen();
}
diff --git a/src/main/java/game/worldmap/ShorcutListPanel.java b/src/main/java/game/worldmap/WorldShortcutsPanel.java
similarity index 95%
rename from src/main/java/game/worldmap/ShorcutListPanel.java
rename to src/main/java/game/worldmap/WorldShortcutsPanel.java
index 7ab4ab6..bcebed0 100644
--- a/src/main/java/game/worldmap/ShorcutListPanel.java
+++ b/src/main/java/game/worldmap/WorldShortcutsPanel.java
@@ -7,9 +7,9 @@
import net.miginfocom.swing.MigLayout;
-public class ShorcutListPanel extends JPanel
+public class WorldShortcutsPanel extends JPanel
{
- public ShorcutListPanel()
+ public WorldShortcutsPanel()
{
setLayout(new MigLayout("fill", "[45%]32[45%]"));
diff --git a/src/main/java/util/ui/FilteredListPanel.java b/src/main/java/util/ui/FilteredListPanel.java
index a010014..4c7baac 100644
--- a/src/main/java/util/ui/FilteredListPanel.java
+++ b/src/main/java/util/ui/FilteredListPanel.java
@@ -52,14 +52,14 @@ public void mouseClicked(MouseEvent evt)
if (evt.getButton() != MouseEvent.BUTTON1) {
return;
}
-
+
if (evt.getClickCount() == 1) {
Rectangle rect = list.getCellBounds(0, list.getLastVisibleIndex());
if (rect != null && !rect.contains(evt.getPoint())) {
list.clearSelection();
}
}
-
+
if (evt.getClickCount() == 2) {
Rectangle rect = list.getCellBounds(0, list.getLastVisibleIndex());
if (rect != null && rect.contains(evt.getPoint())) {
@@ -156,4 +156,9 @@ private void updateListFilter()
public T getSelected()
{ return list.getSelectedValue(); }
+
+ public void setSelected(T value)
+ {
+ list.setSelectedValue(value, true);
+ }
}