Compare commits

...

1 Commits

Author SHA1 Message Date
Zukero
fb8dcb9fb4 v0.6.1! Rebuilt completely the Quest editor. Each quest stage has its
own backlinks now. Quest log entries and dialogue replies are now
translatable too. Multiple minor UI improvements (notably multiline text
area are now taller, and rewards and requirements appear more clearly in
the dialogue tree view).
2017-04-14 15:52:32 +02:00
14 changed files with 599 additions and 308 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jardesc> <jardesc>
<jar path="ATContentStudio/ATCS_v0.6.0.jar"/> <jar path="ATContentStudio/ATCS_v0.6.1.jar"/>
<options buildIfNeeded="true" compress="true" descriptionLocation="/ATContentStudio/ATCS_JAR.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/> <options buildIfNeeded="true" compress="true" descriptionLocation="/ATContentStudio/ATCS_JAR.jardesc" exportErrors="true" exportWarnings="true" includeDirectoryEntries="false" overwrite="false" saveDescription="true" storeRefactorings="false" useSourceFolders="false"/>
<storedRefactorings deprecationInfo="true" structuralOnly="false"/> <storedRefactorings deprecationInfo="true" structuralOnly="false"/>
<selectedProjects/> <selectedProjects/>

View File

@@ -1,6 +1,6 @@
!include MUI2.nsh !include MUI2.nsh
!define VERSION "0.6.0" !define VERSION "0.6.1"
!define TRAINER_VERSION "0.1.3" !define TRAINER_VERSION "0.1.3"
!define JAVA_BIN "javaw" !define JAVA_BIN "javaw"

View File

@@ -24,7 +24,7 @@ import com.gpl.rpg.atcontentstudio.ui.WorkspaceSelector;
public class ATContentStudio { public class ATContentStudio {
public static final String APP_NAME = "Andor's Trail Content Studio"; 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 boolean STARTED = false;
public static StudioFrame frame = null; public static StudioFrame frame = null;

View File

@@ -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.JSONElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC; import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; 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.TMXMap;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet; import com.gpl.rpg.atcontentstudio.model.maps.TMXMapSet;
import com.gpl.rpg.atcontentstudio.model.maps.Worldmap; import com.gpl.rpg.atcontentstudio.model.maps.Worldmap;
@@ -758,6 +759,15 @@ public class Project implements ProjectTreeNode, Serializable {
} else { } else {
if (type == GameSource.Type.source) { if (type == GameSource.Type.source) {
JSONElement clone = (JSONElement) node.clone(); 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()) { for (GameDataElement backlink : node.getBacklinks()) {
backlink.elementChanged(node, clone); backlink.elementChanged(node, clone);
} }

View File

@@ -265,6 +265,12 @@ public class Dialogue extends JSONElement {
break; break;
case questProgress: case questProgress:
reward.reward_obj = proj.getQuest(reward.reward_obj_id); 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; break;
case skillIncrease: case skillIncrease:
//Nothing to do (yet ?). //Nothing to do (yet ?).
@@ -361,11 +367,7 @@ public class Dialogue extends JSONElement {
} }
if (r.requirements != null) { if (r.requirements != null) {
for (Requirement req : r.requirements) { for (Requirement req : r.requirements) {
if (req.required_obj == oldOne) { req.elementChanged(oldOne, newOne);
oldOne.removeBacklink(this);
req.required_obj = newOne;
if (newOne != null) newOne.addBacklink(this);
}
} }
} }
} }
@@ -377,6 +379,12 @@ public class Dialogue extends JSONElement {
r.reward_obj = newOne; r.reward_obj = newOne;
if (newOne != null) newOne.addBacklink(this); 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);
}
}
} }
} }
} }

View File

@@ -30,22 +30,6 @@ public class Quest extends JSONElement {
public Integer visible_in_log = null; public Integer visible_in_log = null;
public List<QuestStage> stages = null; public List<QuestStage> 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 @Override
public String getDesc() { public String getDesc() {
return (needsSaving() ? "*" : "")+name+" ("+id+")"; return (needsSaving() ? "*" : "")+name+" ("+id+")";
@@ -105,6 +89,8 @@ public class Quest extends JSONElement {
Quest quest = new Quest(); Quest quest = new Quest();
quest.id = (String) questJson.get("id"); quest.id = (String) questJson.get("id");
quest.name = (String) questJson.get("name"); quest.name = (String) questJson.get("name");
//Quests have to be parsed to have their stages initialized.
quest.parse(questJson);
return quest; return quest;
} }
@@ -117,15 +103,12 @@ public class Quest extends JSONElement {
this.stages = new ArrayList<QuestStage>(); this.stages = new ArrayList<QuestStage>();
for (Object questStageJsonObj : questStagesJson) { for (Object questStageJsonObj : questStagesJson) {
Map questStageJson = (Map)questStageJsonObj; Map questStageJson = (Map)questStageJsonObj;
QuestStage questStage = new QuestStage(); QuestStage questStage = new QuestStage(this);
questStage.progress = JSONElement.getInteger((Number) questStageJson.get("progress")); questStage.parse(questStageJson);
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"));
this.stages.add(questStage); this.stages.add(questStage);
} }
} }
this.state = State.parsed;
} }
@Override @Override
@@ -142,6 +125,9 @@ public class Quest extends JSONElement {
return; return;
} }
for (QuestStage stage : stages) {
stage.link();
}
//Nothing to link to :D //Nothing to link to :D
this.state = State.linked; this.state = State.linked;
} }
@@ -164,9 +150,9 @@ public class Quest extends JSONElement {
clone.name = this.name; clone.name = this.name;
clone.visible_in_log = this.visible_in_log; clone.visible_in_log = this.visible_in_log;
if (this.stages != null) { if (this.stages != null) {
clone.stages = new ArrayList<Quest.QuestStage>(); clone.stages = new ArrayList<QuestStage>();
for (QuestStage stage : this.stages){ for (QuestStage stage : this.stages){
clone.stages.add((QuestStage) stage.clone()); clone.stages.add((QuestStage) stage.clone(clone));
} }
} }
return clone; return clone;
@@ -188,12 +174,7 @@ public class Quest extends JSONElement {
List stagesJson = new ArrayList(); List stagesJson = new ArrayList();
questJson.put("stages", stagesJson); questJson.put("stages", stagesJson);
for (QuestStage stage : this.stages) { for (QuestStage stage : this.stages) {
Map stageJson = new LinkedHashMap(); stagesJson.add(stage.toJson());
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);
} }
} }
return questJson; return questJson;
@@ -204,5 +185,14 @@ public class Quest extends JSONElement {
public String getProjectFilename() { public String getProjectFilename() {
return "questlist_"+getProject().name+".json"; return "questlist_"+getProject().name+".json";
} }
public QuestStage getStage(Integer stageId) {
for (QuestStage stage : stages) {
if (stage.progress.equals(stageId)) {
return stage;
}
}
return null;
}
} }

View File

@@ -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();
}
}

View File

@@ -112,6 +112,12 @@ public class Requirement extends JSONElement {
case questLatestProgress: case questLatestProgress:
case questProgress: case questProgress:
this.required_obj = proj.getQuest(required_obj_id); 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; break;
case consumedBonemeals: case consumedBonemeals:
case skillLevel: case skillLevel:
@@ -150,6 +156,12 @@ public class Requirement extends JSONElement {
this.required_obj = newOne; this.required_obj = newOne;
if (newOne != null) newOne.addBacklink((GameDataElement) this.parent); 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 @Override
public String getProjectFilename() { public String getProjectFilename() {

View File

@@ -39,6 +39,7 @@ import javax.swing.JSpinner.NumberEditor;
import javax.swing.JTextArea; import javax.swing.JTextArea;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.ListModel; import javax.swing.ListModel;
import javax.swing.Scrollable;
import javax.swing.SpinnerNumberModel; import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; 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.JSONElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC; import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; 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.TMXMap;
import com.gpl.rpg.atcontentstudio.utils.WeblateIntegration; import com.gpl.rpg.atcontentstudio.utils.WeblateIntegration;
import com.jidesoft.swing.ComboBoxSearchable; 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) { public static void addTranslationPane(JPanel pane, final JTextComponent tfComponent, final String initialValue) {if (Workspace.activeWorkspace.settings.translatorLanguage.getCurrentValue() != null) {
JPanel labelPane = new JPanel(); 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)); final JLabel translateLinkLabel = new JLabel(getWeblateLabelLink(initialValue));
labelPane.add(translateLinkLabel, JideBoxLayout.FIX); labelPane.add(translateLinkLabel, JideBoxLayout.FIX);
labelPane.add(new JLabel(" "), 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); tfPane.add(tfLabel, JideBoxLayout.FIX);
final JTextArea tfArea = new JTextArea(text); final JTextArea tfArea = new JTextArea(text);
tfArea.setEditable(editable); tfArea.setEditable(editable);
tfArea.setRows(2);
tfArea.setLineWrap(true);
tfArea.setWrapStyleWord(true);
tfPane.add(new JScrollPane(tfArea), JideBoxLayout.VARY); tfPane.add(new JScrollPane(tfArea), JideBoxLayout.VARY);
JButton nullify = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon())); JButton nullify = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
tfPane.add(nullify, JideBoxLayout.FIX); tfPane.add(nullify, JideBoxLayout.FIX);
@@ -644,8 +649,63 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
return gdeBox; return gdeBox;
} }
public JComboBox<QuestStage> 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<QuestStage> combo = new JComboBox<QuestStage>(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" }) @SuppressWarnings({ "rawtypes", "unchecked" })
public JList addBacklinksList(JPanel pane, GameDataElement gde) { 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)); final JList list = new JList(new GDEBacklinksListModel(gde));
list.addMouseListener(new MouseAdapter() { list.addMouseListener(new MouseAdapter() {
@Override @Override
@@ -666,7 +726,7 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
} }
}); });
list.setCellRenderer(new GDERenderer(true, false)); 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.setLayout(new JideBoxLayout(colPane, JideBoxLayout.PAGE_AXIS));
colPane.add(new JScrollPane(list), JideBoxLayout.FIX); colPane.add(new JScrollPane(list), JideBoxLayout.FIX);
colPane.add(new JPanel(), 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." : "")); label.setText("None"+(writable ? ". Click on the button to create one." : ""));
} else { } else {
if (includeType && ((GameDataElement)value).getDataType() != null) { 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 { } 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) { if (((GameDataElement)value).getIcon() == null) {
Notification.addError("Unable to find icon for "+((GameDataElement)value).getDesc()); 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<QuestStage> implements ComboBoxModel<QuestStage> {
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> { public static class GDEBacklinksListModel implements ListModel<GameDataElement> {
GameDataElement source; GameDataElement source;
@@ -892,7 +1027,5 @@ public abstract class Editor extends JPanel implements ProjectElementListener {
return null; return null;
} }
} }

View File

@@ -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.Item;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC; import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; 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.gamedata.Requirement;
import com.gpl.rpg.atcontentstudio.model.maps.TMXMap; import com.gpl.rpg.atcontentstudio.model.maps.TMXMap;
import com.gpl.rpg.atcontentstudio.ui.BooleanBasedCheckBox; import com.gpl.rpg.atcontentstudio.ui.BooleanBasedCheckBox;
@@ -94,7 +95,7 @@ public class DialogueEditor extends JSONElementEditor {
private JTextField rewardObjId; private JTextField rewardObjId;
private JComboBox rewardObjIdCombo; private JComboBox rewardObjIdCombo;
private MyComboBox rewardObj; private MyComboBox rewardObj;
private JSpinner rewardValue; private JComponent rewardValue;
private RepliesListModel repliesListModel; private RepliesListModel repliesListModel;
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@@ -114,7 +115,7 @@ public class DialogueEditor extends JSONElementEditor {
private JPanel requirementParamsPane; private JPanel requirementParamsPane;
private MyComboBox requirementObj; private MyComboBox requirementObj;
private JTextField requirementObjId; private JTextField requirementObjId;
private JSpinner requirementValue; private JComponent requirementValue;
private BooleanBasedCheckBox requirementNegated; private BooleanBasedCheckBox requirementNegated;
private DialogueGraphView dialogueGraphView; private DialogueGraphView dialogueGraphView;
@@ -421,7 +422,7 @@ public class DialogueEditor extends JSONElementEditor {
rewardObjId = null; rewardObjId = null;
rewardObjIdCombo = null; rewardObjIdCombo = null;
rewardObj = addQuestBox(pane, ((Dialogue)target).getProject(), "Quest: ", (Quest) reward.reward_obj, writable, listener); 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; break;
case skillIncrease: case skillIncrease:
rewardMap = null; rewardMap = null;
@@ -613,10 +614,10 @@ public class DialogueEditor extends JSONElementEditor {
replyText = null; replyText = null;
replyNextPhrase = addDialogueBox(pane, ((Dialogue)target).getProject(), "Next phrase: ", reply.next_phrase, writable, listener); 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)) { } 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; replyNextPhrase = null;
} else { } 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); replyNextPhrase = addDialogueBox(pane, ((Dialogue)target).getProject(), "Next phrase: ", reply.next_phrase, writable, listener);
} }
@@ -679,7 +680,7 @@ public class DialogueEditor extends JSONElementEditor {
case questProgress: case questProgress:
requirementObj = addQuestBox(pane, project, "Quest: ", (Quest) requirement.required_obj, writable, listener); requirementObj = addQuestBox(pane, project, "Quest: ", (Quest) requirement.required_obj, writable, listener);
requirementObjId = null; 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; break;
case skillLevel: case skillLevel:
requirementObj = null; requirementObj = null;
@@ -1149,7 +1150,21 @@ public class DialogueEditor extends JSONElementEditor {
} }
rewardsListModel.itemChanged(selectedReward); rewardsListModel.itemChanged(selectedReward);
} else if (source == rewardValue) { } 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; selectedReward.reward_value = (Integer) value;
if (quest != null) {
stage = quest.getStage(selectedReward.reward_value);
if (stage != null) stage.addBacklink(dialogue);
}
rewardsListModel.itemChanged(selectedReward); rewardsListModel.itemChanged(selectedReward);
} else if (source == replyTypeCombo) { } else if (source == replyTypeCombo) {
updateRepliesParamsEditorPane(repliesParamsPane, selectedReply, this); updateRepliesParamsEditorPane(repliesParamsPane, selectedReply, this);
@@ -1190,7 +1205,21 @@ public class DialogueEditor extends JSONElementEditor {
selectedRequirement.required_obj = null; selectedRequirement.required_obj = null;
requirementsListModel.itemChanged(selectedRequirement); requirementsListModel.itemChanged(selectedRequirement);
} else if (source == requirementValue) { } 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; selectedRequirement.required_value = (Integer) value;
if (quest != null) {
stage = quest.getStage(selectedRequirement.required_value);
if (stage != null) stage.addBacklink(dialogue);
}
requirementsListModel.itemChanged(selectedRequirement); requirementsListModel.itemChanged(selectedRequirement);
} else if (source == requirementNegated) { } else if (source == requirementNegated) {
selectedRequirement.negated = (Boolean) value; selectedRequirement.negated = (Boolean) value;

View File

@@ -16,6 +16,7 @@ import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; 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.SaveEvent;
import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataCategory; import com.gpl.rpg.atcontentstudio.model.gamedata.GameDataCategory;
import com.gpl.rpg.atcontentstudio.model.gamedata.JSONElement; 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.TMXMap;
import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment; import com.gpl.rpg.atcontentstudio.model.maps.WorldmapSegment;
import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet; 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.FieldUpdateListener;
import com.gpl.rpg.atcontentstudio.ui.IdChangeImpactWizard; import com.gpl.rpg.atcontentstudio.ui.IdChangeImpactWizard;
import com.gpl.rpg.atcontentstudio.ui.SaveItemsWizard; 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.gpl.rpg.atcontentstudio.ui.sprites.SpriteChooser;
import com.jidesoft.swing.JideBoxLayout; import com.jidesoft.swing.JideBoxLayout;
import com.jidesoft.swing.JideScrollPane;
import com.jidesoft.swing.JideTabbedPane; import com.jidesoft.swing.JideTabbedPane;
public abstract class JSONElementEditor extends Editor { public abstract class JSONElementEditor extends Editor {
@@ -65,7 +71,11 @@ public abstract class JSONElementEditor extends Editor {
} }
public void addEditorTab(String id, JPanel 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); scroller.getVerticalScrollBar().setUnitIncrement(16);
editorTabsHolder.addTab(id, scroller); editorTabsHolder.addTab(id, scroller);
editorTabs.put(id, editor); editorTabs.put(id, editor);
@@ -178,8 +188,17 @@ public abstract class JSONElementEditor extends Editor {
if (node.getParent() instanceof GameDataCategory<?>) { if (node.getParent() instanceof GameDataCategory<?>) {
((GameDataCategory<?>)node.getParent()).remove(node); ((GameDataCategory<?>)node.getParent()).remove(node);
node.save(); 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()) { for (GameDataElement backlink : node.getBacklinks()) {
backlink.elementChanged(node, proj.getGameDataElement(node.getClass(), node.id)); backlink.elementChanged(node, newOne);
} }
} }
} }

View File

@@ -1,6 +1,5 @@
package com.gpl.rpg.atcontentstudio.ui.gamedataeditors; package com.gpl.rpg.atcontentstudio.ui.gamedataeditors;
import java.awt.BorderLayout;
import java.awt.Component; import java.awt.Component;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
@@ -8,27 +7,30 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTable; import javax.swing.JSpinner;
import javax.swing.JTextArea; import javax.swing.JTextArea;
import javax.swing.JTextField; 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.ListSelectionEvent;
import javax.swing.event.ListSelectionListener; 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.ATContentStudio;
import com.gpl.rpg.atcontentstudio.model.GameDataElement; import com.gpl.rpg.atcontentstudio.model.GameDataElement;
import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode; import com.gpl.rpg.atcontentstudio.model.ProjectTreeNode;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; 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.DefaultIcons;
import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener; import com.gpl.rpg.atcontentstudio.ui.FieldUpdateListener;
import com.gpl.rpg.atcontentstudio.ui.IntegerBasedCheckBox; 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 form_view_id = "Form";
private static final String json_view_id = "JSON"; private static final String json_view_id = "JSON";
private QuestStage selectedStage = null;
private JTextField idField; private JTextField idField;
private JTextField nameField; private JTextField nameField;
private IntegerBasedCheckBox visibleBox; private IntegerBasedCheckBox visibleBox;
private QuestStageTableModel stagesModel; private StagesListModel stagesListModel;
private JTable stagesTable; private JList<QuestStage> stagesList;
private JButton createStage;
private JButton deleteStage; // private JPanel stagesParamPane;
private JButton moveUp; private JSpinner progressField;
private JButton moveDown; private JTextArea logTextField;
private JSpinner xpRewardField;
private IntegerBasedCheckBox finishQuestBox;
public QuestEditor(Quest quest) { public QuestEditor(Quest quest) {
@@ -72,242 +79,214 @@ public class QuestEditor extends JSONElementEditor {
nameField = addTranslatableTextField(pane, "Quest Name: ", quest.name, quest.writable, listener); nameField = addTranslatableTextField(pane, "Quest Name: ", quest.name, quest.writable, listener);
visibleBox = addIntegerBasedCheckBox(pane, "Visible in quest log", quest.visible_in_log, quest.writable, listener); visibleBox = addIntegerBasedCheckBox(pane, "Visible in quest log", quest.visible_in_log, quest.writable, listener);
JPanel stagesPane = new JPanel(); CollapsiblePanel stagesPane = new CollapsiblePanel("Quest stages: ");
stagesPane.setLayout(new JideBoxLayout(stagesPane, JideBoxLayout.PAGE_AXIS, 6)); stagesPane.setLayout(new JideBoxLayout(stagesPane, JideBoxLayout.PAGE_AXIS));
stagesModel = new QuestStageTableModel(quest, listener); stagesListModel = new StagesListModel(quest);
stagesTable = new JTable(stagesModel); stagesList = new JList<QuestStage>(stagesListModel);
stagesTable.getColumnModel().getColumn(0).setMinWidth(100); stagesList.setCellRenderer(new StagesCellRenderer());
stagesTable.getColumnModel().getColumn(0).setMaxWidth(100); stagesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// stagesTable.getColumnModel().getColumn(1).setPreferredWidth(40); stagesPane.add(new JScrollPane(stagesList), JideBoxLayout.FIX);
// stagesTable.getColumnModel().getColumn(1).setPreferredWidth(40); final JPanel stagesEditorPane = new JPanel();
stagesTable.getColumnModel().getColumn(2).setMinWidth(100); final JButton createStage = new JButton(new ImageIcon(DefaultIcons.getCreateIcon()));
stagesTable.getColumnModel().getColumn(2).setMaxWidth(100); final JButton deleteStage = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon()));
stagesTable.getColumnModel().getColumn(3).setMinWidth(130); final JButton moveStageUp = new JButton(new ImageIcon(DefaultIcons.getArrowUpIcon()));
stagesTable.getColumnModel().getColumn(3).setMaxWidth(130); final JButton moveStageDown = new JButton(new ImageIcon(DefaultIcons.getArrowDownIcon()));
stagesTable.setCellSelectionEnabled(true); deleteStage.setEnabled(false);
stagesTable.getColumnModel().getColumn(1).setCellRenderer(new MultilineCellRenderer()); moveStageUp.setEnabled(false);
stagesPane.add(new JScrollPane(stagesTable), BorderLayout.CENTER); moveStageDown.setEnabled(false);
if (quest.writable) { stagesList.addListSelectionListener(new ListSelectionListener() {
JPanel buttonPane = new JPanel(); @Override
buttonPane.setLayout(new JideBoxLayout(buttonPane, JideBoxLayout.LINE_AXIS, 6)); public void valueChanged(ListSelectionEvent e) {
createStage = new JButton(new ImageIcon(DefaultIcons.getCreateIcon())); selectedStage = (QuestStage) stagesList.getSelectedValue();
deleteStage = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon())); if (selectedStage != null) {
moveUp = new JButton(new ImageIcon(DefaultIcons.getArrowUpIcon())); deleteStage.setEnabled(true);
moveDown = new JButton(new ImageIcon(DefaultIcons.getArrowDownIcon())); moveStageUp.setEnabled(stagesList.getSelectedIndex() > 0);
buttonPane.add(createStage, JideBoxLayout.FIX); moveStageDown.setEnabled(stagesList.getSelectedIndex() < (stagesListModel.getSize() - 1));
buttonPane.add(deleteStage, JideBoxLayout.FIX); } else {
buttonPane.add(moveUp, JideBoxLayout.FIX); deleteStage.setEnabled(false);
buttonPane.add(moveDown, JideBoxLayout.FIX); moveStageUp.setEnabled(false);
buttonPane.add(new JPanel(), JideBoxLayout.VARY); moveStageDown.setEnabled(false);
deleteStage.setEnabled(false);
moveUp.setEnabled(false);
moveDown.setEnabled(false);
stagesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
updateTableButtons();
} }
}); updateStageEditorPane(stagesEditorPane, selectedStage, listener);
}
});
if (quest.writable) {
JPanel listButtonsPane = new JPanel();
listButtonsPane.setLayout(new JideBoxLayout(listButtonsPane, JideBoxLayout.LINE_AXIS, 6));
createStage.addActionListener(new ActionListener() { createStage.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
stagesModel.createStage(); QuestStage stage = new QuestStage(quest);
listener.valueChanged(stagesTable, null); stagesListModel.addItem(stage);
stagesTable.revalidate(); stagesList.setSelectedValue(stage, true);
stagesTable.repaint(); 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() { deleteStage.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
stagesModel.deleteRow(stagesTable.getSelectedRow()); if (selectedStage != null) {
listener.valueChanged(stagesTable, null); stagesListModel.removeItem(selectedStage);
stagesTable.revalidate(); selectedStage = null;
stagesTable.repaint(); stagesList.clearSelection();
updateTableButtons(); 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 @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
stagesModel.moveRow(stagesTable.getSelectedRow(), true); if (selectedStage != null) {
listener.valueChanged(stagesTable, null); stagesListModel.moveUp(selectedStage);
stagesTable.setRowSelectionInterval(stagesTable.getSelectedRow() - 1, stagesTable.getSelectedRow() - 1); stagesList.setSelectedValue(selectedStage, true);
updateTableButtons(); 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 @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
stagesModel.moveRow(stagesTable.getSelectedRow(), false); if (selectedStage != null) {
listener.valueChanged(stagesTable, null); stagesListModel.moveDown(selectedStage);
stagesTable.setRowSelectionInterval(stagesTable.getSelectedRow() + 1, stagesTable.getSelectedRow() + 1); stagesList.setSelectedValue(selectedStage, true);
updateTableButtons(); 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); 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<QuestStage> {
Quest quest; Quest source;
FieldUpdateListener listener;
public StagesListModel(Quest quest) {
public QuestStageTableModel(Quest q, FieldUpdateListener listener) { this.source = quest;
this.quest = q;
this.listener = listener;
} }
@Override @Override
public int getRowCount() { public int getSize() {
if (quest.stages == null) return 0; if (source.stages == null) return 0;
return quest.stages.size(); return source.stages.size();
} }
@Override @Override
public int getColumnCount() { public QuestStage getElementAt(int index) {
return 4; if (source.stages == null) return null;
return source.stages.get(index);
} }
@Override public void addItem(QuestStage item) {
public String getColumnName(int columnIndex) { if (source.stages == null) {
switch (columnIndex) { source.stages = new ArrayList<QuestStage>();
case 0:
return "Progress ID";
case 1:
return "Log text";
case 2:
return "XP reward";
case 3:
return "Finishes quest";
default:
return "???";
} }
} source.stages.add(item);
int index = source.stages.indexOf(item);
@Override for (ListDataListener l : listeners) {
public Class<?> getColumnClass(int columnIndex) { l.intervalAdded(new ListDataEvent(this, ListDataEvent.INTERVAL_ADDED, index, index));
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.QuestStage>();
quest.stages.add(new Quest.QuestStage());
for (TableModelListener l: listeners) {
l.tableChanged(new TableModelEvent(this, quest.stages.size() - 1));
} }
} }
public void moveRow(int rowNumber, boolean moveUp) { public void removeItem(QuestStage item) {
Quest.QuestStage stage = quest.stages.get(rowNumber); int index = source.stages.indexOf(item);
quest.stages.remove(stage); source.stages.remove(item);
quest.stages.add(rowNumber + (moveUp ? -1 : 1), stage); if (source.stages.isEmpty()) {
for (TableModelListener l : listeners) { source.stages = null;
l.tableChanged(new TableModelEvent(this, rowNumber + (moveUp ? -1 : 0), rowNumber + (moveUp ? 0 : 1))); }
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) { public void moveUp(QuestStage item) {
quest.stages.remove(rowNumber); int index = source.stages.indexOf(item);
for (TableModelListener l: listeners) { QuestStage exchanged = source.stages.get(index - 1);
l.tableChanged(new TableModelEvent(this, rowNumber, quest.stages.size())); 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<TableModelListener> listeners = new CopyOnWriteArrayList<TableModelListener>(); 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<ListDataListener> listeners = new CopyOnWriteArrayList<ListDataListener>();
@Override @Override
public void addTableModelListener(TableModelListener l) { public void addListDataListener(ListDataListener l) {
listeners.add(l); listeners.add(l);
} }
@Override @Override
public void removeTableModelListener(TableModelListener l) { public void removeListDataListener(ListDataListener l) {
listeners.remove(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 { public class QuestFieldUpdater implements FieldUpdateListener {
@Override @Override
@@ -337,6 +316,18 @@ public class QuestEditor extends JSONElementEditor {
ATContentStudio.frame.editorChanged(QuestEditor.this); ATContentStudio.frame.editorChanged(QuestEditor.this);
} else if (source == visibleBox) { } else if (source == visibleBox) {
quest.visible_in_log = (Integer) value; 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;
}
}
} }

View File

@@ -15,6 +15,7 @@ import javax.swing.ImageIcon;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JToolTip; import javax.swing.JToolTip;
import javax.swing.SwingConstants;
import javax.swing.ToolTipManager; import javax.swing.ToolTipManager;
import prefuse.Display; import prefuse.Display;
@@ -68,6 +69,7 @@ public class DialogueGraphView extends Display {
public static final String ICON = "icon"; public static final String ICON = "icon";
public static final String TARGET = "target"; public static final String TARGET = "target";
public static final String REPLY = "reply"; public static final String REPLY = "reply";
public static final String HIDDEN_REPLY = "hidden_reply";
public static final String HAS_REQS = "has_reqs"; public static final String HAS_REQS = "has_reqs";
private static final Schema DECORATOR_SCHEMA = PrefuseLib.getVisualItemSchema(); 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(ICON, Image.class, DefaultIcons.getNullifyIcon());
graph.addColumn(TARGET, GameDataElement.class, null); graph.addColumn(TARGET, GameDataElement.class, null);
graph.addColumn(REPLY, Dialogue.Reply.class, null); graph.addColumn(REPLY, Dialogue.Reply.class, null);
graph.addColumn(HIDDEN_REPLY, Dialogue.Reply.class, null);
graph.addColumn(HAS_REQS, boolean.class, false); graph.addColumn(HAS_REQS, boolean.class, false);
addDialogue(dialogue, npcIcon); addDialogue(dialogue, npcIcon);
} }
@@ -224,6 +227,8 @@ public class DialogueGraphView extends Display {
} else if (r.next_phrase != null) { } else if (r.next_phrase != null) {
//Go directly to next phrase //Go directly to next phrase
rNode = addDialogue(r.next_phrase, npcIcon); 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)) { } else if (Dialogue.Reply.KEY_PHRASE_ID.contains(r.next_phrase_id)) {
//Go directly to key phrase //Go directly to key phrase
rNode = addKeyPhraseNode(d, r.next_phrase_id); rNode = addKeyPhraseNode(d, r.next_phrase_id);
@@ -499,27 +504,32 @@ public class DialogueGraphView extends Display {
label = new JLabel(new ImageIcon(DefaultIcons.getDialogueIcon())); label = new JLabel(new ImageIcon(DefaultIcons.getDialogueIcon()));
label.setText(d.id); label.setText(d.id);
content.add(label, JideBoxLayout.FIX); content.add(label, JideBoxLayout.FIX);
if (tooltippedItem.get(REPLY) == null) { Object replObj = tooltippedItem.get(REPLY);
if (d.rewards != null && !d.rewards.isEmpty()) { if (replObj == null) {
for (Dialogue.Reward r : d.rewards) { replObj = tooltippedItem.get(HIDDEN_REPLY);
label = new JLabel(); }
DialogueEditor.decorateRewardJLabel(label, r); 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); 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);
}
}
} }
} }

View File

@@ -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.JSONElement;
import com.gpl.rpg.atcontentstudio.model.gamedata.NPC; import com.gpl.rpg.atcontentstudio.model.gamedata.NPC;
import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; 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.gamedata.Requirement;
import com.gpl.rpg.atcontentstudio.model.maps.ContainerArea; import com.gpl.rpg.atcontentstudio.model.maps.ContainerArea;
import com.gpl.rpg.atcontentstudio.model.maps.KeyArea; import com.gpl.rpg.atcontentstudio.model.maps.KeyArea;
@@ -172,7 +173,7 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private JComboBox requirementObj; private JComboBox requirementObj;
private JTextField requirementObjId; private JTextField requirementObjId;
private JSpinner requirementValue; private JComponent requirementValue;
private BooleanBasedCheckBox requirementNegated; private BooleanBasedCheckBox requirementNegated;
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@@ -642,7 +643,7 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
case questProgress: case questProgress:
requirementObj = addQuestBox(pane, project, "Quest: ", (Quest) requirement.required_obj, writable, listener); requirementObj = addQuestBox(pane, project, "Quest: ", (Quest) requirement.required_obj, writable, listener);
requirementObjId = null; 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; break;
case skillLevel: case skillLevel:
requirementObj = null; requirementObj = null;
@@ -1949,11 +1950,37 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe
} else if (source == requirementValue) { } else if (source == requirementValue) {
if (selectedMapObject instanceof KeyArea) { if (selectedMapObject instanceof KeyArea) {
KeyArea area = (KeyArea) selectedMapObject; 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; 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(); if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
} else if (selectedMapObject instanceof ReplaceArea) { } else if (selectedMapObject instanceof ReplaceArea) {
ReplaceArea area = (ReplaceArea) selectedMapObject; 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; 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(); if (area.oldSchoolRequirement) area.updateNameFromRequirementChange();
} }
} else if (source == requirementNegated) { } else if (source == requirementNegated) {