package script_editor;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import editor.FileControl;
import editor.LevelEditor;
import editor.Trigger;
public class ScriptEditor extends JFrame {
private static final long serialVersionUID = 1L;
public static final String TITLE = "Script Editor (Hobby)";
public static final int WIDTH = 700;
public static final int HEIGHT = 400;
public static File LAST_SAVED_DIRECTORY = FileControl.lastSavedDirectory;
public LevelEditor parent;
public ScriptInput input;
public ScriptToolbar scriptToolbar;
public ScriptViewer scriptViewer;
public ScriptChanger scriptChanger;
private boolean modifiedFlag = false;
@SuppressWarnings("unused")
private String scriptName;
public ScriptEditor(String title, LevelEditor parent) {
super(title);
this.parent = parent;
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // For good measure.
this.pack();
this.setVisible(true);
Dimension size = new Dimension(WIDTH, HEIGHT);
this.setSize(size);
this.setPreferredSize(size);
this.setMaximumSize(size);
this.setMinimumSize(size);
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent event) {
// TODO: 2014-6-26: Add the ability to save temp script data on the fly. Closing included.
ScriptEditor.this.dispose();
// 7 is a magic number for "Script Editor" button action command. I don't like to make a new variable just for this.
JButton button = ScriptEditor.this.parent.fileControlPanel.buttonCache.get(Integer.toString(7));
button.setEnabled(true);
ScriptEditor.this.parent.scriptEditor = null;
}
});
addingComponents();
// Generates a scripting tutorial upon loading script editor. This generated file will not be persistent and the script editor will not overwrite if the file exists.
generateScriptingTutorial();
LAST_SAVED_DIRECTORY = FileControl.lastSavedDirectory;
ToolTipManager.sharedInstance().setInitialDelay(1);
this.setTitle(this.getTitle() + " - Untitled.script");
this.setScriptName("Untitled");
}
/**
*
* <p>
* Generates a ReadMe text file upon opening the Script Editor.
* </p>
*
* @return Nothing.
* */
public void generateScriptingTutorial() {
File file = new File("readme.txt");
if (!file.exists()) {
// There are many different ways you can do to write data to files. This is one of them.
String[] tutorialLines = new String[] { "/ Automation", "/", "/ Entities that can walk, or run, must be required to have movements for the game", "/ to feel lively.", "/", "/ More commands to come.", " ", "/ _: Whitespaces.", "/ @: Trigger name.",
"/ ^: [Direction, Steps]. Can be chained for delaying scripted movements.", "/ $: Start of script. Always appear at beginning of script.", "/ %: Script delimiter. Always appear at end of script.", "/ #: Speech Dialogue.", "/ /: Comments. Gets ignored.",
"/ ?: Question Dialogue.", "/ +: Affirmative dialogue.", "/ -: Negative dialogue", "/ [: Affirmative Action", "/ ]: Negative Action", "/ ;: Repeat Flag. If contains ';', it means it's enabled by default.", " ",
"/ DO NOT CHANGE/REMOVE THIS TRIGGER SCRIPT. THIS IS RESERVED ONLY. FOLLOW THIS FORMAT.", "$0", "@Eraser", "%" };
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("readme.txt"), "utf-8"));
for (int i = 0; i < tutorialLines.length; i++) {
writer.write(tutorialLines[i]);
writer.newLine();
}
}
catch (IOException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
e.printStackTrace();
}
finally {
try {
writer.close();
}
catch (IOException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
e.printStackTrace();
}
}
}
}
public void addingComponents() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (input == null) {
input = new ScriptInput();
addMouseListener(input);
addMouseMotionListener(input);
}
if (scriptToolbar == null) {
scriptToolbar = new ScriptToolbar(ScriptEditor.this);
scriptToolbar.addMouseListener(input);
scriptToolbar.addMouseMotionListener(input);
add(scriptToolbar, BorderLayout.NORTH);
validate();
}
if (scriptViewer == null) {
scriptViewer = new ScriptViewer(ScriptEditor.this);
scriptViewer.addMouseListener(input);
scriptViewer.addMouseMotionListener(input);
add(scriptViewer, BorderLayout.WEST);
validate();
}
if (scriptChanger == null) {
scriptChanger = new ScriptChanger(ScriptEditor.this);
scriptChanger.addMouseListener(input);
scriptChanger.addMouseMotionListener(input);
add(scriptChanger, BorderLayout.CENTER);
validate();
}
}
});
}
// (11/24/2014): This is where I load triggers at. This is completed, but may require double-checking to be very sure.
/**
* <p>
* Loads the file script.
* </p>
*
* <p>
* This method may require double-checking in the codes, just to be very sure that it is absolutely working as intended. Reason for this is that this method is used as a guideline for loading custom scripts into the game itself.
* </p>
*
* @param script
* - Takes in a SCRIPT file object, which is the scripting file the game and the script editor uses.
* @return Nothing.
* */
public void load(File script) {
String format = script.getName();
if (!format.endsWith(".script")) {
JOptionPane.showMessageDialog(null, "Incorrect file format - Please open files ending with \".script\"");
return;
}
System.out.println("Opened Location: " + script.getAbsolutePath());
BufferedReader reader = null;
try {
JList<Trigger> triggerList = this.scriptViewer.getTriggerList();
DefaultListModel<Trigger> scriptTriggerListModel = (DefaultListModel<Trigger>) triggerList.getModel();
scriptTriggerListModel.clear();
JComboBox<Trigger> comboTriggerList = this.parent.properties.getTriggerList();
DefaultComboBoxModel<Trigger> editorTriggerComboModel = (DefaultComboBoxModel<Trigger>) comboTriggerList.getModel();
editorTriggerComboModel.removeAllElements();
Trigger trigger = new Trigger();
trigger.setTriggerID((short) 0);
trigger.setName("Eraser");
editorTriggerComboModel.addElement(trigger);
comboTriggerList.setSelectedIndex(0);
reader = new BufferedReader(new InputStreamReader(new FileInputStream(script)));
String line = null;
String[] tokens;
trigger = null;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null) {
if (line.startsWith("$")) {
tokens = line.split("\\$");
trigger = new Trigger();
trigger.setTriggerID(Short.valueOf(tokens[1]));
}
else if (line.startsWith("@")) {
tokens = line.split("@");
trigger.setName(tokens[1]);
}
else if (line.startsWith("%")) {
trigger.setScript(builder.toString());
scriptTriggerListModel.addElement(trigger);
editorTriggerComboModel.addElement(trigger);
builder.setLength(0);
}
else if (line.startsWith("#")) {
// Dialogue
}
else if (line.startsWith("?")) {
// Question Mark
}
else if (line.startsWith("+")) {
// Affirmative Answer
}
else if (line.startsWith("-")) {
// Negative Answer
}
else {
builder.append(line).append("\n");
}
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
reader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
this.scriptViewer.getTriggerList().clearSelection();
this.scriptViewer.revalidate();
this.parent.revalidate();
}
public boolean isBeingModified() {
return this.modifiedFlag;
}
public void setScriptName(String scriptName) {
this.scriptName = scriptName;
}
public void setModifiedFlag(boolean value) {
if (!value) {
String str = this.getTitle();
if (str.endsWith("*"))
this.setTitle(str.substring(0, str.length() - 1));
}
this.modifiedFlag = value;
}
public LevelEditor getLevelEditorParent() {
return this.parent;
}
public void save(File script) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(script)));
DefaultListModel<Trigger> model = (DefaultListModel<Trigger>) this.scriptViewer.getTriggerList().getModel();
writer.write("$0");
writer.newLine();
writer.write("@Eraser");
writer.newLine();
writer.write("%");
writer.newLine();
writer.newLine();
writer.newLine();
for (int i = 0; i < model.getSize(); i++) {
Trigger t = model.get(i);
try {
writer.write("$" + Short.toString(t.getTriggerID()));
writer.newLine();
writer.write("@" + t.getName().replace(" ", "_"));
writer.newLine();
writer.write(t.getScript());
writer.newLine();
writer.write("%");
writer.newLine();
writer.newLine();
writer.newLine();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
try {
writer.flush();
writer.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("Saved Location: " + script.getAbsolutePath());
}
}