diff --git a/ATCS_JAR.jardesc b/ATCS_JAR.jardesc index a14050b..167a5a5 100644 --- a/ATCS_JAR.jardesc +++ b/ATCS_JAR.jardesc @@ -1,6 +1,6 @@ - + diff --git a/packaging/Windows/ATCS_Installer.nsi b/packaging/Windows/ATCS_Installer.nsi index a0929a9..52246c5 100644 --- a/packaging/Windows/ATCS_Installer.nsi +++ b/packaging/Windows/ATCS_Installer.nsi @@ -1,6 +1,6 @@ !include MUI2.nsh -!define VERSION "0.6.0" +!define VERSION "0.6.1" !define TRAINER_VERSION "0.1.3" !define JAVA_BIN "javaw" diff --git a/src/com/gpl/rpg/atcontentstudio/ATContentStudio.java b/src/com/gpl/rpg/atcontentstudio/ATContentStudio.java index 45c4f4b..c6da36a 100644 --- a/src/com/gpl/rpg/atcontentstudio/ATContentStudio.java +++ b/src/com/gpl/rpg/atcontentstudio/ATContentStudio.java @@ -24,7 +24,7 @@ import com.gpl.rpg.atcontentstudio.ui.WorkspaceSelector; public class ATContentStudio { public static final String APP_NAME = "Andor's Trail Content Studio"; - public static final String APP_VERSION = "v0.6.0"; + public static final String APP_VERSION = "v0.6.1"; public static boolean STARTED = false; public static StudioFrame frame = null; diff --git a/src/com/gpl/rpg/atcontentstudio/model/Project.java b/src/com/gpl/rpg/atcontentstudio/model/Project.java index 4badae0..dd512b9 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/Project.java +++ b/src/com/gpl/rpg/atcontentstudio/model/Project.java @@ -39,6 +39,7 @@ import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory; import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement; import com.gpl.rpg.atcontentstudio.model.gamedata.NPC; import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; +import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage; import com.gpl.rpg.atcontentstudio.model.maps.TMXMap; import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet; import com.gpl.rpg.atcontentstudio.model.maps.Worldmap; @@ -758,6 +759,15 @@ public class Project implements ProjectTreeNode, Serializable { } else { if (type == GameSource.Type.source) { JSONElement clone = (JSONElement) node.clone(); + if (node instanceof Quest) { + for (QuestStage oldStage : ((Quest) node).stages) { + QuestStage newStage = ((Quest) clone).getStage(oldStage.progress); + for (GameDataElement backlink : oldStage.getBacklinks()) { + backlink.elementChanged(oldStage, newStage); + } + oldStage.getBacklinks().clear(); + } + } for (GameDataElement backlink : node.getBacklinks()) { backlink.elementChanged(node, clone); } diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java index 59ffaa2..7cb382f 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java @@ -265,6 +265,12 @@ public class Dialogue extends JSONElement { break; case questProgress: reward.reward_obj = proj.getQuest(reward.reward_obj_id); + if (reward.reward_obj != null && reward.reward_value != null) { + QuestStage stage = ((Quest)reward.reward_obj).getStage(reward.reward_value); + if (stage != null) { + stage.addBacklink(this); + } + } break; case skillIncrease: //Nothing to do (yet ?). @@ -361,11 +367,7 @@ public class Dialogue extends JSONElement { } if (r.requirements != null) { for (Requirement req : r.requirements) { - if (req.required_obj == oldOne) { - oldOne.removeBacklink(this); - req.required_obj = newOne; - if (newOne != null) newOne.addBacklink(this); - } + req.elementChanged(oldOne, newOne); } } } @@ -377,6 +379,12 @@ public class Dialogue extends JSONElement { r.reward_obj = newOne; if (newOne != null) newOne.addBacklink(this); } + if (oldOne instanceof QuestStage) { + if (r.reward_obj != null && r.reward_obj.equals(oldOne.parent) && r.reward_value != null && r.reward_value.equals(((QuestStage) oldOne).progress)) { + oldOne.removeBacklink((GameDataElement) this); + if (newOne != null) newOne.addBacklink((GameDataElement) this); + } + } } } } diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Quest.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Quest.java index 3b71ccf..c1e683a 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Quest.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Quest.java @@ -30,22 +30,6 @@ public class Quest extends JSONElement { public Integer visible_in_log = null; public List stages = null; - public static class QuestStage implements Cloneable { - public Integer progress = null; - public String log_text = null; - public Integer exp_reward = null; - public Integer finishes_quest = null; - - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - } - return null; - } - } - @Override public String getDesc() { return (needsSaving() ? "*" : "")+name+" ("+id+")"; @@ -105,6 +89,8 @@ public class Quest extends JSONElement { Quest quest = new Quest(); quest.id = (String) questJson.get("id"); quest.name = (String) questJson.get("name"); + //Quests have to be parsed to have their stages initialized. + quest.parse(questJson); return quest; } @@ -117,15 +103,12 @@ public class Quest extends JSONElement { this.stages = new ArrayList(); for (Object questStageJsonObj : questStagesJson) { Map questStageJson = (Map)questStageJsonObj; - QuestStage questStage = new QuestStage(); - questStage.progress = JSONElement.getInteger((Number) questStageJson.get("progress")); - questStage.log_text = (String) questStageJson.get("logText"); - questStage.exp_reward = JSONElement.getInteger((Number) questStageJson.get("rewardExperience")); - questStage.finishes_quest = JSONElement.getInteger((Number) questStageJson.get("finishesQuest")); + QuestStage questStage = new QuestStage(this); + questStage.parse(questStageJson); this.stages.add(questStage); } } - + this.state = State.parsed; } @Override @@ -142,6 +125,9 @@ public class Quest extends JSONElement { return; } + for (QuestStage stage : stages) { + stage.link(); + } //Nothing to link to :D this.state = State.linked; } @@ -164,9 +150,9 @@ public class Quest extends JSONElement { clone.name = this.name; clone.visible_in_log = this.visible_in_log; if (this.stages != null) { - clone.stages = new ArrayList(); + clone.stages = new ArrayList(); for (QuestStage stage : this.stages){ - clone.stages.add((QuestStage) stage.clone()); + clone.stages.add((QuestStage) stage.clone(clone)); } } return clone; @@ -188,12 +174,7 @@ public class Quest extends JSONElement { List stagesJson = new ArrayList(); questJson.put("stages", stagesJson); for (QuestStage stage : this.stages) { - Map stageJson = new LinkedHashMap(); - stagesJson.add(stageJson); - if (stage.progress != null) stageJson.put("progress", stage.progress); - if (stage.log_text != null) stageJson.put("logText", stage.log_text); - if (stage.exp_reward != null) stageJson.put("rewardExperience", stage.exp_reward); - if (stage.finishes_quest != null) stageJson.put("finishesQuest", stage.finishes_quest); + stagesJson.add(stage.toJson()); } } return questJson; @@ -204,5 +185,14 @@ public class Quest extends JSONElement { public String getProjectFilename() { return "questlist_"+getProject().name+".json"; } + + public QuestStage getStage(Integer stageId) { + for (QuestStage stage : stages) { + if (stage.progress.equals(stageId)) { + return stage; + } + } + return null; + } } diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/QuestStage.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/QuestStage.java new file mode 100644 index 0000000..61baa85 --- /dev/null +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/QuestStage.java @@ -0,0 +1,103 @@ +package com.gpl.rpg.atcontentstudio.model.gamedata; + +import java.awt.Image; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.gpl.rpg.atcontentstudio.model.GameDataElement; +import com.gpl.rpg.atcontentstudio.ui.DefaultIcons; + +public class QuestStage extends JSONElement { + + private static final long serialVersionUID = 8313645819951513431L; + + public Integer progress = null; + public String log_text = null; + public Integer exp_reward = null; + public Integer finishes_quest = null; + + public QuestStage(Quest parent){ + this.parent = parent; + } + + public QuestStage clone(Quest cloneParent) { + QuestStage clone = new QuestStage(cloneParent); + clone.progress = progress != null ? new Integer(progress) : null; + clone.log_text = log_text != null ? new String(log_text) : null; + clone.exp_reward = exp_reward != null ? new Integer(exp_reward) : null; + clone.finishes_quest = finishes_quest != null ? new Integer(finishes_quest) : null; + clone.id = this.id; + return clone; + } + + @SuppressWarnings("rawtypes") + @Override + public void parse(Map jsonObj) { + progress = JSONElement.getInteger((Number) jsonObj.get("progress")); + this.id = ((Quest)parent).id+":"+progress; + log_text = (String) jsonObj.get("logText"); + exp_reward = JSONElement.getInteger((Number) jsonObj.get("rewardExperience")); + finishes_quest = JSONElement.getInteger((Number) jsonObj.get("finishesQuest")); + state = State.parsed; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public Map toJson() { + Map stageJson = new LinkedHashMap(); + if (progress != null) stageJson.put("progress", progress); + if (log_text != null) stageJson.put("logText", log_text); + if (exp_reward != null) stageJson.put("rewardExperience", exp_reward); + if (finishes_quest != null) stageJson.put("finishesQuest", finishes_quest); + return stageJson; + } + + @Override + public String getDesc() { + return progress+" - "+(exp_reward != null ? "["+exp_reward+"XP]" : "")+((finishes_quest != null) && (finishes_quest == 1) ? "[END]" : "")+log_text; + } + + @Override + public void link() { + if (this.state == State.created || this.state == State.modified || this.state == State.saved) { + //This type of state is unrelated to parsing/linking. + return; + } + if (this.state == State.init) { + //Not parsed yet. + this.parse(); + } else if (this.state == State.linked) { + //Already linked. + return; + } + + //Nothing to link to :D + this.state = State.linked; + } + + @Override + public void elementChanged(GameDataElement oldOne, GameDataElement newOne) { + // Nothing to link to. + } + + @Override + public String getProjectFilename() { + return ((Quest)parent).getProjectFilename(); + } + + @Override + public GameDataElement clone() { + return null; + } + + @Override + public Image getIcon() { + return DefaultIcons.getQuestIcon(); + } + + public Image getImage() { + return DefaultIcons.getQuestImage(); + } + + +} \ No newline at end of file diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Requirement.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Requirement.java index a67392c..8294c64 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Requirement.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Requirement.java @@ -112,6 +112,12 @@ public class Requirement extends JSONElement { case questLatestProgress: case questProgress: this.required_obj = proj.getQuest(required_obj_id); + if (this.required_obj != null && this.required_value != null) { + QuestStage stage = ((Quest)this.required_obj).getStage(this.required_value); + if (stage != null) { + stage.addBacklink((GameDataElement) this.parent); + } + } break; case consumedBonemeals: case skillLevel: @@ -150,6 +156,12 @@ public class Requirement extends JSONElement { this.required_obj = newOne; if (newOne != null) newOne.addBacklink((GameDataElement) this.parent); } + if (oldOne instanceof QuestStage) { + if (this.required_obj != null && this.required_obj.equals(oldOne.parent) && this.required_value != null && this.required_value.equals(((QuestStage) oldOne).progress)) { + oldOne.removeBacklink((GameDataElement) this.parent); + if (newOne != null) newOne.addBacklink((GameDataElement) this.parent); + } + } } @Override public String getProjectFilename() { diff --git a/src/com/gpl/rpg/atcontentstudio/ui/Editor.java b/src/com/gpl/rpg/atcontentstudio/ui/Editor.java index 6ae9ae0..8d885d5 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/Editor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/Editor.java @@ -39,6 +39,7 @@ import javax.swing.JSpinner.NumberEditor; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.ListModel; +import javax.swing.Scrollable; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -63,6 +64,7 @@ import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory; import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement; import com.gpl.rpg.atcontentstudio.model.gamedata.NPC; import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; +import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage; import com.gpl.rpg.atcontentstudio.model.maps.TMXMap; import com.gpl.rpg.atcontentstudio.utils.WeblateIntegration; import com.jidesoft.swing.ComboBoxSearchable; @@ -118,7 +120,7 @@ public abstract class Editor extends JPanel implements ProjectElementListener { public static void addTranslationPane(JPanel pane, final JTextComponent tfComponent, final String initialValue) {if (Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue() != null) { JPanel labelPane = new JPanel(); - labelPane.setLayout(new JideBoxLayout(labelPane, JideBoxLayout.LINE_AXIS)); + labelPane.setLayout(new JideBoxLayout(labelPane, JideBoxLayout.LINE_AXIS, 6)); final JLabel translateLinkLabel = new JLabel(getWeblateLabelLink(initialValue)); labelPane.add(translateLinkLabel, JideBoxLayout.FIX); labelPane.add(new JLabel(" "), JideBoxLayout.FIX); @@ -270,6 +272,9 @@ public abstract class Editor extends JPanel implements ProjectElementListener { tfPane.add(tfLabel, JideBoxLayout.FIX); final JTextArea tfArea = new JTextArea(text); tfArea.setEditable(editable); + tfArea.setRows(2); + tfArea.setLineWrap(true); + tfArea.setWrapStyleWord(true); tfPane.add(new JScrollPane(tfArea), JideBoxLayout.VARY); JButton nullify = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon())); tfPane.add(nullify, JideBoxLayout.FIX); @@ -644,8 +649,63 @@ public abstract class Editor extends JPanel implements ProjectElementListener { return gdeBox; } + public JComboBox addQuestStageBox(JPanel pane, Project proj, String label, Integer initialValue, boolean writable, final FieldUpdateListener listener, Quest quest, final JComboBox questSelectionBox) { + JPanel gdePane = new JPanel(); + gdePane.setLayout(new JideBoxLayout(gdePane, JideBoxLayout.LINE_AXIS, 6)); + JLabel gdeLabel = new JLabel(label); + gdePane.add(gdeLabel, JideBoxLayout.FIX); + + QuestStage initial = null; + if (quest != null) { + initial = quest.getStage(initialValue); + } + final QuestStageComboModel comboModel = new QuestStageComboModel(proj, initial, quest); + final JComboBox combo = new JComboBox(comboModel); + combo.setRenderer(new GDERenderer(false, writable)); + new ComboBoxSearchable(combo){ + @Override + protected String convertElementToString(Object object) { + if (object == null) return "none"; + else return ((GameDataElement)object).getDesc(); + } + }; + questSelectionBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (comboModel.selected != null) { + Editor.this.target.removeBacklink(comboModel.selected); + } + Quest newQuest = (Quest) questSelectionBox.getSelectedItem(); + comboModel.changeQuest(newQuest); + combo.revalidate(); + } + }); + combo.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + listener.valueChanged(combo, comboModel.selected == null ? null : comboModel.selected.progress); + } + }); + + + + combo.setEnabled(writable); + gdePane.add(combo, JideBoxLayout.VARY); + + pane.add(gdePane, JideBoxLayout.FIX); + + return combo; + } + + + @SuppressWarnings({ "rawtypes", "unchecked" }) public JList addBacklinksList(JPanel pane, GameDataElement gde) { + return addBacklinksList(pane, gde, "Elements linking to this one"); + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + public JList addBacklinksList(JPanel pane, GameDataElement gde, String title) { final JList list = new JList(new GDEBacklinksListModel(gde)); list.addMouseListener(new MouseAdapter() { @Override @@ -666,7 +726,7 @@ public abstract class Editor extends JPanel implements ProjectElementListener { } }); list.setCellRenderer(new GDERenderer(true, false)); - CollapsiblePanel colPane = new CollapsiblePanel("Elements linking to this one"); + CollapsiblePanel colPane = new CollapsiblePanel(title); colPane.setLayout(new JideBoxLayout(colPane, JideBoxLayout.PAGE_AXIS)); colPane.add(new JScrollPane(list), JideBoxLayout.FIX); colPane.add(new JPanel(), JideBoxLayout.FIX); @@ -744,9 +804,25 @@ public abstract class Editor extends JPanel implements ProjectElementListener { label.setText("None"+(writable ? ". Click on the button to create one." : "")); } else { if (includeType && ((GameDataElement)value).getDataType() != null) { - label.setText(((GameDataElement)value).getDataType().toString()+"/"+((GameDataElement)value).getDesc()); + if (value instanceof QuestStage) { + String text = ((GameDataElement)value).getDesc(); + if (text.length() > 60) { + text = text.substring(0, 57)+"..."; + } + label.setText(((GameDataElement)value).getDataType().toString()+"/"+((Quest)((QuestStage)value).parent).id+":"+text); + } else { + label.setText(((GameDataElement)value).getDataType().toString()+"/"+((GameDataElement)value).getDesc()); + } } else { - label.setText(((GameDataElement)value).getDesc()); + if (value instanceof QuestStage) { + String text = ((GameDataElement)value).getDesc(); + if (text.length() > 60) { + text = text.substring(0, 57)+"..."; + } + label.setText(text); + } else { + label.setText(((GameDataElement)value).getDesc()); + } } if (((GameDataElement)value).getIcon() == null) { Notification.addError("Unable to find icon for "+((GameDataElement)value).getDesc()); @@ -759,6 +835,65 @@ public abstract class Editor extends JPanel implements ProjectElementListener { } + public static class QuestStageComboModel extends AbstractListModel implements ComboBoxModel { + + private static final long serialVersionUID = -5854574666510314715L; + + public Project project; + public Quest currentQuest; + public QuestStage selected; + + public QuestStageComboModel(Project proj, QuestStage initial, Quest quest) { + this.project = proj; + this.currentQuest = quest; + this.selected = initial; + } + + @Override + public int getSize() { + if (currentQuest == null) return 1; + return currentQuest.stages.size()+1; + } + + @Override + public QuestStage getElementAt(int index) { + if (index == 0) { + return null; + } + return currentQuest.stages.get(index - 1); + } + + @SuppressWarnings("unchecked") + @Override + public void setSelectedItem(Object anItem) { + selected = (QuestStage) anItem; + } + + @Override + public Object getSelectedItem() { + return selected; + } + + public void itemAdded(QuestStage item, int index) { + fireIntervalAdded(this, index, index); + } + + public void itemRemoved(QuestStage item, int index) { + fireIntervalRemoved(this, index, index); + } + + public void changeQuest(Quest newQuest) { + int size = getSize(); + currentQuest = null; + selected = null; + fireIntervalRemoved(this, 1, size); + currentQuest = newQuest; + fireIntervalAdded(this, 1, getSize()); + } + + } + + public static class GDEBacklinksListModel implements ListModel { GameDataElement source; @@ -892,7 +1027,5 @@ public abstract class Editor extends JPanel implements ProjectElementListener { return null; } - - } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java index 7a518f7..c86e3cd 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java @@ -43,6 +43,7 @@ import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist; import com.gpl.rpg.atcontentstudio.model.gamedata.Item; import com.gpl.rpg.atcontentstudio.model.gamedata.NPC; import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; +import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage; import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement; import com.gpl.rpg.atcontentstudio.model.maps.TMXMap; import com.gpl.rpg.atcontentstudio.ui.BooleanBasedCheckBox; @@ -94,7 +95,7 @@ public class DialogueEditor extends JSONElementEditor { private JTextField rewardObjId; private JComboBox rewardObjIdCombo; private MyComboBox rewardObj; - private JSpinner rewardValue; + private JComponent rewardValue; private RepliesListModel repliesListModel; @SuppressWarnings("rawtypes") @@ -114,7 +115,7 @@ public class DialogueEditor extends JSONElementEditor { private JPanel requirementParamsPane; private MyComboBox requirementObj; private JTextField requirementObjId; - private JSpinner requirementValue; + private JComponent requirementValue; private BooleanBasedCheckBox requirementNegated; private DialogueGraphView dialogueGraphView; @@ -421,7 +422,7 @@ public class DialogueEditor extends JSONElementEditor { rewardObjId = null; rewardObjIdCombo = null; rewardObj = addQuestBox(pane, ((Dialogue)target).getProject(), "Quest: ", (Quest) reward.reward_obj, writable, listener); - rewardValue = addIntegerField(pane, "Step ID: ", reward.reward_value, false, writable, listener); + rewardValue = addQuestStageBox(pane, ((Dialogue)target).getProject(), "Quest stage: ", reward.reward_value, writable, listener, (Quest) reward.reward_obj, rewardObj); break; case skillIncrease: rewardMap = null; @@ -613,10 +614,10 @@ public class DialogueEditor extends JSONElementEditor { replyText = null; replyNextPhrase = addDialogueBox(pane, ((Dialogue)target).getProject(), "Next phrase: ", reply.next_phrase, writable, listener); } else if (Dialogue.Reply.KEY_PHRASE_ID.contains(reply.next_phrase_id)) { - replyText = addTextField(pane, "Reply text: ", reply.text, writable, listener); + replyText = addTranslatableTextField(pane, "Reply text: ", reply.text, writable, listener); replyNextPhrase = null; } else { - replyText = addTextField(pane, "Reply text: ", reply.text, writable, listener); + replyText = addTranslatableTextField(pane, "Reply text: ", reply.text, writable, listener); replyNextPhrase = addDialogueBox(pane, ((Dialogue)target).getProject(), "Next phrase: ", reply.next_phrase, writable, listener); } @@ -679,7 +680,7 @@ public class DialogueEditor extends JSONElementEditor { case questProgress: requirementObj = addQuestBox(pane, project, "Quest: ", (Quest) requirement.required_obj, writable, listener); requirementObjId = null; - requirementValue = addIntegerField(pane, "Quest stage: ", requirement.required_value, false, writable, listener); + requirementValue = addQuestStageBox(pane, project, "Quest stage: ", requirement.required_value, writable, listener, (Quest) requirement.required_obj, requirementObj); break; case skillLevel: requirementObj = null; @@ -1149,7 +1150,21 @@ public class DialogueEditor extends JSONElementEditor { } rewardsListModel.itemChanged(selectedReward); } else if (source == rewardValue) { + //Backlink removal to quest stages when selecting another quest are handled in the addQuestStageBox() method. Too complex too handle here + Quest quest = null; + QuestStage stage = null; + if (rewardValue instanceof JComboBox) { + quest = ((Quest)selectedReward.reward_obj); + if (quest != null && selectedReward.reward_value != null) { + stage = quest.getStage(selectedReward.reward_value); + if (stage != null) stage.removeBacklink(dialogue); + } + } selectedReward.reward_value = (Integer) value; + if (quest != null) { + stage = quest.getStage(selectedReward.reward_value); + if (stage != null) stage.addBacklink(dialogue); + } rewardsListModel.itemChanged(selectedReward); } else if (source == replyTypeCombo) { updateRepliesParamsEditorPane(repliesParamsPane, selectedReply, this); @@ -1190,7 +1205,21 @@ public class DialogueEditor extends JSONElementEditor { selectedRequirement.required_obj = null; requirementsListModel.itemChanged(selectedRequirement); } else if (source == requirementValue) { + //Backlink removal to quest stages when selecting another quest are handled in the addQuestStageBox() method. Too complex too handle here + Quest quest = null; + QuestStage stage = null; + if (requirementValue instanceof JComboBox) { + quest = ((Quest)selectedRequirement.required_obj); + if (quest != null && selectedRequirement.required_value != null) { + stage = quest.getStage(selectedRequirement.required_value); + if (stage != null) stage.removeBacklink(dialogue); + } + } selectedRequirement.required_value = (Integer) value; + if (quest != null) { + stage = quest.getStage(selectedRequirement.required_value); + if (stage != null) stage.addBacklink(dialogue); + } requirementsListModel.itemChanged(selectedRequirement); } else if (source == requirementNegated) { selectedRequirement.negated = (Boolean) value; diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java index 96278bf..45b0e34 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/JSONElementEditor.java @@ -16,6 +16,7 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; +import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; @@ -29,6 +30,8 @@ import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode; import com.gpl.rpg.atcontentstudio.model.SaveEvent; import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataCategory; import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement; +import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; +import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage; import com.gpl.rpg.atcontentstudio.model.maps.TMXMap; import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment; import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet; @@ -37,8 +40,11 @@ import com.gpl.rpg.atcontentstudio.ui.Editor; import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener; import com.gpl.rpg.atcontentstudio.ui.IdChangeImpactWizard; import com.gpl.rpg.atcontentstudio.ui.SaveItemsWizard; +import com.gpl.rpg.atcontentstudio.ui.ScrollablePanel; +import com.gpl.rpg.atcontentstudio.ui.ScrollablePanel.ScrollableSizeHint; import com.gpl.rpg.atcontentstudio.ui.sprites.SpriteChooser; import com.jidesoft.swing.JideBoxLayout; +import com.jidesoft.swing.JideScrollPane; import com.jidesoft.swing.JideTabbedPane; public abstract class JSONElementEditor extends Editor { @@ -65,7 +71,11 @@ public abstract class JSONElementEditor extends Editor { } public void addEditorTab(String id, JPanel editor) { - JScrollPane scroller = new JScrollPane(editor); + ScrollablePanel view = new ScrollablePanel(new BorderLayout()); + view.setScrollableWidth(ScrollableSizeHint.FIT); + view.setScrollableHeight(ScrollableSizeHint.STRETCH); + view.add(editor, BorderLayout.CENTER); + JScrollPane scroller = new JScrollPane(view, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); scroller.getVerticalScrollBar().setUnitIncrement(16); editorTabsHolder.addTab(id, scroller); editorTabs.put(id, editor); @@ -178,8 +188,17 @@ public abstract class JSONElementEditor extends Editor { if (node.getParent() instanceof GameDataCategory) { ((GameDataCategory)node.getParent()).remove(node); node.save(); + GameDataElement newOne = proj.getGameDataElement(node.getClass(), node.id); + if (node instanceof Quest) { + for (QuestStage oldStage : ((Quest) node).stages) { + QuestStage newStage = newOne != null ? ((Quest) newOne).getStage(oldStage.progress) : null; + for (GameDataElement backlink : oldStage.getBacklinks()) { + backlink.elementChanged(oldStage, newStage); + } + } + } for (GameDataElement backlink : node.getBacklinks()) { - backlink.elementChanged(node, proj.getGameDataElement(node.getClass(), node.id)); + backlink.elementChanged(node, newOne); } } } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/QuestEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/QuestEditor.java index bfe20a0..4e416f5 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/QuestEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/QuestEditor.java @@ -1,6 +1,5 @@ package com.gpl.rpg.atcontentstudio.ui.gamedataeditors; -import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -8,27 +7,30 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -import javax.swing.BorderFactory; +import javax.swing.DefaultListCellRenderer; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; -import javax.swing.JTable; +import javax.swing.JSpinner; import javax.swing.JTextArea; import javax.swing.JTextField; -import javax.swing.UIManager; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; -import javax.swing.event.TableModelEvent; -import javax.swing.event.TableModelListener; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableModel; import com.gpl.rpg.atcontentstudio.ATContentStudio; import com.gpl.rpg.atcontentstudio.model.GameDataElement; import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode; import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; +import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage; +import com.gpl.rpg.atcontentstudio.ui.CollapsiblePanel; import com.gpl.rpg.atcontentstudio.ui.DefaultIcons; import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener; import com.gpl.rpg.atcontentstudio.ui.IntegerBasedCheckBox; @@ -43,15 +45,20 @@ public class QuestEditor extends JSONElementEditor { private static final String form_view_id = "Form"; private static final String json_view_id = "JSON"; + private QuestStage selectedStage = null; + private JTextField idField; private JTextField nameField; private IntegerBasedCheckBox visibleBox; - private QuestStageTableModel stagesModel; - private JTable stagesTable; - private JButton createStage; - private JButton deleteStage; - private JButton moveUp; - private JButton moveDown; + private StagesListModel stagesListModel; + private JList stagesList; + +// private JPanel stagesParamPane; + private JSpinner progressField; + private JTextArea logTextField; + private JSpinner xpRewardField; + private IntegerBasedCheckBox finishQuestBox; + public QuestEditor(Quest quest) { @@ -72,242 +79,214 @@ public class QuestEditor extends JSONElementEditor { nameField = addTranslatableTextField(pane, "Quest Name: ", quest.name, quest.writable, listener); visibleBox = addIntegerBasedCheckBox(pane, "Visible in quest log", quest.visible_in_log, quest.writable, listener); - JPanel stagesPane = new JPanel(); - stagesPane.setLayout(new JideBoxLayout(stagesPane, JideBoxLayout.PAGE_AXIS, 6)); - stagesModel = new QuestStageTableModel(quest, listener); - stagesTable = new JTable(stagesModel); - stagesTable.getColumnModel().getColumn(0).setMinWidth(100); - stagesTable.getColumnModel().getColumn(0).setMaxWidth(100); -// stagesTable.getColumnModel().getColumn(1).setPreferredWidth(40); -// stagesTable.getColumnModel().getColumn(1).setPreferredWidth(40); - stagesTable.getColumnModel().getColumn(2).setMinWidth(100); - stagesTable.getColumnModel().getColumn(2).setMaxWidth(100); - stagesTable.getColumnModel().getColumn(3).setMinWidth(130); - stagesTable.getColumnModel().getColumn(3).setMaxWidth(130); - stagesTable.setCellSelectionEnabled(true); - stagesTable.getColumnModel().getColumn(1).setCellRenderer(new MultilineCellRenderer()); - stagesPane.add(new JScrollPane(stagesTable), BorderLayout.CENTER); - if (quest.writable) { - JPanel buttonPane = new JPanel(); - buttonPane.setLayout(new JideBoxLayout(buttonPane, JideBoxLayout.LINE_AXIS, 6)); - createStage = new JButton(new ImageIcon(DefaultIcons.getCreateIcon())); - deleteStage = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon())); - moveUp = new JButton(new ImageIcon(DefaultIcons.getArrowUpIcon())); - moveDown = new JButton(new ImageIcon(DefaultIcons.getArrowDownIcon())); - buttonPane.add(createStage, JideBoxLayout.FIX); - buttonPane.add(deleteStage, JideBoxLayout.FIX); - buttonPane.add(moveUp, JideBoxLayout.FIX); - buttonPane.add(moveDown, JideBoxLayout.FIX); - buttonPane.add(new JPanel(), JideBoxLayout.VARY); - deleteStage.setEnabled(false); - moveUp.setEnabled(false); - moveDown.setEnabled(false); - - stagesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - - @Override - public void valueChanged(ListSelectionEvent e) { - updateTableButtons(); + CollapsiblePanel stagesPane = new CollapsiblePanel("Quest stages: "); + stagesPane.setLayout(new JideBoxLayout(stagesPane, JideBoxLayout.PAGE_AXIS)); + stagesListModel = new StagesListModel(quest); + stagesList = new JList(stagesListModel); + stagesList.setCellRenderer(new StagesCellRenderer()); + stagesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + stagesPane.add(new JScrollPane(stagesList), JideBoxLayout.FIX); + final JPanel stagesEditorPane = new JPanel(); + final JButton createStage = new JButton(new ImageIcon(DefaultIcons.getCreateIcon())); + final JButton deleteStage = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon())); + final JButton moveStageUp = new JButton(new ImageIcon(DefaultIcons.getArrowUpIcon())); + final JButton moveStageDown = new JButton(new ImageIcon(DefaultIcons.getArrowDownIcon())); + deleteStage.setEnabled(false); + moveStageUp.setEnabled(false); + moveStageDown.setEnabled(false); + stagesList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + selectedStage = (QuestStage) stagesList.getSelectedValue(); + if (selectedStage != null) { + deleteStage.setEnabled(true); + moveStageUp.setEnabled(stagesList.getSelectedIndex() > 0); + moveStageDown.setEnabled(stagesList.getSelectedIndex() < (stagesListModel.getSize() - 1)); + } else { + deleteStage.setEnabled(false); + moveStageUp.setEnabled(false); + moveStageDown.setEnabled(false); } - }); - + updateStageEditorPane(stagesEditorPane, selectedStage, listener); + } + }); + if (quest.writable) { + JPanel listButtonsPane = new JPanel(); + listButtonsPane.setLayout(new JideBoxLayout(listButtonsPane, JideBoxLayout.LINE_AXIS, 6)); createStage.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - stagesModel.createStage(); - listener.valueChanged(stagesTable, null); - stagesTable.revalidate(); - stagesTable.repaint(); + QuestStage stage = new QuestStage(quest); + stagesListModel.addItem(stage); + stagesList.setSelectedValue(stage, true); + listener.valueChanged(new JLabel(), null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff. } }); deleteStage.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - stagesModel.deleteRow(stagesTable.getSelectedRow()); - listener.valueChanged(stagesTable, null); - stagesTable.revalidate(); - stagesTable.repaint(); - updateTableButtons(); + if (selectedStage != null) { + stagesListModel.removeItem(selectedStage); + selectedStage = null; + stagesList.clearSelection(); + listener.valueChanged(new JLabel(), null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff. + } } }); - moveUp.addActionListener(new ActionListener() { + moveStageUp.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { - stagesModel.moveRow(stagesTable.getSelectedRow(), true); - listener.valueChanged(stagesTable, null); - stagesTable.setRowSelectionInterval(stagesTable.getSelectedRow() - 1, stagesTable.getSelectedRow() - 1); - updateTableButtons(); + if (selectedStage != null) { + stagesListModel.moveUp(selectedStage); + stagesList.setSelectedValue(selectedStage, true); + listener.valueChanged(new JLabel(), null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff. + } } }); - moveDown.addActionListener(new ActionListener() { + moveStageDown.addActionListener(new ActionListener() { + @Override public void actionPerformed(ActionEvent e) { - stagesModel.moveRow(stagesTable.getSelectedRow(), false); - listener.valueChanged(stagesTable, null); - stagesTable.setRowSelectionInterval(stagesTable.getSelectedRow() + 1, stagesTable.getSelectedRow() + 1); - updateTableButtons(); + if (selectedStage != null) { + stagesListModel.moveDown(selectedStage); + stagesList.setSelectedValue(selectedStage, true); + listener.valueChanged(new JLabel(), null); //Item changed, but we took care of it, just do the usual notification and JSON update stuff. + } } }); - stagesPane.add(buttonPane, JideBoxLayout.FIX); + listButtonsPane.add(createStage, JideBoxLayout.FIX); + listButtonsPane.add(deleteStage, JideBoxLayout.FIX); + listButtonsPane.add(moveStageUp, JideBoxLayout.FIX); + listButtonsPane.add(moveStageDown, JideBoxLayout.FIX); + listButtonsPane.add(new JPanel(), JideBoxLayout.VARY); + stagesPane.add(listButtonsPane, JideBoxLayout.FIX); } + if (quest.stages == null || quest.stages.isEmpty()) { + stagesPane.collapse(); + } + stagesEditorPane.setLayout(new JideBoxLayout(stagesEditorPane, JideBoxLayout.PAGE_AXIS)); + stagesPane.add(stagesEditorPane, JideBoxLayout.FIX); pane.add(stagesPane, JideBoxLayout.FIX); } - public void updateTableButtons() { + public void updateStageEditorPane(JPanel pane, QuestStage selectedStage, FieldUpdateListener listener) { + pane.removeAll(); + if (selectedStage != null) { + boolean writable = ((Quest)target).writable; + progressField = addIntegerField(pane, "Progress ID: ", selectedStage.progress, false, writable, listener); + logTextField = addTranslatableTextArea(pane, "Log text: ", selectedStage.log_text, writable, listener); + xpRewardField = addIntegerField(pane, "XP Reward: ", selectedStage.exp_reward, false, writable, listener); + finishQuestBox = addIntegerBasedCheckBox(pane, "Finishes quest", selectedStage.finishes_quest, writable, listener); + addBacklinksList(pane, selectedStage, "Elements linking to this quest stage"); - if (stagesTable.getSelectedRow() >= 0 && stagesTable.getSelectedRow() < stagesModel.getRowCount()) { - deleteStage.setEnabled(true); - if (stagesTable.getSelectedRow() == 0) { - moveUp.setEnabled(false); - } else { - moveUp.setEnabled(true); - } - if (stagesTable.getSelectedRow() >= stagesModel.getRowCount() - 1) { - moveDown.setEnabled(false); - } else { - moveDown.setEnabled(true); - } - } else { - deleteStage.setEnabled(false); - moveUp.setEnabled(false); - moveDown.setEnabled(false); } - + pane.revalidate(); + pane.repaint(); } - public class QuestStageTableModel implements TableModel { + public static class StagesListModel implements ListModel { - Quest quest; - FieldUpdateListener listener; - - public QuestStageTableModel(Quest q, FieldUpdateListener listener) { - this.quest = q; - this.listener = listener; + Quest source; + + public StagesListModel(Quest quest) { + this.source = quest; } + @Override - public int getRowCount() { - if (quest.stages == null) return 0; - return quest.stages.size(); + public int getSize() { + if (source.stages == null) return 0; + return source.stages.size(); } @Override - public int getColumnCount() { - return 4; + public QuestStage getElementAt(int index) { + if (source.stages == null) return null; + return source.stages.get(index); } - - @Override - public String getColumnName(int columnIndex) { - switch (columnIndex) { - case 0: - return "Progress ID"; - case 1: - return "Log text"; - case 2: - return "XP reward"; - case 3: - return "Finishes quest"; - default: - return "???"; + + public void addItem(QuestStage item) { + if (source.stages == null) { + source.stages = new ArrayList(); } - } - - @Override - public Class getColumnClass(int columnIndex) { - switch (columnIndex) { - case 0: - return Integer.class; - case 1: - return String.class; - case 2: - return Integer.class; - case 3: - return Boolean.class; - default: - return null; - } - } - - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - return quest.writable; - } - - @Override - public Object getValueAt(int rowIndex, int columnIndex) { - switch (columnIndex) { - case 0: - return quest.stages.get(rowIndex).progress; - case 1: - return quest.stages.get(rowIndex).log_text; - case 2: - return quest.stages.get(rowIndex).exp_reward; - case 3: - return quest.stages.get(rowIndex).finishes_quest != null && quest.stages.get(rowIndex).finishes_quest.equals(1); - default: - return null; - } - } - - @Override - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - switch (columnIndex) { - case 0: - quest.stages.get(rowIndex).progress = (Integer)aValue; - break; - case 1: - quest.stages.get(rowIndex).log_text = (String)aValue; - break; - case 2: - quest.stages.get(rowIndex).exp_reward = (Integer)aValue; - break; - case 3: - quest.stages.get(rowIndex).finishes_quest = ((Boolean)aValue) ? one : null; - break; - } - listener.valueChanged(stagesTable, aValue); - } - - public void createStage() { - if (quest.stages == null) quest.stages = new ArrayList(); - quest.stages.add(new Quest.QuestStage()); - for (TableModelListener l: listeners) { - l.tableChanged(new TableModelEvent(this, quest.stages.size() - 1)); + source.stages.add(item); + int index = source.stages.indexOf(item); + for (ListDataListener l : listeners) { + l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index, index)); } } - public void moveRow(int rowNumber, boolean moveUp) { - Quest.QuestStage stage = quest.stages.get(rowNumber); - quest.stages.remove(stage); - quest.stages.add(rowNumber + (moveUp ? -1 : 1), stage); - for (TableModelListener l : listeners) { - l.tableChanged(new TableModelEvent(this, rowNumber + (moveUp ? -1 : 0), rowNumber + (moveUp ? 0 : 1))); + public void removeItem(QuestStage item) { + int index = source.stages.indexOf(item); + source.stages.remove(item); + if (source.stages.isEmpty()) { + source.stages = null; + } + for (ListDataListener l : listeners) { + l.intervalRemoved(new ListDataEvent(this, ListDataEvent.INTERVAL_REMOVED, index, index)); + } + } + + public void itemChanged(QuestStage item) { + int index = source.stages.indexOf(item); + for (ListDataListener l : listeners) { + l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index)); } } - public void deleteRow(int rowNumber) { - quest.stages.remove(rowNumber); - for (TableModelListener l: listeners) { - l.tableChanged(new TableModelEvent(this, rowNumber, quest.stages.size())); + public void moveUp(QuestStage item) { + int index = source.stages.indexOf(item); + QuestStage exchanged = source.stages.get(index - 1); + source.stages.set(index, exchanged); + source.stages.set(index - 1, item); + for (ListDataListener l : listeners) { + l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index - 1, index)); } - if (quest.stages.isEmpty()) quest.stages = null; } - - public List listeners = new CopyOnWriteArrayList(); - + + public void moveDown(QuestStage item) { + int index = source.stages.indexOf(item); + QuestStage exchanged = source.stages.get(index + 1); + source.stages.set(index, exchanged); + source.stages.set(index + 1, item); + for (ListDataListener l : listeners) { + l.contentsChanged(new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, index, index + 1)); + } + } + + + List listeners = new CopyOnWriteArrayList(); + @Override - public void addTableModelListener(TableModelListener l) { + public void addListDataListener(ListDataListener l) { listeners.add(l); } @Override - public void removeTableModelListener(TableModelListener l) { + public void removeListDataListener(ListDataListener l) { listeners.remove(l); } - } + + public static class StagesCellRenderer extends DefaultListCellRenderer { + private static final long serialVersionUID = 7987880146189575234L; + + @Override + public Component getListCellRendererComponent(@SuppressWarnings("rawtypes") JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (c instanceof JLabel) { + JLabel label = ((JLabel)c); + label.setText(((QuestStage)value).getDesc()); + label.setIcon(new ImageIcon(((QuestStage)value).getIcon())); + } + return c; + } + } + + public class QuestFieldUpdater implements FieldUpdateListener { @Override @@ -337,6 +316,18 @@ public class QuestEditor extends JSONElementEditor { ATContentStudio.frame.editorChanged(QuestEditor.this); } else if (source == visibleBox) { quest.visible_in_log = (Integer) value; + } else if (source == progressField) { + selectedStage.progress = (Integer) value; + stagesListModel.itemChanged(selectedStage); + } else if (source == logTextField) { + selectedStage.log_text = (String) value; + stagesListModel.itemChanged(selectedStage); + } else if (source == xpRewardField) { + selectedStage.exp_reward = (Integer) value; + stagesListModel.itemChanged(selectedStage); + } else if (source == finishQuestBox) { + selectedStage.finishes_quest = (Integer) value; + stagesListModel.itemChanged(selectedStage); } @@ -351,47 +342,6 @@ public class QuestEditor extends JSONElementEditor { } - - public class MultilineCellRenderer extends JTextArea implements TableCellRenderer { - private static final long serialVersionUID = 6539816623608859506L; - - public MultilineCellRenderer() { - setLineWrap(true); - setWrapStyleWord(true); - //setOpaque(true); - } - - @Override - public Component getTableCellRendererComponent(JTable table, - Object value, boolean isSelected, boolean hasFocus, - int row, int column) { - if (isSelected) { - setForeground(stagesTable.getSelectionForeground()); - setBackground(stagesTable.getSelectionBackground()); - } else { - setForeground(stagesTable.getForeground()); - setBackground(stagesTable.getBackground()); - } - setFont(stagesTable.getFont()); - if (hasFocus) { - setBorder(UIManager.getBorder("Table.focusCellHighlightBorder")); - if (stagesTable.isCellEditable(row, column)) { - setForeground(UIManager.getColor("Table.focusCellForeground")); - setBackground(UIManager.getColor("Table.focusCellBackground")); - } - } else { - setBorder(BorderFactory.createLineBorder(getBackground(), 1)); - } - setText((value == null ? "" : value.toString())); - - int fh = getFontMetrics(getFont()).getHeight(); -// int tl = getText().length(); - setSize(stagesTable.getWidth(), fh); - stagesTable.setRowHeight(row, getPreferredSize().height); - - return this; - } - } } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/dialoguetree/DialogueGraphView.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/dialoguetree/DialogueGraphView.java index 03374df..52fbe53 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/dialoguetree/DialogueGraphView.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/dialoguetree/DialogueGraphView.java @@ -15,6 +15,7 @@ import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JToolTip; +import javax.swing.SwingConstants; import javax.swing.ToolTipManager; import prefuse.Display; @@ -68,6 +69,7 @@ public class DialogueGraphView extends Display { public static final String ICON = "icon"; public static final String TARGET = "target"; public static final String REPLY = "reply"; + public static final String HIDDEN_REPLY = "hidden_reply"; public static final String HAS_REQS = "has_reqs"; private static final Schema DECORATOR_SCHEMA = PrefuseLib.getVisualItemSchema(); @@ -174,6 +176,7 @@ public class DialogueGraphView extends Display { graph.addColumn(ICON, Image.class, DefaultIcons.getNullifyIcon()); graph.addColumn(TARGET, GameDataElement.class, null); graph.addColumn(REPLY, Dialogue.Reply.class, null); + graph.addColumn(HIDDEN_REPLY, Dialogue.Reply.class, null); graph.addColumn(HAS_REQS, boolean.class, false); addDialogue(dialogue, npcIcon); } @@ -224,6 +227,8 @@ public class DialogueGraphView extends Display { } else if (r.next_phrase != null) { //Go directly to next phrase rNode = addDialogue(r.next_phrase, npcIcon); + //Add a pointer to the hidden reply, in order to fetch requirements later. + rNode.set(HIDDEN_REPLY, r); } else if (Dialogue.Reply.KEY_PHRASE_ID.contains(r.next_phrase_id)) { //Go directly to key phrase rNode = addKeyPhraseNode(d, r.next_phrase_id); @@ -499,27 +504,32 @@ public class DialogueGraphView extends Display { label = new JLabel(new ImageIcon(DefaultIcons.getDialogueIcon())); label.setText(d.id); content.add(label, JideBoxLayout.FIX); - if (tooltippedItem.get(REPLY) == null) { - if (d.rewards != null && !d.rewards.isEmpty()) { - for (Dialogue.Reward r : d.rewards) { - label = new JLabel(); - DialogueEditor.decorateRewardJLabel(label, r); + Object replObj = tooltippedItem.get(REPLY); + if (replObj == null) { + replObj = tooltippedItem.get(HIDDEN_REPLY); + } + if (replObj != null && replObj instanceof Dialogue.Reply) { + Dialogue.Reply r = (Dialogue.Reply) replObj; + if (r.requirements != null && !r.requirements.isEmpty()) { + JLabel reqTitle = new JLabel("--Requirements--", SwingConstants.CENTER); + content.add(reqTitle, JideBoxLayout.FIX); + for (Requirement req : r.requirements) { + label = new JLabel("", SwingConstants.CENTER); + DialogueEditor.decorateRequirementJLabel(label, req); content.add(label, JideBoxLayout.FIX); } } - } else { - Object replObj = tooltippedItem.get(REPLY); - if (replObj instanceof Dialogue.Reply) { - Dialogue.Reply r = (Dialogue.Reply) replObj; - if (r.requirements != null && !r.requirements.isEmpty()) { - for (Requirement req : r.requirements) { - label = new JLabel(); - DialogueEditor.decorateRequirementJLabel(label, req); - content.add(label, JideBoxLayout.FIX); - } - } - } } + if (d.rewards != null && !d.rewards.isEmpty()) { + JLabel rewTitle = new JLabel("--Rewards--", SwingConstants.CENTER); + rewTitle.setAlignmentY(CENTER_ALIGNMENT); + content.add(rewTitle, JideBoxLayout.FIX); + for (Dialogue.Reward r : d.rewards) { + label = new JLabel("", SwingConstants.CENTER); + DialogueEditor.decorateRewardJLabel(label, r); + content.add(label, JideBoxLayout.FIX); + } + } } } diff --git a/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java index 03dd81b..fb6040b 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java @@ -81,6 +81,7 @@ import com.gpl.rpg.atcontentstudio.model.gamedata.Item; import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement; import com.gpl.rpg.atcontentstudio.model.gamedata.NPC; import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; +import com.gpl.rpg.atcontentstudio.model.gamedata.QuestStage; import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement; import com.gpl.rpg.atcontentstudio.model.maps.ContainerArea; import com.gpl.rpg.atcontentstudio.model.maps.KeyArea; @@ -172,7 +173,7 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @SuppressWarnings("rawtypes") private JComboBox requirementObj; private JTextField requirementObjId; - private JSpinner requirementValue; + private JComponent requirementValue; private BooleanBasedCheckBox requirementNegated; @SuppressWarnings("rawtypes") @@ -642,7 +643,7 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe case questProgress: requirementObj = addQuestBox(pane, project, "Quest: ", (Quest) requirement.required_obj, writable, listener); requirementObjId = null; - requirementValue = addIntegerField(pane, "Quest stage: ", requirement.required_value, false, writable, listener); + requirementValue = addQuestStageBox(pane, project, "Quest stage: ", requirement.required_value, writable, listener, (Quest) requirement.required_obj, requirementObj); break; case skillLevel: requirementObj = null; @@ -1949,11 +1950,37 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe } else if (source == requirementValue) { if (selectedMapObject instanceof KeyArea) { KeyArea area = (KeyArea) selectedMapObject; + Quest quest = null; + QuestStage stage = null; + if (requirementValue instanceof JComboBox) { + quest = ((Quest)area.requirement.required_obj); + if (quest != null && area.requirement.required_value != null) { + stage = quest.getStage(area.requirement.required_value); + if (stage != null) stage.removeBacklink(map); + } + } area.requirement.required_value = (Integer) value; + if (quest != null) { + stage = quest.getStage(area.requirement.required_value); + if (stage != null) stage.addBacklink(map); + } if (area.oldSchoolRequirement) area.updateNameFromRequirementChange(); } else if (selectedMapObject instanceof ReplaceArea) { ReplaceArea area = (ReplaceArea) selectedMapObject; + Quest quest = null; + QuestStage stage = null; + if (requirementValue instanceof JComboBox) { + quest = ((Quest)area.requirement.required_obj); + if (quest != null && area.requirement.required_value != null) { + stage = quest.getStage(area.requirement.required_value); + if (stage != null) stage.removeBacklink(map); + } + } area.requirement.required_value = (Integer) value; + if (quest != null) { + stage = quest.getStage(area.requirement.required_value); + if (stage != null) stage.addBacklink(map); + } if (area.oldSchoolRequirement) area.updateNameFromRequirementChange(); } } else if (source == requirementNegated) {