This commit is contained in:
Martin Haye 2015-07-06 17:09:30 -07:00
commit e3b9387719
11 changed files with 405 additions and 196 deletions

View File

@ -1,42 +1,42 @@
package org.badvision.outlaweditor.data; package org.badvision.outlaweditor.data;
import java.util.List;
import org.badvision.outlaweditor.Application; import org.badvision.outlaweditor.Application;
import org.badvision.outlaweditor.data.xml.Global; import org.badvision.outlaweditor.data.xml.Global;
import org.badvision.outlaweditor.data.xml.Scripts; import org.badvision.outlaweditor.data.xml.NamedEntity;
import org.badvision.outlaweditor.data.xml.Variables;
public class DataUtilities { public class DataUtilities {
public static void sortScripts(Scripts s) {
if (s == null || s.getScript() == null) {
return;
}
s.getScript().sort((a, b) -> {
if (a.getName().equalsIgnoreCase("init")) {
return -1;
} else if (b.getName().equalsIgnoreCase("init")) {
return 1;
}
return a.getName().compareTo(b.getName());
});
}
public static void ensureGlobalExists() { public static void ensureGlobalExists() {
if (Application.gameData.getGlobal() == null) { if (Application.gameData.getGlobal() == null) {
Application.gameData.setGlobal(new Global()); Application.gameData.setGlobal(new Global());
} }
} }
public static void sortVariables(Variables vars) { public static void sortNamedEntities(List<? extends NamedEntity> entities) {
if (vars == null || vars.getVariable()== null) { if (entities == null) {
return; return;
} }
vars.getVariable().sort((a, b) -> { entities.sort((a,b)->{
if (a.getName().equalsIgnoreCase("init")) { String nameA = a == null ? "" : nullSafe(a.getName());
return -1; String nameB = b == null ? "" : nullSafe(b.getName());
} else if (b.getName().equalsIgnoreCase("init")) { if (nameA.equalsIgnoreCase("init")) return -1;
return 1; if (nameB.equalsIgnoreCase("init")) return 1;
} return nameA.compareTo(nameB);
return a.getName().compareTo(b.getName());
}); });
} }
public static String nullSafe(String str) {
if (str == null) return "";
return str;
}
public static String uppercaseFirst(String str) {
StringBuilder b = new StringBuilder(str);
int i = 0;
do {
b.replace(i, i + 1, b.substring(i, i + 1).toUpperCase());
i = b.indexOf(" ", i) + 1;
} while (i > 0 && i < b.length());
return b.toString();
}
} }

View File

@ -32,7 +32,7 @@ public abstract class GlobalEditorTabController {
@FXML @FXML
abstract protected void onDataTypeDeletePressed(ActionEvent event); abstract protected void onDataTypeDeletePressed(ActionEvent event);
@FXML @FXML
abstract protected void onDeleteClonePressed(ActionEvent event); abstract protected void onDataTypeClonePressed(ActionEvent event);
@FXML @FXML
abstract protected void onVariableAddPressed(ActionEvent event); abstract protected void onVariableAddPressed(ActionEvent event);
@FXML @FXML

View File

@ -1,28 +1,39 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.badvision.outlaweditor.ui; package org.badvision.outlaweditor.ui;
import com.sun.glass.ui.Application;
import java.beans.BeanInfo; import java.beans.BeanInfo;
import java.beans.IntrospectionException; import java.beans.IntrospectionException;
import java.beans.Introspector; import java.beans.Introspector;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.adapter.JavaBeanStringPropertyBuilder;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType; import javafx.scene.control.ButtonType;
import javafx.scene.control.Control; import javafx.scene.control.Control;
import javafx.scene.control.Dialog; import javafx.scene.control.Dialog;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane; import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.util.Callback;
import static org.badvision.outlaweditor.data.DataUtilities.uppercaseFirst;
/** /**
* *
@ -32,7 +43,7 @@ public class ModalEditor {
public static interface EditControl<V> { public static interface EditControl<V> {
public Control getControl(); public Node getControl();
public V getValue(); public V getValue();
@ -59,6 +70,86 @@ public class ModalEditor {
} }
} }
static class TableControl<T, S> implements EditControl<List<T>> {
Map<String, Callback<TableColumn<T, S>, TableCell<T, S>>> cols;
Class<T> rowType;
ObservableList<T> rows;
TableView<T> table;
VBox control;
public TableControl(Map<String, Callback<TableColumn<T, S>, TableCell<T, S>>> cols, Class<T> rowType) {
this.cols = cols;
this.rowType = rowType;
rows = FXCollections.observableArrayList();
table = new TableView(rows);
cols.forEach((String colName, Callback<TableColumn<T, S>, TableCell<T, S>> factory) -> {
TableColumn<T, S> col = new TableColumn<>(uppercaseFirst(colName));
col.setCellValueFactory((TableColumn.CellDataFeatures<T, S> param) -> {
try {
return (ObservableValue<S>) new JavaBeanStringPropertyBuilder().bean(param.getValue()).name(colName).build();
} catch (NoSuchMethodException ex) {
Logger.getLogger(ModalEditor.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
}
});
col.setCellFactory(factory);
col.setPrefWidth(150);
table.getColumns().add(col);
});
table.setPlaceholder(new Label("Click + to add one or more attributes"));
table.setEditable(true);
table.setPrefWidth(cols.size() * 150 + 5);
Button addButton = new Button("+");
addButton.setOnAction((event) -> {
try {
rows.add(rowType.newInstance());
Application.invokeLater(() -> {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(ModalEditor.class.getName()).log(Level.SEVERE, null, ex);
}
table.edit(rows.size() - 1, table.getColumns().get(0));
});
} catch (InstantiationException | IllegalAccessException ex) {
Logger.getLogger(ModalEditor.class.getName()).log(Level.SEVERE, null, ex);
}
});
Button removeButton = new Button("-");
removeButton.setOnAction((event) -> {
rows.removeAll(table.getSelectionModel().getSelectedItems());
});
addButton.setPrefWidth(25);
removeButton.setPrefWidth(25);
control = new VBox(
table,
new HBox(
10,
addButton,
removeButton
)
);
}
@Override
public Node getControl() {
return control;
}
@Override
public List<T> getValue() {
return rows;
}
@Override
public void setValue(List<T> value) {
rows.setAll(value);
}
}
public PropertyDescriptor getPropertyDescriptor(PropertyDescriptor[] descriptors, String propertyName) { public PropertyDescriptor getPropertyDescriptor(PropertyDescriptor[] descriptors, String propertyName) {
for (PropertyDescriptor descriptor : descriptors) { for (PropertyDescriptor descriptor : descriptors) {
if (descriptor.getName().equalsIgnoreCase(propertyName)) { if (descriptor.getName().equalsIgnoreCase(propertyName)) {
@ -81,7 +172,7 @@ public class ModalEditor {
GridPane grid = new GridPane(); GridPane grid = new GridPane();
grid.setHgap(10); grid.setHgap(10);
grid.setVgap(10); grid.setVgap(10);
grid.setPadding(new Insets(20, 150, 10, 10)); grid.setPadding(new Insets(20, 50, 10, 10));
final AtomicInteger row = new AtomicInteger(0); final AtomicInteger row = new AtomicInteger(0);
obj.forEach((String property, EditControl control) -> { obj.forEach((String property, EditControl control) -> {
@ -105,9 +196,18 @@ public class ModalEditor {
obj.forEach((String property, EditControl control) -> { obj.forEach((String property, EditControl control) -> {
PropertyDescriptor descriptor = getPropertyDescriptor(info.getPropertyDescriptors(), property); PropertyDescriptor descriptor = getPropertyDescriptor(info.getPropertyDescriptors(), property);
try { try {
if (descriptor.getWriteMethod() != null) {
descriptor.getWriteMethod().invoke(sourceObject, control.getValue()); descriptor.getWriteMethod().invoke(sourceObject, control.getValue());
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { } else {
Logger.getLogger(ModalEditor.class.getName()).log(Level.SEVERE, null, ex); Object val = descriptor.getReadMethod().invoke(sourceObject);
if (val instanceof List) {
List sourceList = (List) val;
sourceList.clear();
sourceList.addAll((Collection) control.getValue());
}
}
} catch (NullPointerException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(ModalEditor.class.getName()).log(Level.SEVERE, "Error updating property " + property, ex);
} }
}); });
return sourceObject; return sourceObject;
@ -117,14 +217,4 @@ public class ModalEditor {
return dialog.showAndWait(); return dialog.showAndWait();
} }
private String uppercaseFirst(String str) {
StringBuilder b = new StringBuilder(str);
int i = 0;
do {
b.replace(i, i + 1, b.substring(i, i + 1).toUpperCase());
i = b.indexOf(" ", i) + 1;
} while (i > 0 && i < b.length());
return b.toString();
}
} }

View File

@ -29,6 +29,10 @@ import javafx.scene.control.Button;
import javafx.scene.control.Menu; import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar; import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem; import javafx.scene.control.MenuItem;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.effect.BlurType; import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow; import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image; import javafx.scene.image.Image;
@ -50,6 +54,7 @@ import javafx.stage.Modality;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.util.Callback; import javafx.util.Callback;
import javafx.util.Duration; import javafx.util.Duration;
import javafx.util.converter.DefaultStringConverter;
import javax.xml.bind.JAXB; import javax.xml.bind.JAXB;
import org.badvision.outlaweditor.Application; import org.badvision.outlaweditor.Application;
import static org.badvision.outlaweditor.Application.currentPlatform; import static org.badvision.outlaweditor.Application.currentPlatform;
@ -64,6 +69,7 @@ import org.badvision.outlaweditor.data.xml.Global;
import org.badvision.outlaweditor.data.xml.Scope; import org.badvision.outlaweditor.data.xml.Scope;
import org.badvision.outlaweditor.data.xml.Script; import org.badvision.outlaweditor.data.xml.Script;
import org.badvision.outlaweditor.data.xml.Tile; import org.badvision.outlaweditor.data.xml.Tile;
import org.badvision.outlaweditor.data.xml.UserType;
import org.badvision.outlaweditor.data.xml.Variable; import org.badvision.outlaweditor.data.xml.Variable;
import org.badvision.outlaweditor.data.xml.Variables; import org.badvision.outlaweditor.data.xml.Variables;
import org.badvision.outlaweditor.ui.impl.ImageConversionWizardController; import org.badvision.outlaweditor.ui.impl.ImageConversionWizardController;
@ -281,6 +287,52 @@ public class UIAction {
return editor.editObject(v, controls, Variable.class, "Variable", "Edit and press OK, or Cancel to abort"); return editor.editObject(v, controls, Variable.class, "Variable", "Edit and press OK, or Cancel to abort");
} }
public static void createAndEditUserType() throws IntrospectionException {
UserType type = new UserType();
if (editAndGetUserType(type).isPresent()) {
if (Application.gameData.getGlobal().getUserTypes() == null) {
Application.gameData.getGlobal().setUserTypes(new Global.UserTypes());
}
Application.gameData.getGlobal().getUserTypes().getUserType().add(type);
}
}
public static void editUserType(UserType type) {
try {
editAndGetUserType(type);
} catch (IntrospectionException ex) {
Logger.getLogger(UIAction.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static Optional<UserType> editAndGetUserType(UserType type) throws IntrospectionException {
ModalEditor editor = new ModalEditor();
Map<String, ModalEditor.EditControl> controls = new LinkedHashMap<>();
Map<String, Callback<TableColumn<
Variable, String>, TableCell<Variable, String>>> attributeControls = new LinkedHashMap<>();
attributeControls.put("name", TextFieldTableCell.<Variable, String>forTableColumn(new DefaultStringConverter() {
@Override
public String toString(String value) {
return value == null ? "Change Me" : value;
}
}));
attributeControls.put("type", ComboBoxTableCell.<Variable, String>forTableColumn(new DefaultStringConverter() {
@Override
public String toString(String value) {
return value == null ? "String" : value;
}
}, "String","Boolean","Number"));
attributeControls.put("comment", TextFieldTableCell.<Variable, String>forTableColumn(new DefaultStringConverter()));
controls.put("name", new ModalEditor.TextControl());
controls.put("attribute", new ModalEditor.TableControl(attributeControls, Variable.class));
controls.put("comment", new ModalEditor.TextControl());
return editor.editObject(type, controls, UserType.class, "User Type", "Edit and press OK, or Cancel to abort");
}
public static ImageConversionWizardController openImageConversionModal(Image image, ImageDitherEngine ditherEngine, int targetWidth, int targetHeight, ImageConversionPostAction postAction) { public static ImageConversionWizardController openImageConversionModal(Image image, ImageDitherEngine ditherEngine, int targetWidth, int targetHeight, ImageConversionPostAction postAction) {
FXMLLoader fxmlLoader = new FXMLLoader(UIAction.class.getResource("/imageConversionWizard.fxml")); FXMLLoader fxmlLoader = new FXMLLoader(UIAction.class.getResource("/imageConversionWizard.fxml"));
try { try {

View File

@ -55,6 +55,8 @@ public class ApplicationUIControllerImpl extends ApplicationUIController {
rebuildImageSelectors(); rebuildImageSelectors();
rebuildMapSelectors(); rebuildMapSelectors();
rebuildTileSelectors(); rebuildTileSelectors();
globalController.redrawGlobalDataTypes();
globalController.redrawGlobalVariables();
redrawScripts(); redrawScripts();
} }
@ -66,12 +68,9 @@ public class ApplicationUIControllerImpl extends ApplicationUIController {
@Override @Override
public void redrawScripts() { public void redrawScripts() {
if (currentTab == TABS.map) {
mapController.redrawMapScripts(); mapController.redrawMapScripts();
} else {
globalController.redrawGlobalScripts(); globalController.redrawGlobalScripts();
} }
}
@Override @Override
public void rebuildMapSelectors() { public void rebuildMapSelectors() {

View File

@ -16,6 +16,7 @@ import org.badvision.outlaweditor.Application;
import org.badvision.outlaweditor.TransferHelper; import org.badvision.outlaweditor.TransferHelper;
import org.badvision.outlaweditor.data.DataUtilities; import org.badvision.outlaweditor.data.DataUtilities;
import org.badvision.outlaweditor.data.xml.Script; import org.badvision.outlaweditor.data.xml.Script;
import org.badvision.outlaweditor.data.xml.UserType;
import org.badvision.outlaweditor.data.xml.Variable; import org.badvision.outlaweditor.data.xml.Variable;
import org.badvision.outlaweditor.ui.GlobalEditorTabController; import org.badvision.outlaweditor.ui.GlobalEditorTabController;
import org.badvision.outlaweditor.ui.UIAction; import org.badvision.outlaweditor.ui.UIAction;
@ -26,8 +27,74 @@ public class GlobalEditorTabControllerImpl extends GlobalEditorTabController {
@Override @Override
public void initialize() { public void initialize() {
super.initialize(); super.initialize();
variableList.setOnEditStart((ListView.EditEvent<Variable> event) -> {
UIAction.editVariable(event.getSource().getItems().get(event.getIndex()), Application.gameData.getGlobal());
variableList.getSelectionModel().clearSelection();
});
variableList.setCellFactory(new Callback<ListView<Variable>, ListCell<Variable>>() {
@Override
public ListCell<Variable> call(ListView<Variable> param) {
final ListCell<Variable> cell = new ListCell<Variable>() {
@Override
protected void updateItem(Variable item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
} else {
setText(item.getName());
if (item.getComment() != null && !(item.getComment().isEmpty())) {
setTooltip(new Tooltip(item.getComment()));
} }
setFont(Font.font(null, FontWeight.BOLD, 12.0));
}
}
};
return cell;
}
});
globalScriptList.setOnEditStart((ListView.EditEvent<Script> event) -> {
UIAction.editScript(event.getSource().getItems().get(event.getIndex()), Application.gameData.getGlobal());
globalScriptList.getSelectionModel().clearSelection();
});
globalScriptList.setCellFactory(new Callback<ListView<Script>, ListCell<Script>>() {
@Override
public ListCell<Script> call(ListView<Script> param) {
final ListCell<Script> cell = new ListCell<Script>() {
@Override
protected void updateItem(Script item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
} else {
setText(item.getName());
setFont(Font.font(null, FontWeight.BOLD, 12.0));
}
}
};
return cell;
}
});
dataTypeList.setOnEditStart((ListView.EditEvent<UserType> event) -> {
UIAction.editUserType(event.getSource().getItems().get(event.getIndex()));
dataTypeList.getSelectionModel().clearSelection();
});
dataTypeList.setCellFactory((listView) -> new ListCell<UserType>() {
@Override
protected void updateItem(UserType item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
} else {
setText(item.getName());
if (item.getComment() != null && !(item.getComment().isEmpty())) {
setTooltip(new Tooltip(item.getComment()));
}
setFont(Font.font(null, FontWeight.BOLD, 12.0));
}
}
});
}
@Override @Override
protected void onScriptAddPressed(ActionEvent event) { protected void onScriptAddPressed(ActionEvent event) {
@ -70,14 +137,31 @@ public class GlobalEditorTabControllerImpl extends GlobalEditorTabController {
@Override @Override
protected void onDataTypeAddPressed(ActionEvent event) { protected void onDataTypeAddPressed(ActionEvent event) {
try {
UIAction.createAndEditUserType();
redrawGlobalDataTypes();
} catch (IntrospectionException ex) {
Logger.getLogger(GlobalEditorTabControllerImpl.class.getName()).log(Level.SEVERE, null, ex);
}
} }
@Override @Override
protected void onDataTypeDeletePressed(ActionEvent event) { protected void onDataTypeDeletePressed(ActionEvent event) {
UserType type = dataTypeList.getSelectionModel().getSelectedItem();
if (type != null) {
UIAction.confirm(
"Are you sure you want to delete the user-defined type "
+ type.getName()
+ "? There is no undo for this!",
() -> {
Application.gameData.getGlobal().getUserTypes().getUserType().remove(type);
redrawGlobalDataTypes();
}, null);
}
} }
@Override @Override
protected void onDeleteClonePressed(ActionEvent event) { protected void onDataTypeClonePressed(ActionEvent event) {
} }
@Override @Override
@ -132,30 +216,8 @@ public class GlobalEditorTabControllerImpl extends GlobalEditorTabController {
@Override @Override
public void redrawGlobalScripts() { public void redrawGlobalScripts() {
DataUtilities.ensureGlobalExists(); DataUtilities.ensureGlobalExists();
globalScriptList.setOnEditStart((ListView.EditEvent<Script> event) -> {
UIAction.editScript(event.getSource().getItems().get(event.getIndex()), Application.gameData.getGlobal());
});
globalScriptList.setCellFactory(new Callback<ListView<Script>, ListCell<Script>>() {
@Override
public ListCell<Script> call(ListView<Script> param) {
final ListCell<Script> cell = new ListCell<Script>() {
@Override
protected void updateItem(Script item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
} else {
setText(item.getName());
setFont(Font.font(null, FontWeight.BOLD, 12.0));
}
}
};
return cell;
}
});
if (globalScriptList.getItems() != null && Application.gameData.getGlobal().getScripts() != null) { if (globalScriptList.getItems() != null && Application.gameData.getGlobal().getScripts() != null) {
DataUtilities.sortScripts(Application.gameData.getGlobal().getScripts()); DataUtilities.sortNamedEntities(Application.gameData.getGlobal().getScripts().getScript());
globalScriptList.getItems().setAll(Application.gameData.getGlobal().getScripts().getScript()); globalScriptList.getItems().setAll(Application.gameData.getGlobal().getScripts().getScript());
} else { } else {
globalScriptList.getItems().clear(); globalScriptList.getItems().clear();
@ -165,32 +227,8 @@ public class GlobalEditorTabControllerImpl extends GlobalEditorTabController {
@Override @Override
public void redrawGlobalVariables() { public void redrawGlobalVariables() {
DataUtilities.ensureGlobalExists(); DataUtilities.ensureGlobalExists();
variableList.setOnEditStart((ListView.EditEvent<Variable> event) -> {
UIAction.editVariable(event.getSource().getItems().get(event.getIndex()), Application.gameData.getGlobal());
});
variableList.setCellFactory(new Callback<ListView<Variable>, ListCell<Variable>>() {
@Override
public ListCell<Variable> call(ListView<Variable> param) {
final ListCell<Variable> cell = new ListCell<Variable>() {
@Override
protected void updateItem(Variable item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
} else {
setText(item.getName());
if (item.getComment() != null && !(item.getComment().isEmpty())) {
setTooltip(new Tooltip(item.getComment()));
}
setFont(Font.font(null, FontWeight.BOLD, 12.0));
}
}
};
return cell;
}
});
if (variableList.getItems() != null && Application.gameData.getGlobal().getVariables() != null) { if (variableList.getItems() != null && Application.gameData.getGlobal().getVariables() != null) {
DataUtilities.sortVariables(Application.gameData.getGlobal().getVariables()); DataUtilities.sortNamedEntities(Application.gameData.getGlobal().getVariables().getVariable());
variableList.getItems().setAll(Application.gameData.getGlobal().getVariables().getVariable()); variableList.getItems().setAll(Application.gameData.getGlobal().getVariables().getVariable());
} else { } else {
variableList.getItems().clear(); variableList.getItems().clear();
@ -200,6 +238,11 @@ public class GlobalEditorTabControllerImpl extends GlobalEditorTabController {
@Override @Override
public void redrawGlobalDataTypes() { public void redrawGlobalDataTypes() {
DataUtilities.ensureGlobalExists(); DataUtilities.ensureGlobalExists();
if (dataTypeList.getItems() != null && Application.gameData.getGlobal().getUserTypes() != null) {
DataUtilities.sortNamedEntities(Application.gameData.getGlobal().getUserTypes().getUserType());
dataTypeList.getItems().setAll(Application.gameData.getGlobal().getUserTypes().getUserType());
} else {
dataTypeList.getItems().clear();
}
} }
} }

View File

@ -279,7 +279,7 @@ public class MapEditorTabControllerImpl extends MapEditorTabController {
mapWrapAround.setDisable(true); mapWrapAround.setDisable(true);
setCurrentEditor(null); setCurrentEditor(null);
} else { } else {
DataUtilities.sortScripts(m.getScripts()); DataUtilities.sortNamedEntities(m.getScripts().getScript());
if (m.getHeight() == null) { if (m.getHeight() == null) {
m.setHeight(512); m.setHeight(512);
} }
@ -426,7 +426,7 @@ public class MapEditorTabControllerImpl extends MapEditorTabController {
mapScriptsList.getItems().clear(); mapScriptsList.getItems().clear();
} else { } else {
if (mapScriptsList.getItems() != null && getCurrentMap().getScripts() != null) { if (mapScriptsList.getItems() != null && getCurrentMap().getScripts() != null) {
DataUtilities.sortScripts(getCurrentMap().getScripts()); DataUtilities.sortNamedEntities(getCurrentMap().getScripts().getScript());
mapScriptsList.getItems().setAll(getCurrentMap().getScripts().getScript()); mapScriptsList.getItems().setAll(getCurrentMap().getScripts().getScript());
} else { } else {
mapScriptsList.getItems().clear(); mapScriptsList.getItems().clear();

View File

@ -40,7 +40,7 @@
<items> <items>
<Button mnemonicParsing="false" onAction="#onDataTypeAddPressed" text="+" /> <Button mnemonicParsing="false" onAction="#onDataTypeAddPressed" text="+" />
<Button mnemonicParsing="false" onAction="#onDataTypeDeletePressed" text="-" /> <Button mnemonicParsing="false" onAction="#onDataTypeDeletePressed" text="-" />
<Button mnemonicParsing="false" onAction="#onDeleteClonePressed" text="Clone" /> <Button mnemonicParsing="false" onAction="#onDataTypeClonePressed" text="Clone" />
</items> </items>
</ToolBar> </ToolBar>
<ScrollPane fitToHeight="true" fitToWidth="true" prefHeight="419.0" prefWidth="201.0"> <ScrollPane fitToHeight="true" fitToWidth="true" prefHeight="419.0" prefWidth="201.0">

View File

@ -2,12 +2,19 @@
<xs:schema version="1.0" <xs:schema version="1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" targetNamespace="outlaw" xmlns:tns="outlaw" attributeFormDefault="unqualified"> elementFormDefault="qualified" targetNamespace="outlaw" xmlns:tns="outlaw" attributeFormDefault="unqualified">
<xs:complexType name="namedEntity">
<xs:attribute name="name" use="required" type="xs:NCName"/>
<xs:attribute name="comment" type="xs:string"/>
</xs:complexType>
<xs:complexType name="image"> <xs:complexType name="image">
<xs:complexContent>
<xs:extension base="tns:namedEntity">
<xs:sequence> <xs:sequence>
<xs:element name="displayData" type="tns:platformData" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="displayData" type="tns:platformData" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence> </xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN"/>
<xs:attribute name="category" type="xs:string"/> <xs:attribute name="category" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType> </xs:complexType>
<xs:complexType name="tile"> <xs:complexType name="tile">
<xs:complexContent> <xs:complexContent>
@ -29,8 +36,9 @@
</xs:simpleContent> </xs:simpleContent>
</xs:complexType> </xs:complexType>
<xs:complexType name="script"> <xs:complexType name="script">
<xs:complexContent>
<xs:extension base="tns:namedEntity">
<xs:sequence> <xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="description" type="xs:string" minOccurs="0"/> <xs:element name="description" type="xs:string" minOccurs="0"/>
<xs:element name="category" type="xs:string" minOccurs="0"/> <xs:element name="category" type="xs:string" minOccurs="0"/>
<xs:element name="block" type="tns:block"/> <xs:element name="block" type="tns:block"/>
@ -49,6 +57,8 @@
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
</xs:sequence> </xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType> </xs:complexType>
<xs:complexType name="scripts"> <xs:complexType name="scripts">
<xs:sequence> <xs:sequence>
@ -56,9 +66,11 @@
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
<xs:complexType name="variable"> <xs:complexType name="variable">
<xs:attribute name="name" use="required" type="xs:NCName"/> <xs:complexContent>
<xs:extension base="tns:namedEntity">
<xs:attribute name="type" use="required" type="xs:NMTOKEN"/> <xs:attribute name="type" use="required" type="xs:NMTOKEN"/>
<xs:attribute name="comment" type="xs:string"/> </xs:extension>
</xs:complexContent>
</xs:complexType> </xs:complexType>
<xs:complexType name="variables"> <xs:complexType name="variables">
<xs:sequence> <xs:sequence>
@ -105,17 +117,13 @@
</xs:complexContent> </xs:complexContent>
</xs:complexType> </xs:complexType>
<xs:complexType name="userType"> <xs:complexType name="userType">
<xs:complexContent>
<xs:extension base="tns:namedEntity">
<xs:sequence> <xs:sequence>
<xs:element name="attribute" minOccurs="1" maxOccurs="unbounded"> <xs:element name="attribute" minOccurs="1" maxOccurs="unbounded" type="tns:variable"/>
<xs:complexType>
<xs:attribute name="name" use="required" type="xs:NCName"/>
<xs:attribute name="type" use="required" type="xs:NMTOKEN"/>
<xs:attribute name="comment" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence> </xs:sequence>
<xs:attribute name="name" use="required" type="xs:NCName"/> </xs:extension>
<xs:attribute name="comment" use="required" type="xs:string"/> </xs:complexContent>
</xs:complexType> </xs:complexType>
<xs:complexType name="scope"> <xs:complexType name="scope">
<xs:sequence> <xs:sequence>

View File

@ -74,7 +74,7 @@
<block type="text_getboolean"></block> <block type="text_getboolean"></block>
<block type="text_getcharacter"></block> <block type="text_getcharacter"></block>
</category> </category>
<category var="customTypes" name="Custom Types"> <category id="customTypes" name="Custom Types">
</category> </category>
<category name="Graphics"> <category name="Graphics">
<block type="graphics_set_portrait"></block> <block type="graphics_set_portrait"></block>

View File

@ -63,52 +63,69 @@ if (typeof Mythos === "undefined") {
Mythos.buildCustomTypeBlocks(userType); Mythos.buildCustomTypeBlocks(userType);
}); });
}, },
buildCustomType: function (userType) { buildCustomTypeBlocks: function (userType) {
Blockly.Blocks['userType_' + userType.getName()] = { Blockly.Blocks['userType_' + userType.getName()] = {
init: function () { init: function () {
try {
var typeConstructor = this; var typeConstructor = this;
typeConstructor.setPreviousStatement(false);
typeConstructor.setNextStatement(false);
typeConstructor.setOutput(true, null);
typeConstructor.setColour(200); typeConstructor.setColour(200);
typeConstructor.setTooltip(userType.getComment());
typeConstructor.appendDummyInput() typeConstructor.appendDummyInput()
.appendField("Create " + userType.getName()); .appendField("Create " + userType.getName());
Mythos.each(userType.getAttribute(), function (attribute) { Mythos.each(userType.getAttribute(), function (attribute) {
typeConstructor.appendValueInput(attribute.getName()) typeConstructor.appendValueInput(attribute.getName())
.setAlign(Blockly.ALIGN_RIGHT) .setAlign(Blockly.ALIGN_RIGHT)
.setCheck(attribute.getType()) .setCheck(attribute.getType())
.appendField(attribute.getName()); .appendField(attribute.getName())
}); });
typeConstructor.setPreviousStatement(true); } catch (error) {
typeConstructor.setNextStatement(true); Mythos.editor.log(error);
typeConstructor.setOutput(true, userType.getName()); }
} }
}; };
Blockly.Blocks['set_' + userType.getName()] = { Blockly.Blocks['set_' + userType.getName()] = {
init: function () { init: function () {
try {
var typeSetter = this; var typeSetter = this;
typeSetter.setColour(200); typeSetter.setColour(200);
typeSetter.appendValueInput("Set ")
.setAlign(Blockly.ALIGN_LEFT)
.setCheck(null)
.appendField(Mythos.getVariableDropdown(userType), "VAR")
.appendField(".")
.appendField(Mythos.getAttributeDropdown(userType), "ATTR");
typeSetter.setPreviousStatement(true); typeSetter.setPreviousStatement(true);
typeSetter.setNextStatement(true); typeSetter.setNextStatement(true);
typeSetter.setOutput(false); typeSetter.setOutput(false);
typeSetter.setTooltip(userType.getComment());
typeSetter.appendValueInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField("Set")
.appendField(new Blockly.FieldVariable(userType.getName()), "VAR")
.appendField(".")
.appendField(Mythos.getAttributeDropdown(userType), "ATTR")
.appendField("to");
} catch (error) {
Mythos.editor.log(error);
}
} }
}; };
Blockly.Blocks['get_' + userType.getName()] = { Blockly.Blocks['get_' + userType.getName()] = {
init: function () { init: function () {
try {
var typeGetter = this; var typeGetter = this;
typeGetter.setColour(200); typeGetter.setColour(200);
typeGetter.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.setCheck(null)
.appendField(Mythos.getVariableDropdown(userType), "VAR")
.appendField(".")
.appendField(Mythos.getAttributeDropdown(userType), "ATTR");
typeGetter.setPreviousStatement(false); typeGetter.setPreviousStatement(false);
typeGetter.setNextStatement(false); typeGetter.setNextStatement(false);
typeGetter.setOutput(true, null); typeGetter.setOutput(true, null);
typeGetter.setTooltip(userType.getComment());
typeGetter.appendDummyInput()
.setAlign(Blockly.ALIGN_LEFT)
.appendField("Get")
.appendField(new Blockly.FieldVariable(userType.getName()), "VAR")
.appendField(".")
.appendField(Mythos.getAttributeDropdown(userType), "ATTR");
} catch (error) {
Mythos.editor.log(error);
}
} }
}; };
}, },
@ -118,14 +135,14 @@ if (typeof Mythos === "undefined") {
Mythos.each(variables, function (variable) { Mythos.each(variables, function (variable) {
options.push([variable.getName(), variable.getName()]); options.push([variable.getName(), variable.getName()]);
}); });
return Blockly.FieldDropdown(options); return new Blockly.FieldDropdown(options);
}, },
getAttributeDropdown: function (userType) { getAttributeDropdown: function (userType) {
var options = []; var options = [];
Mythos.each(userType.getAttribute(), function (attribute) { Mythos.each(userType.getAttribute(), function (attribute) {
options.push([attribute.getName(), attribute.getName()]); options.push([attribute.getName(), attribute.getName()]);
}); });
return Blockly.FieldDropdown(options); return new Blockly.FieldDropdown(options);
}, },
addFunctionsFromScope: function (target, prefix, functions) { addFunctionsFromScope: function (target, prefix, functions) {
Mythos.each(functions, function (func) { Mythos.each(functions, function (func) {